Как было правильно указано, вы не можете объявить float items[size];
, пока size
не будет правильно инициализировано положительным целочисленным значением. Ваша попытка объявить items
до size
содержит значение вызывает неопределенное поведение из-за вашей попытки получить доступ к неинициализированному значению. (допустимая операция вашего кода на этом этапе закончена, и он может делать все, что угодно, начиная от правильной работы до StackOverflow или SegFaulting)
Каждый раз, когда вы принимаете пользовательский ввод, вы должны учитывать каждый символ, который остается во входном буфере (stdin
здесь). Это особенно верно при приеме ввода с scanf
(или семейством) из-за способа, которым scanf
обрабатывает input или , соответствующие сбоям. В любом из этих случаев дальнейшие символы не читаются , а любые оскорбительные символы остаются непрочитанными во входном буфере - просто ожидая, что вас снова укусят при следующей попытке чтения (обычно это приводит к бесконечному циклу, если вы принимая входные данные в цикле)
(это одна из основных причин, по которой линейно-ориентированная функция , такая как fgets
, рекомендуется для ввода данных пользователем)
scanf
можно использовать, если используется правильно. Это означает, что вы несете ответственность за проверку возврата из scanf
каждый раз . Вы должны справиться с тремя условиями
(return == EOF)
пользователь отменяет ввод, генерируя руководство EOF
, нажимая Ctrl + d (или в windows Ctrl + z , но см. CTRL + Z не генерирует EOF в Windows 10 );
(return == expected No. of conversions)
указывает на успешное чтение - тогда вам нужно проверить, соответствует ли входные данные каким-либо дополнительным критериям (например, положительное целое число, положительная с плавающей точкой и т. Д.); и
- в противном случае вы должны обработать ошибку match или input , и вы должны учитывать каждый символ, который может остаться в вашем входном буфере. (обычно вы будете сканировать вперед во входном буфере до тех пор, пока не будет найден
'\n'
или EOF
, отбрасывающий все оставшиеся посторонние символы)
Если вы делаете свою работу, вы можете успешно использовать scanf
по мере необходимости.
Далее, общее предостережение не используйте плавающую точку для валюты (люди очень злятся, когда вы начинаете терять деньги из-за ошибок округления) Хотя это хорошо для вашего примера программы - просто поймите, в В реальной программе обработки валюты вы должны обрабатывать валюту как значение без знака, умноженное на 100
(или все, что требуется), чтобы обеспечить точное представление всех сумм.
Собрав вместе требования scanf
, вы можете безопасно сделать что-то вроде следующего:
#include <stdio.h>
/* function to empty extraneous characters from stdin
* (like the '\n' generated by pressing [Enter])
*/
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int size = 0, i;
float total = 0.0;
for (;;) { /* loop continually until valid size entered */
int rtn;
printf ("How many items are you checking out today?: ");
rtn = scanf ("%d", &size);
if (rtn == EOF) { /* handle EOF */
fprintf (stderr, "(user canceled input)\n");
return 1;
}
else if (rtn == 1 && size > 0) { /* valid int received */
empty_stdin();
break;
} /* otherwise, handle error */
fprintf (stderr, "error: invalid input.\n\n");
empty_stdin (); /* remove any chars from stdin up to '\n' */
}
float items[size]; /* declare VLA of size floats */
for (i = 0; i < size; i++) {
items[i] = 0.0; /* initialize each (or memset VLA) */
for (;;) { /* loop continually until valid item price entered */
int rtn;
printf (" price of item[%2d]: ", i + 1); /* prompt for price */
rtn = scanf ("%f", &items[i]);
if (rtn == EOF) { /* handle EOF */
fprintf (stderr, "(user canceled input)\n");
return 1;
}
else if (rtn == 1 && items[i] > 0) { /* valid price received */
empty_stdin();
break;
} /* otherwise, handle error */
fprintf (stderr, "error: invalid input.\n\n");
empty_stdin (); /* remove any chars from stdin up to '\n' */
}
total += items[i];
}
printf ("\ntotal (%d items): $%.2f\n", size, total);
}
Пример использования / Вывод
(показано с преднамеренными ошибками в записи)
$ ./bin/checkout
How many items are you checking out today?: what?
error: invalid input.
How many items are you checking out today?: 4
price of item[ 1]: free?
error: invalid input.
price of item[ 1]: 1.25
price of item[ 2]: 3.50
price of item[ 3]: discount?
error: invalid input.
price of item[ 3]: 2.25
price of item[ 4]: 3
total (4 items): $10.00
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.