Search code examples
cscanfstdio

C - scanf to pull a number in quotes only after a specific sequence of characters


Say I have a string like this:

Hello World - this is a line of textCOLOR="4"

and this string is stored in buf[1000]

As you can see this string has a color tag in the format of COLOR="n". The number is what needs to be pulled (it can be between 1 and 56) and assigned to an int variable. I'd like for this tag to be able to be anywhere in the string.

I can run the following code to extract the color value:

int colorNumber = 1; //default value
if (scanf(buf, "%*[^\"]\"%2d[^\"]\"", &colorNumber)) {
    // work with number
}

and that works fine, but if the string were to contain a number or quote in it then the scanf would fail to produce the number.

I've tried a few variations of my second scanf argument, but those didn't work. I tried "%*[^\"]COLOR=\"%2d[^\"]\"" but that doesn't seem to work at all.

I've looked through the man pages for scanf, but I couldn't find what I was looking for in there either.

Perhaps scanf is not the right tool for this? I'm willing to try other libraries/functions if necessary.


Solution

  • try

    if (sscanf(buf, "%*[^C]COLOR=\"%d", &colorNUM) == 1)
    

    The reason your attempted "%*[^\"]COLOR"... format didn't work is that the %*[\"] matches everything up to the ", skipping past the COLOR, so will then fail to match COLOR. The above will fail if there's another C somwhere else in the string before COLOR, however. To avoid that you're probably better off using strstr, possibly in a loop if COLOR might appear multiple places.

    for (const char *p = buf; p = strstr(p, "COLOR"); ++p) {
        if (sscanf(p, "COLOR=\"%d", &colorNum) == 1) {
            // found a color number
    

    Note also, trying to match characters after the %d is pointless as regardelss of whether they match or not, the returned values will be the same, so there's no way to tell. If you want to ensure there's a " after the number, you need something like

    int end = 0;
    if (sscanf(p, "COLOR=\"%d\"%n", &colorNum, &end), end > 0)
    

    by checking that %n wrote something to end, you're also checking that everything before the %n matched correctly.