我正在尝试使用堆栈进行后缀求值。输出应该采用
2,3,4,+,-,#
以 # 表示表达式结束的格式。问题是允许使用负数,即负数2,3,-10,+,-,#
也是有效输入。我需要一种方法来将数字与字符分开。
int main() {
int num;
char ch;
int ret;
printf("Enter integers or characters separated by commas (e.g., 12,a,34,#):\n");
while (1) {
scanf(" ,");
ret = scanf("%d", &num);
if (ret == 1) {
printf("Input is an Integer: %d\n", num);
if (ret == -1)
break;
} else {
if (scanf(" %c", &ch) == 1) {
// Print an error message for non-integer input
//ch = getchar();
printf("Input is a Character: '%c' (invalid integer)\n", ch);
} else {
printf("End of input\n");
break;
}
}
}
return 0;
}
我面临的问题是,如果输入的是1,2,3,a,b,-1
->,它会正确地将数字识别为数字,a
将识别b
为字符。但是如果我输入的1,2,3,+,-,#,-1
是 作为输入,它会以某种方式接受,
而不是+
,而将 识别为。我不知道为什么会发生这种情况。任何帮助都值得感激。-
#
问题是
scanf("%d", &num)
只有一个字符向前看。它读取符号+
,由于它可以开始一个数字,因此它会读取下一个字符来解析数字,但这个字符是,,
所以它会将其推回到输入流并返回0
。您的版本scanf
不能推回超过一个字节,因此读取的下一个字节scanf(" %c", &ch)
是,
,而不是符号。在之后+
也会出现同样的问题。-
,
这种行为看起来像是实现质量问题,但 C 标准实际上规定读取并丢弃预期形式的前缀,只有第一个不能成为匹配部分的字节留在输入流中。因此,符号
+
和任何前面的空格都会因%d
转换失败而被消耗。函数系列中的另一个陷阱scanf
使它们难以正确使用,并且不太可能进行错误恢复。scanf()
不是适合您项目的正确工具。fgets
并且strtol
似乎更合适并提供更好的错误检查:问题是字符
+
和-
可能是数字的一部分,例如-1
,因此在这些字符的情况下,当scanf("%d", &num)
无法读取整数十进制数时,它将消耗输入中的+
或字符,因此以下最终将分隔逗号读取为输入字符。-
scanf(" %c", &ch)
解决此问题的一个方法是首先将逗号之间的每个条目读取
,
为字符串,并将其存储在字符数组中。为此,您可以" %[^,\n]"
在scanf
函数中使用说明符,即字符串说明符,用于丢弃前导空白字符,并将除逗号,
或换行符之外的所有内容存储\n
在字符数组中。然后就可以使用该
sscanf
函数处理数组中的字符串,判断它是否是有效的int
或者是一个字符。像这样:
或者,按照@chux-ReinstateMonica 的建议,您可以使用它
strtol
来处理字符串,如下所示:读取用户输入并进行解析是一项挑战。通常最好将输入与解析分开,因为每个部分都有各自的特定问题和恢复,无法很好地协同工作。
scanf()
可能无法完全恢复扫描失败的输入。只能恢复 1 个扫描失败的字符。失败后,再次扫描可能会在意想不到的地方恢复。输入,然后解析
考虑读取一个标记:一个直到分隔符
','
或EOF
最大长度的字符串。读取令牌后,根据需要多次解析它。
如果必须使用
scanf("%d",...
,请先扫描标志。[ 我更喜欢 @isnick - 制作这个 wiki]
类似于