正如已经正确指出的那样,您不能声明float items[size];
直到size
被有效初始化为正整数值。由于您尝试访问未初始化的值,您尝试声明items
之前size
包含一个值会调用未定义的行为。(此时您的代码的有效操作已经结束,它可以做任何事情,从看起来正确运行到 StackOverflow 或 SegFaulting)
每当您进行用户输入时,您必须考虑输入缓冲区中保留的每个字符(stdin
此处)。scanf
由于scanf
处理输入或匹配失败的方式,在与(或家人)一起接受输入时尤其如此。当任何一种情况发生时,都不会读取更多字符,并且输入缓冲区中的任何违规字符都不会被读取 - 只是在等待下一次尝试读取时再次咬你(如果你在循环中接受输入,通常会导致无限循环)
(这是推荐使用面向行的函数fgets
来获取用户输入的主要原因之一)
scanf
可以使用,如果使用正确。这意味着您有责任检查每次退货。你必须处理三个条件scanf
(return == EOF)
EOF
用户通过按Ctrl+d(或在 windows 上Ctrl+z,但请参阅CTRL+Z 在 Windows 10 中不生成 EOF )生成手册来取消输入;
(return == expected No. of conversions)
表示读取成功——然后由您来检查输入是否满足任何附加条件(例如正整数、正浮点等);和
- 否则,您必须处理匹配或输入失败,并且必须考虑输入缓冲区中可能留下的每个字符。(通常您将在输入缓冲区中向前扫描,直到发现 a
'\n'
orEOF
丢弃任何剩余的无关字符)
如果你做你的工作,你可以成功地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
如果您还有其他问题,请仔细查看并告诉我。