почему scanf () не превращает ни один в два числа - PullRequest
1 голос
/ 25 апреля 2020

Я новичок ie на C ++, и я столкнулся с некоторыми проблемами. Вопрос, который необходимо решить, состоит в том, чтобы иметь 5 входных данных, входные данные могут включать целые числа и строку «нет», попытаться суммировать целые числа во входных данных, и результат должен быть двойным. Вот что я сделал: я поместил пять входов в массив и использую scanf (), чтобы превратить их в double, но когда я ввожу none и использую printf, чтобы увидеть массив, я обнаружил, что он не превращает ни один в два числа с плавающей точкой, выполняет scanf есть какие-либо ограничения на преобразование строк в удвоение?

Вот код:

int main()
{
    double sc[5];

    for (int i = 0; i < 5; i++) {
        sc[i] = 3;
        scanf("%lf", &sc[i]);
        printf("%lf\n", sc[i]);
    }
}

и вывод:

34
34.000000
none
3.000000
3.000000
56
56.000000
89
89.000000

1 Ответ

0 голосов
/ 25 апреля 2020

Вызов scanf("%lf", &something) заполняет something тогда и только тогда, когда ввод является действительным числом с плавающей запятой. Строка none - это , а не , такое действительное число.

Причина, по которой вы получаете два значения 3, вероятно, заключается в том, что nan является допустимым число с плавающей запятой, поэтому scanf находит n и говорит: "Ха, это будет nan". Но затем он находит, к большому разочарованию, o и решает, что он больше не действителен.

Но он уже прочитал no из входного потока. Затем он возвращается и делает то же самое с ne (a) .

После этого вы снова начинаете давать ему действительные номера, чтобы он продолжал.


Если вы хотите иметь возможность обрабатывать строки и чисел, вам придется использовать наименее ограничивающий (строка), а затем принять решение. Примерно так (хотя scanf("%s") опасно для реального кода, это, вероятно, нормально для работы с классами):

Следующий код делает это и (как следует) проверяет возвращаемое значение из scanf/sscanf, чтобы убедиться, что оно было правильно отсканировано:

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

int main() {
    static char bigstring[1000];
    double sc[5];

    for (int i = 0; i < 5; i++) {
        sc[i] = 3;
        if (scanf("%s", bigstring) != 1) {
            puts("*** Could not get input");
            return 1;
        }

        if (strcmp("none", bigstring) == 0) {
            puts("Got 'none', converting to -999");
            sc[i] = -999;
        } else if (sscanf(bigstring, "%lf", &sc[i]) != 1) {
            printf("*** Could not convert input '%s' to float", bigstring);
            return 1;
        } else {
            printf("Got %f\n", sc[i]);
        }
    }

    puts("\nThe five entered numbers were:");
    for (int i = 0; i < 5; i++) {
        printf("   %lf\n", sc[i]);
    }
}

Запуск, который работает правильно с основными c тестовыми данными:

pax:~$ printf "34\nnone\n56\n89\n111\n" | ./qq
Got 34.000000
Got 'none', converting to -999
Got 56.000000
Got 89.000000
Got 111.000000

The five entered numbers were:
   34.000000
   -999.000000
   56.000000
   89.000000
   111.000000

(a) Интересно, что это выглядит так происходит только с реальным пользовательским вводом, а не с передачей данных через программу в соответствии с моим оператором printf.

Поведение идеально , по моему мнению, должно было бы оставить поток ввода, указывающий на неверные данные. Другими словами, если точный текст не является допустимым (например, nan), указатель не должен двигаться вообще. Однако в стандарте C есть сноска, которая допускает такое поведение, если, например, входной поток недоступен для поиска:

fscanf возвращает максимум один входной символ на входной поток.

Таким образом, хотя он может быть в состоянии выполнить резервное копирование дальше, чем на конвейере, это может быть не так при работе с терминалом input.

Когда я ввожу x в качестве ввода, кажется, что делает pu sh, что обратно, потому что каждый последующий элемент массива заполнен 3, что означает, что он читает что x непрерывно. Все, что начинается с n, похоже, потребляет только этот и следующий символ.

...