anon349
anon349

Reputation: 23

Scanf delimiter and empty string

I'm having a problem reading in values using sscanf() with delimiters.

sscanf(line, "%15[^:]:%20[^:]:%d:%d:%50[^:]:%25[^:]:%25[^\n]",
       string1, string2, &value1, &value2, string3, string4, string5);

There's only a problem when line is something like:

abc:defg:1:2::hijk:no

When I print out the strings/values, everything is normal up until 'string 3'. It outputs some weird character, then 'string4' outputs an empty space and string5 outputs a similar weird character.

Anybody have any idea how I can scan in the right values?

edit: I meant abc:defg:1:2::hijk:no, not abc:defg:1:2::hijk:lm:no

Upvotes: 1

Views: 1788

Answers (4)

M.M
M.M

Reputation: 141628

The problem is that the [ specifier causes matching failure if it does not match any characters. The scanf function stops reading when a matching failure occurs.

The garbage you see is because you are printing out uninitialized variables (the scanning never got so far as to fill in those variables).

If you want to allow zero or more characters for a character field, you can't use a string with %[ followed by some other stuff.

Alternatives include:

  • Make several separate calls to scanf which keep going even if the previous one failed
  • Don't use scanf (probably simpler in the long run).

A regex library might be the simplest option.

Upvotes: 2

BLUEPIXY
BLUEPIXY

Reputation: 40155

use strsep like below

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

char *strsep(char **sp, const char *sep);

int main(){
    char line[] = "abc:defg:1:2::hijk:no\n";
    int value1, value2;
    char string1[16];
    char string2[20];
    char string3[51];
    char string4[26];
    char string5[26];
    char *p = line;
/*
    sscanf(line, "%15[^:]:%20[^:]:%d:%d:%50[^:]:%25[^:]:%25[^\n]",
        string1, string2, &value1, &value2, string3, string4, string5);
*/
    strcpy(string1, strsep(&p, ":"));//or strncpy, etc. 
    strcpy(string2, strsep(&p, ":"));
    value1 = atoi(strsep(&p, ":"));
    value2 = atoi(strsep(&p, ":"));
    strcpy(string3, strsep(&p, ":"));
    strcpy(string4, strsep(&p, ":"));
    strcpy(string5, strsep(&p, ":\n"));
    printf("%s %s %d %d \"%s\" %s %s\n",
        string1, string2, value1, value2, string3, string4, string5);
    return 0;
}

See the following links for strsep.
strsep

strsep is not a standard function.
if it does not exist, be implemented as follows(E.g) :

char *strsep(char **sp, const char *sep){
    char *p, *s;
    if (sp == NULL || *sp == NULL || **sp == '\0') return(NULL);
    s = *sp;
    p = s + strcspn(s, sep);
    if (*p != '\0') *p++ = '\0';
    *sp = p;
    return(s);
}

Upvotes: 0

pmg
pmg

Reputation: 108978

You need to check the return value from scanf() calls

errno = 0;
int chk = sscanf(line, "%15[^:]:%20[^:]:%d:%d:%50[^:]:%25[^:]:%25[^\n]",
       string1, string2, &value1, &value2, string3, string4, string5);
switch (chk) {
    case 7: /* all ok */;
            break;
    case 6:
    case 5:
    case 4:
    case 3:
    case 2:
    case 1:
    case 0: /* not enough variabes were assigned a value */;
            break;
    case EOF: /* error reading data */;
              /* use ferror() and/or feof() and errno to determine cause of error */;
              break;
    default: /* no other cases are possible */;
             break;
}

Upvotes: 2

Anbu.Sankar
Anbu.Sankar

Reputation: 1346

try this..( & is missing for scanning int)

sscanf(line, "%15[^:]:%20[^:]:%d:%d:%50[^:]:%25[^:]:%25[^\n]", string1, string 2, &value1, &value2, string3, string4, string5);

Upvotes: 1

Related Questions