c - 为什么我的程序直接跳过变量初始化之后的第一条指令?
问题描述
所以我正在尝试编写一个从左到右计算表达式的程序(就像操作按照输入的顺序执行一样)。例如:
Enter an expression: 1+2.5*3
Value of expression: 10.5
所以,我应该在不使用数组或字符串的情况下做到这一点。我的想法是继续扫描字符,直到扫描的字符与 0 到 9 之间的任何数字不同。然后,字符被转换为浮点数,并根据最后扫描的字符是什么,求和、乘法和诸如此类的操作被执行.
这是我写的:
#include <stdio.h>
#include <math.h>
int main() {
char digit = ' ';
int counter = 0;
int number = 0
float reversed_number = 0, reversed_decimal = 0, reversed_number2 = 0,
reversed_decimal2 = 0, result = 0;
printf("Enter an expression: ");
while(digit != '\n') {
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_number = pow(10, i)*(number / 10);
number /= 10;
}
if(digit == '.'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_decimal = pow(10, i)*(number / 10);
number /= 10;
counter++;
}
reversed_decimal /= pow(10, counter - 1);
reversed_number += reversed_decimal;
counter = 0;
}
else if(digit == '+'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_number2 = pow(10, i)*(number / 10);
number /= 10;
}
if(digit == '.'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_decimal2 = pow(10, i)*(number / 10);
number /= 10;
counter++;
}
reversed_decimal2 /= pow(10, counter - 1);
reversed_number2 += reversed_decimal2;
counter = 0;
}
result += reversed_number + reversed_number2;
}
else if(digit == '-'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_number2 = pow(10, i)*(number / 10);
number /= 10;
}
if(digit == '.'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_decimal2 = pow(10, i)*(number / 10);
number /= 10;
counter++;
}
reversed_decimal2 /= pow(10, counter - 1);
reversed_number2 += reversed_decimal2;
counter = 0;
}
result += reversed_number - reversed_number2;
}
else if(digit == '*'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_number2 = pow(10, i)*(number / 10);
number /= 10;
}
if(digit == '.'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_decimal2 = pow(10, i)*(number / 10);
number /= 10;
counter++;
}
reversed_decimal2 /= pow(10, counter - 1);
reversed_number2 += reversed_decimal2;
counter = 0;
}
result += reversed_number * reversed_number2;
}
else if(digit == '/'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_number2 = pow(10, i)*(number / 10);
number /= 10;
}
if(digit == '.'){
for(int i = 0; digit >= 48 && digit <= 57; i++){
digit = getchar();
number += pow(10, i)*(digit - 48);
}
for(int i = 0; number == 0; i++){
reversed_decimal2 = pow(10, i)*(number / 10);
number /= 10;
counter++;
}
reversed_decimal2 /= pow(10, counter - 1);
reversed_number2 += reversed_decimal2;
counter = 0;
}
result += reversed_number / reversed_number2;
}
}
printf("Value of expression: %g", result);
return 0;
}
代码编译得很好,没有任何警告,但是当我运行程序时,发生了一些奇怪的事情,它甚至没有打印出“输入表达式:”,它只是继续监听用户输入。我真的不明白为什么......即使代码完全与我的推理完全错误,它至少应该打印出第一个 printf 函数,因为在它可以使程序循环之前没有任何东西。
这里到底发生了什么?因为我不知道
解决方案
发生了一些奇怪的事情,它甚至没有打印出“输入一个表达式:”
这是因为 I/O 缓冲。printf
不会立即写入,它使用缓冲区。因为stdout
这是一个行缓冲区,这意味着它只会在看到换行符时刷新缓冲区(即写入)。由于您从不打印换行符stdout
,因此永远不会刷新。您可以显式刷新stdout
.
printf("Enter an expression: ");
fflush(stdout);
它只是继续监听用户输入
一些调试打印揭示了问题。
while(digit != '\n') {
printf("Top of while digit: '%c'\n", digit);
for(int i = 0; digit >= 48 && digit <= 57; i++){
puts("in loop");
digit = getchar();
printf(" digit: '%c'\n", digit);
number += pow(10, i)*(digit - 48);
}
printf("After first loop: '%c'\n", digit);
for(int i = 0; number == 0; i++){
printf("In second loop, number: %d\n", number);
reversed_number = pow(10, i)*(number / 10);
number /= 10;
}
printf("Digit: '%c'\n", digit);
$ ./test
Enter an expression: Top of while digit: ' '
After first loop: ' '
In second loop, number: 0
In second loop, number: 0
In second loop, number: 0
In second loop, number: 0
In second loop, number: 0
...
第一个循环看到digit
is并立即退出而不调用
getchar
. 这number == 0
使得第二个循环无休止地运行number /= 10
,即 0。
相反,如果您想逐行处理,请阅读一行,然后解析它。
char line[BUFSIZ];
fgets(line, sizeof(line), stdin);
for( int i = 0; line[i] != '\n' && line[i] != '\0'; i++ ) {
printf("%c", line[i]);
}
然后为了进一步清理您的代码,您可以使用isdigit
和朋友而不是检查单个 ASCII 代码。
if( isdigit(*c) ) {
printf("%c is a digit!\n", *c);
}
scanf
或者,这是从输入中读取和解析整个数字的合适时间。
推荐阅读
- symfony - 使用 axios 和 Symfony 删除对象时的状态码 500 但删除有效
- c# - 如何在 XAML 的 ShellPage 中使用 FontIcon 和 Glyph?
- c++ - 无法在c ++中输入第二行数字
- c# - 出现错误无法将“Newtonsoft.Json.Linq.JObject”类型的对象转换为“Newtonsoft.Json.Linq.JArray”类型
- python - 用户更改单元格内容时回调数据表
- swift - 调用中位置 #2、#3 的额外参数 - Swift
- c - 我可以在 C 中有一个长度不确定的数组吗?
- c - 如何在 C 中使用 exec argv 传递指针?
- android - 如何在 Android 中使用 Groupie 在 Recyclerview 中实现 HeaderItems
- excel - 在工作簿中移动形状