简体   繁体   中英

C sscanf to validate input format

I want to write a program which reads a line of input from the user, in the following format: <Name>,<Age>,<City>

  • The Name can contain English letters, spaces and - only.
  • The Age must be an integer between 18 to 120.
  • The City must contain English letters and - only.

Each of them can be of size 49. I want to store the information and print an informative error will be printed for bad input.

My code is the following:

    char str[150];
    char input[3][50] = { 0 };
    int num = 0;
    if (fgets(str, 150, stdin) != NULL) {
        num = sscanf(str, "%[a-zA-Z -],%[0-9],%[a-zA-Z-]", input[0], input[1], input[2]);
    }
    if (num < 3) {
        printf("ERROR\n");
    }

The problem is that an error will not be printed for an input such as Name1$#,20,NY , Best,19,Rome123 , or Best,100,Paris1$ , where the city is in wrong format (with trailing characters). There is any way to solve it using sscanf ?

You can use sscanf() and character classes for your purpose but there are small problems with your format string:

  • AZ assumes ASCII encoding or at least an encoding where letters are contiguous.
  • a trailing - has a special meaning, put the dash in first position to match a dash explicitly.
  • there is no length prefix, so a name or city longer than 49 characters will overflow the destination array.

Rather than using fgets() , you should read the line mannually to detect overlong lines.

You can add an extra %c to check for extra characters at the end of the line. Storing the converted value is not required if you don't intend to use the field values, but you must convert the number to check if its value is in the requested range:

    char str[150];
    char name[50];
    char city[50];
    char agestr[4];
    size_t i;
    int c, age, pos, n;

    for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
        if (i < sizeof(str) - 1)
            str[i] = (char)c;
    }
    if (c == EOF && i == 0) {
        printf("end of file\n");
        return -1;
    }
    if (i >= sizeof(str)) {
        printf("line too long\n");
        return 0;
    }
    str[i] = '\0';
    pos = 0;
    /* validate the name */
    if (sscanf(str + pos, "%49[-a-zA-Z ]%n", name, &n) != 1 || str[pos + n] != ',') {
        printf("invalid name\n");
        return 0;
    }
    pos += n + 1;
    /* validate the age */
    if (str[pos] == '0' || sscanf(str + pos, "%3[0-9]%n", agestr, &n) != 1 || str[pos + n] != ',') {
        printf("invalid age\n");
        return 0;
    }
    age = atoi(agestr);
    if (age < 18 || age > 120) {
        printf("age out of range: %d\n", age);
        return 0;
    }
    pos += n + 1;
    /* validate the city */
    if (sscanf(str + pos, "%49[-a-zA-Z]%n", city, &n) != 1 || str[pos + n] != '\0') {
        printf("invalid city\n");
        return 0;
    }
    /* Input was validated... proceed */

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM