2

我正在做类似excel的事情,我有这样的事情:

1         2           3
A1        B1          C1

它替换指定内容的内容,其中A1替换1的内容。B1替换2的内容......等等......

我正在使用一个多维数组,我做这样的事情:

int offset = 0, readCharCount;
    while(sscanf(matris[i][c] + offset, "%c%d%*c%n", &col, &linha, &readCharCount) == 2){
        //printf("%c, %d\n", col, linha);
        //strcpy(matris[i][c], matris[linha-1][col - 'A']);

        offset += readCharCount;
      //printf(" {%c, %d}", col, linha);
      //printf("\n");
  }

但是当我有 A1+B1+C1 和其他东西时,我无法替换全部内容,因为其他引用将被删除....

因此,在单元格 A1+B1+C1 中,我想将 B1 更改为指定的内容....我想要这样:

This -> A1+B1+C1

to -> 1+2+3

……

谢谢。

4

3 回答 3

4

您可能只是重用这个c++ 解决方案(改为通过硬编码替换通用迭代器char*)。

我试了一下。但是,我想发出警告:看起来您正在尝试实现表达式解析器。我强烈建议你要么

  • 处理(递归下降)解析器
  • 使用 flex/bison(或 lex/yacc)

所以你不会把自己描绘在 C 中容易出错的文本处理的尴尬角落。

编辑:我用 C++重写了你的 C 程序;你可以看到它在这里工作

编辑 2:您的 C 程序在纯 C 中的另一个修复:http: //ideone.com/ExnufJ 现在也更新以支持迭代扩展

答案只与纯 C 方法有关:

那么,让我们开始吧。我假设一个示例“电子表格”(它可能包含数字而不是字符串):

const char* cells[][4] = {
    /* A       B           C        D                 */
    { "the"  , "lazy"    , "cow"  , "jumped"  }, /* 1 */
    { "over" , "the"     , "quick", "brown"   }, /* 2 */
    { "paper", "packages", "tied" , "up"      }, /* 3 */
    { "with" , "silver"  , "white", "winters" }, /* 4 */
    { "that" , "melt"    , "fox" ,  "springs" }, /* 5 */
};

仅使用两个助手:

const char* get_cell_value(const char* coordinate_b, const char* coordinate_e);
char* expand_cell_references(const char* f, const char* const l, char* o); /*the magic engine*/

我们可以编写如下演示程序:

int main()
{
    const char in[] = "The C2 D2 C5 D1 A2 B2 B1 dog!";

    char out[1024] = {0};
    expand_cell_references(in, in+strlen(in), out);
    puts(out); /* "The quick brown fox jumped over the lazy dog!" */

    return 0;
}

根据评论打印众所周知的测试短语。现在,get_cell_value真的很简单:

const char* get_cell_value(const char* coordinate_b, const char* coordinate_e)
{
    size_t col = 0, row = 0;
    const char* it;
    for (it=coordinate_b; it != coordinate_e; ++it)
    {
        if (*it >= 'A' && *it <= 'Z')
            col = 26*col + (*it - 'A');
        if (*it >= '0' && *it <= '9')
            row = 10*row + (*it - '0'); /* or use atoi and friends */
    }
    row--; /* 1-based row nums in Excel */

    return cells[row][col]; /* 1-based indexes in Excel */
}

并且expand_cell_references稍微复杂一些,作为一个简单的 DFA 解析器:

char* expand_cell_references(const char* f, const char* const l, char* o)
{
    enum parser_state {
        other,
        in_coord_col,
        in_coord_row
    } state = other;

    /*temporary storage for coordinates being parsed:*/
    char accum[16] = {0};
    char* accit = accum;
    while (f!=l)
    {
        switch(state) /*dummy, the transitions flow in fallthrough order for now*/
        {
            case other:
                *(accit = accum) = 0; /*reset the accumulator*/
                while (f!=l && !(*f>='A' && *f<='Z'))
                    *o++ = *f++;
                /*fallthrough*/
            case in_coord_col:
                while (f!=l && *f>='A' && *f<='Z')
                    *accit++ = *f++;
                /*fallthrough*/
            case in_coord_row:
                {
                    const char* expanded = accum;
                    if (f!=l && *f>='0' && *f<='9')
                    {
                        while (f!=l && *f>='0' && *f<='9')
                            *accit++ = *f++;
                        expanded = get_cell_value(accum, accit);
                    }
                    else
                    {
                        *accit = 0;
                    }
                    while (*expanded)
                        *o++ = *expanded++;
                    continue; /*state = other;*/
                }
        }
    }
    return o;
}

我在那里采取了一些捷径,因为这种语法非常简约,但它应该让你对从哪里开始有一个正确的想法。

请在此处查看现场演示http://ideone.com/kS7XqB,以便您自己玩。请注意,我在get_cell_value函数中添加了调试(断言),因此您不会意外引用越界索引。

于 2013-06-21T19:49:35.737 回答
1

我认为 as 可以通过表查找替换为值,只需将名称剪切为要替换的字符串名称中的对应值即可。

例如

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


typedef struct pair {
    char key[16];
    int  value;
} Pair;

int main(void){
    Pair var_table[] = { { "A1", 1 }, {"B1", 2}, { "C1", 3 }};//sorted
    size_t size = sizeof(var_table)/sizeof(*var_table);
    char input[256] = "A1+B1+C1";
    char outbuff[4096];
    char *p;
    int offset = 0;

    printf("This -> %s\n\n", input);
    for(p=input;*p;){
        Pair *var;
        char op, *opp;

        opp=strpbrk(p, "+-*/");
        if(opp){
            op = *opp;
            *opp = '\0';//cut string at op position
        }
        //search key(p)
        var = (Pair*)bsearch(p, var_table, size, sizeof(*var), (int (*)(const void *, const void *))strcmp);
        if(var)//find!
            offset += sprintf(outbuff + offset, "%d", var->value);//or store array? 
        else
            offset += sprintf(outbuff + offset, "%s", "#UNKNOWN_VAR_NAME#");
        if(opp){
            offset += sprintf(outbuff + offset, "%c", op);
            p = opp + 1;
        } else 
            break;
    }
    printf("to -> %s\n", outbuff);


    return 0;
}
于 2013-06-22T09:19:02.880 回答
0

每当您在 C 中遇到一些字符串操作问题时,您的第一反应应该是看看string.h那里有什么可用的。正如这里的几个答案中所述,没有直接进行字符串替换的功能,但应该可以使用strstrstrncpy查找子字符串的出现然后将替换复制(到新缓冲区中,以免破坏原始的其余部分, 明显地)。

于 2013-06-21T19:04:44.620 回答