C sscanf для проверки формата ввода - PullRequest
1 голос
/ 09 апреля 2020

Я хочу написать программу, которая читает строку ввода от пользователя в следующем формате: <Name>,<Age>,<City>

  • Имя может содержать английские sh буквы, пробелы и - только.
  • Возраст должен быть целым числом от 18 до 120.
  • Город должен содержать только буквы sh на английском языке и только -.

Каждый из них может иметь размер 49. Я хочу сохранить информацию и распечатать информационную ошибку, которая будет напечатана при неправильном вводе.

Мой код следующий:

    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");
    }

Проблема является то, что ошибка не будет напечатана для ввода, такого как Name1$#,20,NY, Best,19,Rome123 или Best,100,Paris1$, где город имеет неправильный формат (с завершающими символами). Есть ли способ решить это с помощью sscanf?

1 Ответ

4 голосов
/ 09 апреля 2020

Вы можете использовать sscanf() и классы символов для своих целей, но есть небольшие проблемы с вашей строкой формата:

  • A-Z предполагает кодировку ASCII или, по крайней мере, кодировку, где буквы являются смежными.
  • в конце - имеет особое значение, поместите da sh в первую позицию, чтобы явно соответствовать da sh.
  • префикс длины отсутствует, поэтому имя или город, длина которого превышает 49 символов, переполнит целевой массив.

Вместо того, чтобы использовать fgets(), вы должны прочитать строку вручную, чтобы обнаружить слишком длинные строки.

Вы можете добавить дополнительные %c чтобы проверить наличие дополнительных символов в конце строки. Сохранение преобразованного значения не требуется, если вы не собираетесь использовать значения поля, но вы должны преобразовать число, чтобы проверить, находится ли его значение в требуемом диапазоне:

    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 */
...