Возвращаемое значение sscanf - PullRequest
0 голосов
/ 18 октября 2018

Я читал о sscanf, и я столкнулся с этим:

Возвращаемое значение Каждая из этих функций [включая s_sscanf ()] возвращает количество полей, которые успешно преобразованы и назначены;возвращаемое значение не включает поля, которые были прочитаны, но не назначены.Возвращаемое значение 0 указывает, что поля не были назначены.Возвращаемое значение - EOF для ошибки или если конец строки достигнут перед первым преобразованием.

Я делаю проверку ошибок для моего входного файла, и я хочу удостовериться, что получаю правильную строкупоэтому я попытался использовать sscanf, но как мне убедиться, что в строке нет больше полей, чем я ожидал.Так что, если у меня есть 3 значения в строке, но мне нужно только два, тогда это неверная строка для меня, но когда я использую sscanf, я читаю только 2 переменные, а остальные игнорируются.Как проверить всю строку, убедившись, что в строке нет мусора, но я не уверен, чего ожидать, поэтому я не могу добавить еще одну переменную, потому что пользователь может ввести что угодно.Кто-то упомянул мне, что вы можете использовать * в своей функции sscanf, но я не совсем уверен, как я не смог найти его где-нибудь, где это реализовано в коде.

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Семейство функций scanf() возвращает количество выполненных успешных назначений.Если код ожидает три элемента ввода, то из значения, возвращенного одним sscanf(), невозможно определить, были ли предоставлены три или более элементов ввода.

Функции scanf() работают, читая символ, пытаясьсопоставьте этот символ, сделав присваивание, если это применимо, затем перейдите к следующему символу или вернитесь из вызова функции.Существует спецификатор преобразования %n, в котором хранится количество символов, прочитанных в этом процессе (без увеличения количества прочитанных символов).Этот спецификатор преобразования может быть использован для определения того, был ли введен исчерпанный ввод при вызове sscanf().

. Приведенный ниже код демонстрирует.Строки ввода, собранные fgets(), содержат символ новой строки, если только ввод не слишком велик для размещения в массиве буферов.Здесь buffer[] достаточно большой, чтобы хранить входные данные разумного размера, но более надежный код будет обрабатывать слишком большие входные данные более осторожно.Когда sscanf() сканирует входную строку, каждый символ читается по очереди, пока не произойдет неудачное совпадение или не будет достигнут конец строки, поэтому ожидаемое после сопоставления "%d %d %d %n" число символов чтения совпадает с длиной вводастрока, включая любые завершающие пробельные символы.

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

#define BUF_SZ  1024

int main(void)
{
    char buffer[BUF_SZ];
    int x, y, z;
    int pos;

    printf("Enter three integers: ");
    fflush(stdout);

    // get user input
    if (fgets(buffer, sizeof buffer, stdin) != NULL) {

        // first check: does input match 3 integers?
        if (sscanf(buffer, "%d %d %d %n", &x, &y, &z, &pos) != 3) {
            puts("Incorrectly formatted input");
        } else {
            // second check: did sscanf() finish at the end of the buffer?
            int expected = strlen(buffer);
            if (pos != expected) {
                puts("Extra input in buffer");
                printf("expected = %d, pos = %d\n", expected, pos);
        } else {
            // everything OK
            printf("You entered: %d, %d, %d\n", x, y, z);
            }
        }
    }

    return 0;
}

Примеры взаимодействий:

>$ ./a.out 
Enter three integers: 1 2 3
You entered: 1, 2, 3
>$ ./a.out 
Enter three integers: 1 2
Incorrectly formatted input
>$ ./a.out 
Enter three integers: 1 2 3 4
Extra input in buffer
expected = 8, pos = 6

Если необходимо запретить даже конечные пробельные символы символы, "%d %d %d%n" можетиспользоваться вместоОбратите внимание, что для того, чтобы это работало, символ новой строки должен быть удален из buffer[], чтобы он не считался дополнительным вводом.Один из типичных способов сделать это - использовать buffer[strcspn(buffer, "\r\n")] = '\0':

int main(void)
{
    char buffer[BUF_SZ];
    int x, y, z;
    int pos;

    printf("Enter three integers: ");
    fflush(stdout);

    // get user input
    if (fgets(buffer, sizeof buffer, stdin) != NULL) {

        // first check: does input match 3 integers?
        if (sscanf(buffer, "%d %d %d%n", &x, &y, &z, &pos) != 3) {
            puts("Incorrectly formatted input");
        } else {
            // remove trailing newline character
            buffer[strcspn(buffer, "\r\n")] = '\0';
            // second check: did sscanf() finish at the end of the buffer?
            int expected = strlen(buffer);
            if (pos != expected) {
                puts("Extra input in buffer");
                printf("expected = %d, pos = %d\n", expected, pos);
        } else {
            // everything OK
            printf("You entered: %d, %d, %d\n", x, y, z);
            }
        }
    }

    return 0;
}
0 голосов
/ 18 октября 2018

Вы можете, во-первых, дать спецификаторы преобразования для значений, которые, как вы уверены, должны присутствовать, а затем добавить «модификатор назначения-выделения» для захвата любого оставшегося ввода.Я не уверен, говорите ли вы о sscanf, fscanf или scanf;Я просто буду использовать scanf для иллюстрации.Следующая программа читает 2 целых числа и помещает все оставшиеся входные данные в строковую переменную, размер которой динамически выделяется:

Обновление: использование sscanf вместо scanf.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
    int a,b;
    char *s;
    int n;
    char src[]="1 2 This is the remainder";
    n=sscanf(src,"%d %d %m[^\n]",&a,&b,&s);
    if(n>2)
        printf("s=%s\n", s), free(s);
    return 0;
}

$ ./a.out 
s=This is the remainder
...