C 中的计算器应该只接受 float/int 个数字
Calculator in C should only accept float/int numbers
我正在开发一个只有基本运算符的小型计算器。它工作得很好,就像我想要的那样。但是有一个小问题。
我的程序是在一个循环中,因此用户理论上可以在每次计算后再次使用它。
但我也希望程序能够区分 float
类型的数字和所有其他元素,因此它只接受浮点数或整数。
问题来了:
如果我输入字母字符,问题就会变得混乱并且无法正确循环。
您可以在输入一些随机字母而不是预期的两个数字时自己尝试一下。
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
int main()
{
float num1, num2, result = 0;
int menu;
while (1) //so that the program basically never stops
{
printf("--- Taschenrechner ---\n\n"
"1. Addition\n"
"2. Subtraktion\n"
"3. Multiplikation\n"
"4. Division\n"
"5. Beenden\n"
"Wählen Sie Ihren gewünschten Operator aus (oder auch nicht): ");
// it is like the calculators menu, distinguishing between
// addition, subtraction, multiplication, division and exit
scanf("%d", &menu);
if (menu >= 5 || menu < 1)
{
printf("\nDas Programm wurde beendet, schade. Bis zum nächsten Mal!"); //if the given integer is 5 or not part of the menu, the program should stop
break;
}
printf("\n\nGeben Sie nun zwei Zahlen ein:\n"); //user should provide two numbers
scanf("%f", &num1);
printf("\n");
scanf("%f", &num2);
if ((isalpha(num1) || isalpha(num2)) == 0) //if the given elements are no numbers at all, in this case part of the alphabet, the program should stop
{
printf("Gut!");
} else
{
printf("Break");
break;
}
switch (menu)
{
case 1:
result = num1 + num2;
break;
case 2:
result = num1 - num2;
break;
case 3:
result = num1 * num2;
break;
case 4:
result = num1 / num2;
break;
default:
printf("\n\nUps, da ist wohl etwas mit den Operatoren schief gelaufen. Versuchen Sie es erneut!"); //here again, if something went wrong within the switch case, program should stop
break;
}
printf("\n\nPerfekt, das hat geklappt!");
sleep(1); //this is just for delaying the result
printf("\n\nIhr Ergebnis wird berechnet\nErgebnis: %.2f\n\n\n", result);
sleep(3);
}
return 0;
}
我真的不知道如何解决这个问题,试了好几天了。解决方案可能真的很简单,但我就是不明白。
一点帮助会非常好。 :)
也不介意节目是德语的。我已经解释了一些东西作为评论。
您应该检查 scanf
编辑的值 return。例如:if( scanf("%d", &menu) == 1 ) { ... }
。如果输入流的下一个字符不是有效整数的一部分,上面的 scanf
将 return 0.
一般来说,您应该始终检查由 scanf return编辑的值。
为确保用户键入有效输入,您应该验证 scanf()
操作是否成功,并在数据无效时要求用户重新输入。 scanf()
returns 成功转换的次数。如果输入无效,您应该阅读并丢弃当前输入行的其余部分。
还要注意 if ((isalpha(num1) || isalpha(num2)) == 0)
是不正确的:它测试 num1
或 num2
是否是 ASCII 字母的代码。如果使用类型 65
或 97
...
,这将错误地检测到无效输入
这是修改后的版本:
#include <stdio.h>
#include <unistd.h>
int main() {
float num1, num2, result = 0;
int menu;
while (1) { //so that the program basically never stops
printf("--- Taschenrechner ---\n\n"
"1. Addition\n"
"2. Subtraktion\n"
"3. Multiplikation\n"
"4. Division\n"
"5. Beenden\n"
"Wählen Sie Ihren gewünschten Operator aus (oder auch nicht): ");
// it is like the calculators menu, distinguishing between
// addition, subtraction, multiplication, division and exit
if (scanf("%d", &menu) != 1 || // invalid menu entry, bail out
menu >= 5 || menu < 1) {
printf("\nDas Programm wurde beendet, schade. Bis zum nächsten Mal!"); //if the given integer is 5 or not part of the menu, the program should stop
break;
}
for (;;) {
printf("\n\nGeben Sie nun zwei Zahlen ein:\n"); //user should provide two numbers
if (scanf("%f%f", &num1, &num2) == 2)
break;
printf("\nUngültige Eingabe\n");
if (scanf("%*[^\n]") == EOF) // discard the rest of the input line
return 1;
}
switch (menu) {
case 1:
result = num1 + num2;
break;
case 2:
result = num1 - num2;
break;
case 3:
result = num1 * num2;
break;
case 4:
result = num1 / num2;
break;
default:
printf("\n\nUps, da ist wohl etwas mit den Operatoren schief gelaufen. Versuchen Sie es erneut!\n");
//here again, if something went wrong within the switch case, program should stop
return 1;
}
printf("\n\nPerfekt, das hat geklappt!");
sleep(1); //this is just for delaying the result
printf("\n\nIhr Ergebnis wird berechnet\nErgebnis: %.2f\n\n\n", result);
sleep(3);
}
return 0;
}
备注:
scanf()
无法转换 2 个浮点数的原因有 2 个:
- 文件过早结束,
- 流中的违规字符不能作为数字的开头,例如
A
或 %
。
要刷新用户输入的行的剩余部分,可以使用循环:
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
if (c == EOF) {
/* no more characters available from stdin: bail out */
return 1;
}
或者可以使用一种 scanf()
转换格式,该格式将读取并丢弃直到换行符的所有字符:
if (scanf("%*[^\n]") == EOF) // discard the rest of the input line
return 1;
解释如下:
%
之后的 *
阻止存储转换后的值,转换说明符不需要指针。
[...]
指定一个 scanset,一组要接受或拒绝的字符。 [abcx-z]
接受 a
、b
、c
、x
、z
和 x
之间的任何字符的任何非空组合和 z
(ASCII 字符集中的 y
)。 [^\n]
接受不同于 \n
的任何非空字符序列,因此输入行的其余部分(如果有的话)。
- 用户键入的无法与行的其余部分一起转换的字符将被读取并丢弃,留下换行符。
- 如果换行前没有这样的字符可用,
scanf()
returns 0
并且换行仍在等待下一次%f
转换;
- 如果流立即到达文件末尾,
scanf()
returns EOF
将导致程序退出。
我正在开发一个只有基本运算符的小型计算器。它工作得很好,就像我想要的那样。但是有一个小问题。
我的程序是在一个循环中,因此用户理论上可以在每次计算后再次使用它。
但我也希望程序能够区分 float
类型的数字和所有其他元素,因此它只接受浮点数或整数。
问题来了: 如果我输入字母字符,问题就会变得混乱并且无法正确循环。 您可以在输入一些随机字母而不是预期的两个数字时自己尝试一下。
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
int main()
{
float num1, num2, result = 0;
int menu;
while (1) //so that the program basically never stops
{
printf("--- Taschenrechner ---\n\n"
"1. Addition\n"
"2. Subtraktion\n"
"3. Multiplikation\n"
"4. Division\n"
"5. Beenden\n"
"Wählen Sie Ihren gewünschten Operator aus (oder auch nicht): ");
// it is like the calculators menu, distinguishing between
// addition, subtraction, multiplication, division and exit
scanf("%d", &menu);
if (menu >= 5 || menu < 1)
{
printf("\nDas Programm wurde beendet, schade. Bis zum nächsten Mal!"); //if the given integer is 5 or not part of the menu, the program should stop
break;
}
printf("\n\nGeben Sie nun zwei Zahlen ein:\n"); //user should provide two numbers
scanf("%f", &num1);
printf("\n");
scanf("%f", &num2);
if ((isalpha(num1) || isalpha(num2)) == 0) //if the given elements are no numbers at all, in this case part of the alphabet, the program should stop
{
printf("Gut!");
} else
{
printf("Break");
break;
}
switch (menu)
{
case 1:
result = num1 + num2;
break;
case 2:
result = num1 - num2;
break;
case 3:
result = num1 * num2;
break;
case 4:
result = num1 / num2;
break;
default:
printf("\n\nUps, da ist wohl etwas mit den Operatoren schief gelaufen. Versuchen Sie es erneut!"); //here again, if something went wrong within the switch case, program should stop
break;
}
printf("\n\nPerfekt, das hat geklappt!");
sleep(1); //this is just for delaying the result
printf("\n\nIhr Ergebnis wird berechnet\nErgebnis: %.2f\n\n\n", result);
sleep(3);
}
return 0;
}
我真的不知道如何解决这个问题,试了好几天了。解决方案可能真的很简单,但我就是不明白。 一点帮助会非常好。 :)
也不介意节目是德语的。我已经解释了一些东西作为评论。
您应该检查 scanf
编辑的值 return。例如:if( scanf("%d", &menu) == 1 ) { ... }
。如果输入流的下一个字符不是有效整数的一部分,上面的 scanf
将 return 0.
一般来说,您应该始终检查由 scanf return编辑的值。
为确保用户键入有效输入,您应该验证 scanf()
操作是否成功,并在数据无效时要求用户重新输入。 scanf()
returns 成功转换的次数。如果输入无效,您应该阅读并丢弃当前输入行的其余部分。
还要注意 if ((isalpha(num1) || isalpha(num2)) == 0)
是不正确的:它测试 num1
或 num2
是否是 ASCII 字母的代码。如果使用类型 65
或 97
...
这是修改后的版本:
#include <stdio.h>
#include <unistd.h>
int main() {
float num1, num2, result = 0;
int menu;
while (1) { //so that the program basically never stops
printf("--- Taschenrechner ---\n\n"
"1. Addition\n"
"2. Subtraktion\n"
"3. Multiplikation\n"
"4. Division\n"
"5. Beenden\n"
"Wählen Sie Ihren gewünschten Operator aus (oder auch nicht): ");
// it is like the calculators menu, distinguishing between
// addition, subtraction, multiplication, division and exit
if (scanf("%d", &menu) != 1 || // invalid menu entry, bail out
menu >= 5 || menu < 1) {
printf("\nDas Programm wurde beendet, schade. Bis zum nächsten Mal!"); //if the given integer is 5 or not part of the menu, the program should stop
break;
}
for (;;) {
printf("\n\nGeben Sie nun zwei Zahlen ein:\n"); //user should provide two numbers
if (scanf("%f%f", &num1, &num2) == 2)
break;
printf("\nUngültige Eingabe\n");
if (scanf("%*[^\n]") == EOF) // discard the rest of the input line
return 1;
}
switch (menu) {
case 1:
result = num1 + num2;
break;
case 2:
result = num1 - num2;
break;
case 3:
result = num1 * num2;
break;
case 4:
result = num1 / num2;
break;
default:
printf("\n\nUps, da ist wohl etwas mit den Operatoren schief gelaufen. Versuchen Sie es erneut!\n");
//here again, if something went wrong within the switch case, program should stop
return 1;
}
printf("\n\nPerfekt, das hat geklappt!");
sleep(1); //this is just for delaying the result
printf("\n\nIhr Ergebnis wird berechnet\nErgebnis: %.2f\n\n\n", result);
sleep(3);
}
return 0;
}
备注:
scanf()
无法转换 2 个浮点数的原因有 2 个:- 文件过早结束,
- 流中的违规字符不能作为数字的开头,例如
A
或%
。
要刷新用户输入的行的剩余部分,可以使用循环:
int c; while ((c = getchar()) != EOF && c != '\n') continue; if (c == EOF) { /* no more characters available from stdin: bail out */ return 1; }
或者可以使用一种 scanf()
转换格式,该格式将读取并丢弃直到换行符的所有字符:
if (scanf("%*[^\n]") == EOF) // discard the rest of the input line
return 1;
解释如下:
%
之后的*
阻止存储转换后的值,转换说明符不需要指针。[...]
指定一个 scanset,一组要接受或拒绝的字符。[abcx-z]
接受a
、b
、c
、x
、z
和x
之间的任何字符的任何非空组合和z
(ASCII 字符集中的y
)。[^\n]
接受不同于\n
的任何非空字符序列,因此输入行的其余部分(如果有的话)。- 用户键入的无法与行的其余部分一起转换的字符将被读取并丢弃,留下换行符。
- 如果换行前没有这样的字符可用,
scanf()
returns0
并且换行仍在等待下一次%f
转换; - 如果流立即到达文件末尾,
scanf()
returnsEOF
将导致程序退出。