#include <stdio.h> int main() { int op1; char op; float op2; scanf("%d%2c%f", &op1, &op, &op2); printf("%d%2c%f", op1, op, op2); return 0; };
为什么当我输入1 * 2时,得到的是32 *2.000000而不是1* 2?
1 * 2
32 *2.000000
1* 2
nuypyhwy1#
代码中的问题是,您将2个带有%2c的字符读入一个对象op,而该对象只有一个字符的空间。这有未定义的行为。正如 chrslg 所评论的,写入op所占用的单字节内存可能会损坏op1的值,该值将成为32,空格字符的ASCII值,但这只是一个初步的解释,可能会发生其他事情,实际上,在不同的计算机上或使用不同的编译选项时,行为可能会有所不同。要忽略运算符前的空格,请在格式字符串中添加一个空格:使用"%d %c%f"。关于2.000000输出,%f的默认小数位数为6。使用%g省略不重要的小数。还要注意,您应该检查scanf()的返回值,并在main函数体之后删除;。以下是修改后的版本:
%2c
op
op1
32
"%d %c%f"
2.000000
%f
%g
scanf()
main
;
#include <stdio.h> int main(void) { int op1; char op; float op2; if (scanf("%d %c%f", &op1, &op, &op2) == 3) { printf("%d %c %g\n", op1, op, op2); } return 0; }
ui7jx7zq2#
answer from chqrlie已识别出您代码中的问题。但是,您可能需要更复杂一点,以处理scanf可能无法很好处理的情况。下面是一个例子,使用strtol和strtof来查找整数和浮点值。它检查这些函数的返回值,以确定是否已成功读取值。如果发生错误,它会发出有意义的错误代码(编码在枚举中)。
scanf
strtol
strtof
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdbool.h> typedef enum { SUCCESS = 0, NOTHING_READ, OP1_NOT_READ, OP_NOT_READ, OP2_NOT_READ } ParseStatus; ) bool is_valid_op(char op) { switch (op) { case '*': case '-': case '+': case '/': return true; default: return false; }; } ParseStatus parse_expr(char *expr, int *op1, char *op, float *op2) { while (isspace(*expr)) expr++; if (!*expr) return NOTHING_READ; char *end; *op1 = strtol(expr, &end, 10); if (expr == end) { return OP1_NOT_READ; } expr = end; while (isspace(*expr)) expr++; if (!*expr) return OP_NOT_READ; *op = *expr++; if (!is_valid_op(*op)) { return OP_NOT_READ; } while (isspace(*expr)) expr++; if (!*expr) return OP2_NOT_READ; *op2 = strtof(expr, &end); if (expr == end) { return OP2_NOT_READ; } return SUCCESS; } int main(void) { char op; int op1; float op2; ParseStatus ps = parse_expr("6*4.5", &op1, &op, &op2); if (ps != SUCCESS) { printf("Improperly formatted expression.\n"); return 1; } printf("%d %c %0.2f\n", op1, op, op2); return 0; }
这将打印:
6 * 4.50
2条答案
按热度按时间nuypyhwy1#
代码中的问题是,您将2个带有
%2c
的字符读入一个对象op
,而该对象只有一个字符的空间。这有未定义的行为。正如 chrslg 所评论的,写入
op
所占用的单字节内存可能会损坏op1
的值,该值将成为32
,空格字符的ASCII值,但这只是一个初步的解释,可能会发生其他事情,实际上,在不同的计算机上或使用不同的编译选项时,行为可能会有所不同。要忽略运算符前的空格,请在格式字符串中添加一个空格:使用
"%d %c%f"
。关于
2.000000
输出,%f
的默认小数位数为6。使用%g
省略不重要的小数。还要注意,您应该检查
scanf()
的返回值,并在main
函数体之后删除;
。以下是修改后的版本:
ui7jx7zq2#
answer from chqrlie已识别出您代码中的问题。但是,您可能需要更复杂一点,以处理
scanf
可能无法很好处理的情况。下面是一个例子,使用strtol
和strtof
来查找整数和浮点值。它检查这些函数的返回值,以确定是否已成功读取值。如果发生错误,它会发出有意义的错误代码(编码在枚举中)。这将打印: