replacing pieces of string

后端 未结 3 1995
星月不相逢
星月不相逢 2021-01-22 18:19

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

1         2           3
A1        B1          C1

where it replaces the content for

相关标签:
3条回答
  • 2021-01-22 18:30

    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.

    0 讨论(0)
  • 2021-01-22 18:35

    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;
    }
    
    0 讨论(0)
  • 2021-01-22 18:47

    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).

    0 讨论(0)
提交回复
热议问题