Ввод float в программу, которая имеет дело только с int - PullRequest
4 голосов
/ 03 августа 2011

У меня есть программа, но когда я ввожу числа с плавающей запятой всякий раз, когда программа запрашивает ввод, программа внезапно пропускает шаг и переходит к конечному выходу.Ниже приведена программа:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int a,b,c;
  int i;

  printf("Please enter a number: ");
  scanf("%d", &a);
  printf("Please enter a number: ");
  scanf("%d", &b);

  c = 0; 
  for(i=0; i < b; i++)
    {
    c = c + a;
    } 

  printf("%d x %d = %d\n", a, b, c);

  return 0;
}

Когда я введу int для a и число с плавающей запятой для b, программа выведет продукт в соответствии с ожиданиями, если числа после десятичной точки для b усечено.Однако при вводе числа с плавающей запятой для a программа не принимает значение для второго числа b, а вместо этого пропускает этот шаг и выводит целочисленную версию a x -858993460 = 0.

Например:

a = int, b = float

Пожалуйста, введите число: 3
Пожалуйста, введите число: 5,6
3 x 5 = 15

a = плавать, b = пропущено

Пожалуйста, введите число 3,9
Пожалуйста, введите число: 3 x -858993460 = 0

ВсеНедостатки в коде являются преднамеренными, но я просто хотел знать, почему он ведет себя так, как я объяснил выше.Я знаю, что это связано с попыткой ввести число с плавающей запятой в целое число со знаком, но я не уверен, что именно заставляет его пропустить второй scanf("%d", &b).Кто-нибудь может объяснить, почему это происходит?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 03 августа 2011

Консольный ввод строка буферизована ; когда вы вводите 3.9 в спецификатор формата %d, используется только 3, оставшиеся данные остаются в буфере, поэтому второй вызов scanf () пытается преобразовать его в соответствии с его спецификатором, находит '.' и прерывает преобразование оставив b неопределенным.

scanf() будет продолжать "проваливаться" до тех пор, пока не будет использован '\n' в конце входных данных. Вы можете сделать это так:

  printf("Please enter a number: ");
  scanf("%d", &a);
  while( getchar() != '\n' ) { /* do nothing */ }

  printf("Please enter a number: ");
  scanf("%d", &b);
  while( getchar() != '\n' ) { /* do nothing */ }

Обратите внимание, что если спецификатор формата равен %c, требуется изменить код очистки, поскольку преобразованный символ уже может быть '\n':

scanf("%c", &c);
while( c != '\n' && getchar() != '\n' ) { /* do nothing */ }
2 голосов
/ 03 августа 2011

Похоже, scanf() читает ваш «3» во втором случае и игнорирует «9».

Затем, когда вызывается второй scanf(), во входе уже есть текстбуфер (".9").

Я не могу точно сказать, что он делает с ".9".Возможно, он нашел точку и просто прервал ее с b неинициализированным.Определить, что происходит, должно быть несложно, перейдя к отладчику.

Но, по сути, не все входные данные обрабатываются при первом вызове scanf(), и поэтому это второй вызовпытается читать.И поэтому вам не нужно вводить какие-либо данные для второго вызова.

1 голос
/ 03 августа 2011

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

И этот конкретный символ рассматривается как непрочитанный и используется в качестве первого символа следующего поля ввода или любой последующей операции чтения.

В приведенном выше примере он сканирует 3 и не может преобразовать . в спецификатор формата "%d".Следовательно, он хранит 3 в переменной a, оставляя .9 непрочитанным.Когда элемент управления передается следующему оператору scanf, он сканирует ., но, опять же, поскольку он не может разрешить . для форматирования спецификатора "%d", он пропускает сканирование ввода для этого поля.

Теперьпоскольку переменная b не была назначена, она содержит некоторое значение мусора .И любая арифметическая операция со значениями мусора приводит к значениям мусора.

...