0

I have written a function that parses a line from a text file and replaces cerain keywords with the appropriate counterpart in a list.

the code looks like this:

std::string __iec_parse_cl(const std::string &line){
    std::string ret = line;

    static const size_t num_tokens = 6;
    static const char *tokens_search[6]{
        filled ...
    };

    static const char *tokens_replace[6]{
        filled ...
    };

    for(size_t x = 0; x < num_tokens; x++){
        size_t yolo;
        do{
            yolo = ret.find(tokens_search[x];
            if(yolo != std::string::npos){
                ret.erase(yolo, strlen(tokens_search[x]));
                ret.insert(yolo, tokens_replace[x]);
            }
        } while(yolo != std::string::npos);
    }

    return ret;
}

When I parse a token that looks like this: globalid and replace it with this: get_global_id everything is fine...

BUT when I try to parse a token that looks like THIS: global_id and try to replace it with this: get_global_id the program stalls somewhere in the function :/

What could be causing this?

RamblingMad
  • 5,332
  • 2
  • 24
  • 48
  • You should change the name of your function, otherwise the behavior of your code is undefined. http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – Benjamin Lindley Dec 08 '13 at 02:55
  • I understand the naming conventions, but I'm fairly certain the standard library or the gcc developers aren't going to use that function name :P haha – RamblingMad Dec 08 '13 at 03:08

1 Answers1

2

That's because your search needs to start after the replacement. If you were to print out your string after each replacement, you would see that it's got get_global_id then get_get_global_id then get_get_get_global_id, etc.

What you need to do is to tell find to start after your last replacement.

    size_t yolo = 0;
    do{
        yolo = ret.find(tokens_search[x], yolo);
        if (yolo != std::string::npos){
            ret.erase(yolo, strlen(tokens_search[x]));
            ret.insert(yolo, tokens_replace[x]);
            yolo += strlen(tokens_replace[x]);
        }
    } while(yolo != std::string::npos);

Doing this will prevent other issues as well, if there are other overlaps between your tokens and their replacements.

Joe Z
  • 17,413
  • 3
  • 28
  • 39
  • It's an easy error to make. I think my first attempt at a macro preprocessor umpteen years ago died a similar ignominious death. Only, because it was in C, with ugly pointers and mallocs and such, it had many more reasons for crashing, making it that much harder to find. – Joe Z Dec 08 '13 at 03:20