replacing pieces of string

2019-02-25 20:04发布

i'm doing something like excel, i have something like this:

1         2           3
A1        B1          C1

where it replaces the content for specified content, where A1 replaces the content for 1. B1 replaces the content of 2...and etc...

i'm using a multidimensional array, and i do the things like this:

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");
  }

But when i have A1+B1+C1 and another things, i cant replace the total content, because other references will be removed....

So, at the cell, A1+B1+C1, i wanna change B1 for the content specified....i wanna have like this:

This -> A1+B1+C1

to -> 1+2+3

....

Thanks.

3条回答
The star\"
2楼-- · 2019-02-25 20:41

I think that as may be replaced with values ​​by table lookup by cutting the name simply its corresponding value in the name of the string you want to replace.

E.g

#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;
}
查看更多
时光不老,我们不散
3楼-- · 2019-02-25 20:48

You might just reuse this c++ solution (replacing the generic iterators by hardcoding char* instead).

I gave it a whirl. However, I wish to give a warning: it looks like you're trying to implement an expression parser. I'd strongly advise you to either

  • handroll a (recursive descent) parser
  • use flex/bison (or lex/yacc)

so you don't paint yourself in an awkward corner of error-prone text-handling in C.

Edit: I rewrote your C program using C++; you can see it working live here.

Edit 2: Another fixup of your C program in pure C: http://ideone.com/ExnufJ updated to support iterative expansions now, too

The answer just concerns itself with the pure C approach:

So, let's get started. I assumed a sample "spreadsheet" (it could contain numbers instead of strings):

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 */
};

Using just two helpers:

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*/

we can write the following demo program:

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;
}

which prints the well-known test phrase as per the comment. Now, get_cell_value is really simple:

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 */
}

And expand_cell_references is slightly more involved, being a simple DFA parser:

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;
}

I took some shortcuts there, because this grammar is so minimalist, but it should give you a proper idea of where to start.

See a live demo here http://ideone.com/kS7XqB so you can play with it yourself. Note that I added debugging (asserts) to the get_cell_value function so you don't accidentally reference out-of-bounds indexes.

查看更多
Summer. ? 凉城
4楼-- · 2019-02-25 20:48

Any time you run into some string manipulation problem in C, your first instinct should be to look at string.h and see what's available there. As outlined in several answers here, there is no function to do string replacement directly, but it should be possible to use strstr and strncpy to find occurrences of substrings and then copy the replacement (into a new buffer so as not to clobber the rest of the original, obviously).

查看更多
登录 后发表回答