Почему я не могу использовать «scanf_s» для чтения символа и числа одновременно? - PullRequest
2 голосов
/ 07 июля 2019

Сбой этого кода:

scanf_s("%c %d",&ch,&x);//Run error

Но этот код работает:

scanf_s("%c",&ch);
scanf_s("%d",&x);//Run succeed

Я хочу знать, почему первый фрагмент кода неправильный.

означает «ошибка выполнения» Компилятор выдает предупреждение и что-то не так, когда я запускаю программу input

Ответы [ 3 ]

3 голосов
/ 07 июля 2019

Поскольку вы используете scanf_s (в отличие от scanf), вам необходимо предоставить дополнительный параметр длины для %c (ср., Например, этот документ от Microsoft относительно scanf_s):

В отличие от scanf и wscanf, scanf_s и wscanf_s требуют указания размеров буфера для некоторых параметров.Укажите размеры для всех параметров набора управления c, C, s, S или string [].

Так что вам нужно будет написать

scanf_s ("%c %d", &ch, 1, &x);

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

Обратите внимание, что scanf_s("%c",&ch); должен выдать такое же предупреждение / ошибку, поскольку в нем также отсутствует обязательный параметр длины для %c.

Команда scanf_s("%d",&x); напротив, это нормально, так как %d не требует (не должен предоставляться) дополнительного параметра длины.

2 голосов
/ 07 июля 2019

Я предполагаю, что вы используете MSVC, который выдает ошибку, если вы используете scanf вместо scanf_s.Я также предполагаю, что вы хотите использовать первое, а не второе.Чтобы отключить ошибку, перейдите в меню «Проект» -> «Свойства [имя проекта]» -> C / C ++ -> препроцессор.В поле «Определения препроцессора» добавьте макрос _CRT_SECURE_NO_WARNINGS.Затем нажмите «Применить».

Теперь вы сможете использовать scanf, как и на любом другом компиляторе / IDE.

enter image description here

0 голосов
/ 07 июля 2019

В качестве расширения ответа Штефана Лехнера рассмотрим, что происходит при выполнении scanf_s("%c %d",&ch,&x).

Технически, это неопределенное поведение, потому что вы не указали правильные параметры для scanf_s.

Однако на практике код будет пытаться интерпретировать ненужные значения в памяти как отсутствующие параметры.То есть код эквивалентен примерно так:

scanf_s("%c %d", &ch, 0xf0000000, 0xdeadbeef);

Здесь 0xf0000000 представляет адрес переменной x.Код scanf_s будет интерпретировать его как размер буфера (очень большой буфер), но это не имеет никакого эффекта, потому что %c говорит ему прочитать только один байт.Кроме того, 0xdeadbeef представляет собой мусор, и код интерпретирует его как адрес для записи вашего целочисленного результата.Запись по случайным адресам - это большое «нет-нет», поэтому происходит сбой.

Когда ваш код читает отдельно char и int, он никогда не сталкивается с записью по случайному адресу, поэтому все работает хорошо,и если вы игнорируете предупреждения компилятора, вы никогда не узнаете, что ваш код содержит ошибки.

...