我用 C 做了一个计算器,但我想修复一些关于 scanf 的错误
I made a calculator in C, but i want to fix some bugs regarding scanf
所以我用 C 做了一个计算器,它可以工作,但我想消除一些错误,它与 scanf 有关。
我遇到的问题是:
- 如果我输入 5 5 ,数字 1 和数字 2 都将是 5。我可以忽略 space 并将数字作为 55 吗?
- 如果我输入 5c,它会将数字 1 读取为 5,然后它会触发故障保护(因为 'c')并关闭。
- 如果我输入一个非常大的数字,它会给出一个错误的结果。有什么方法可以限制 15 个号码吗?
我想我必须用 fgets 替换 scanf ,但由于我编写代码的方式,我不知道如何实现它。有什么想法吗?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void print_help(void);
int main (void)
{
float nr1, nr2, rezultat;
char operatia;
int failsafe; //failsafe
print_help(); //show help
printf("Salut! Am nevoie de un numar: "); //first number
failsafe = scanf("%f", &nr1);
if (failsafe == 1)
{
printf("Ok. Mersi!\r\n");
}
else
{
printf("bruh..");
sleep(2);
exit(-1);
}
printf("Am nevoie de inca un numar: "); //second number
failsafe = scanf("%f", &nr2);
if (failsafe == 1)
{
printf("Haha! foarte buna alegere.\r\n");
}
else
{
printf("bruh..");
sleep(2);
exit(-1);
}
printf("Bun. Ce operatie vrei sa aplic? (scrie doar unul dintre simbolurile prezentate mai sus)\n Raspunsul tau: "); //asking for the operation symbol
scanf(" %c", &operatia);
switch (operatia) //------calculare------
{
case '+':
rezultat = nr1 + nr2;
break;
case '-':
rezultat = nr1 - nr2;
break;
case '/':
if (nr2 == 0)
{
printf("nah man. im out.");
sleep(2);
exit(-2);
}
rezultat = nr1 / nr2;
break;
case '*':
rezultat = nr1 * nr2;
break;
default:
printf("bruh..");
sleep(2);
exit(-1);
}
printf("Rezultatul tau este: %.2f", rezultat); //afisare
sleep(1); //
printf("\r\nThank you and..."); //
sleep(1); //afisare rezultat
printf("Goodbye!"); //
sleep(3); //
return 0;
}
//-----------behind the scenes-----------
void print_help(void)
{
printf("-----------------------------\n\r");
printf("\tCalculator v1.2\r\n\r\n");
printf("-> simbolul pentru adunare este: + \r\n\r\n");
printf("-> simbolul pentru scadere este: - \r\n\r\n");
printf("-> simbolul pentru inmultire este: * \r\n\r\n");
printf("-> simbolul pentru impartire este: / \r\n\r\n");
printf("-----------------------------\n\r");
return;
}
根据 Weather Vane
的建议,您可以更改读取的数据类型,从而增加最大数量!
我建议阅读有关 C 数据类型的维基百科页面,以选择您最感兴趣且最适合您需求的类型!
(https://en.wikipedia.org/wiki/C_data_types)
如果您需要存储更大的数字,则需要实现自己的解决方案,例如存储 preferred_data_type
数组。
据我所知,scanf
不允许将 5 5
解析为 55
。
如果你想实现这个特性,你需要从命令行获取输入作为一个字符串,然后自己解析它:(
这是使用 getline
解析 int
s 所需行为的简单实现。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char *buffer = NULL;
char *number;
ssize_t response;
unsigned int j = 0;
size_t n = 0;
printf("> ");
response = getline(&buffer, &n, stdin);
number = calloc(1, strlen(buffer) + 1);
for (unsigned int i = 0; buffer[i]; i++) {
if (buffer[i] >= '0' && buffer[i] <= '9') {
number[j] = buffer[i];
j++;
}
}
printf("The number you entered: %d\n", atoi(number));
return 0;
}
输出:
➜ Desktop ./a.out
> 5 5
The number you entered: 55
➜ Desktop
您可以使用 fgets
将输入读取为字符串。然后,使用此字符串获取数字或任何您想要的内容。使用 scanf
无法读取整行输入,因为它从输入中逐字读取。
要删除字符串中的 space 个字符,您可以看到 Removing Spaces from a String in C。
要将字符串转换为浮点数,您可以使用 strtof
函数。查看更多 How to convert string to float?
获取输入字符串并用它做一些你想做的事情的小例子:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
void remove_spaces(char* str) {
const char* temp = str;
do {
while (*temp == ' ') {
++temp;
}
} while (*str++ = *temp++);
}
void copy_str(char *str) {
const char* temp = str;
int i = 0;
while (isdigit(*temp)) {
str[i] = *temp++;
i++;
}
str[i] = '[=10=]';
}
int main()
{
float number;
char str[30];
fgets(str, sizeof(str), stdin);
remove_spaces(str);
int len1 = strlen(str);
printf("remove_spaces: %s\n", str);
copy_str(str);
int len2 = strlen(str);
if(len1 > len2+1) {
number = strtof(str,NULL);
printf("FALSE -- number = %f\n", number);
return 0;
}
printf("copy_str: %s\n", str);
if(strlen(str) > 15) {
printf("too long\n");
return 0;
}
number = strtof(str,NULL);
printf("number = %f\n", number);
printf("Hello World");
return 0;
}
输出1:字符串内容space个字符。
55 55
remove_spaces: 5555
copy_str: 5555
number = 5555.000000
Hello World
输出2:字符串内容字母字符。
55 55c
remove_spaces: 5555c
FALSE number = 5555.000000
输出3:字符串太长。
123456789101111111
remove_spaces: 123456789101111111
copy_str: 123456789101111111
too long
所以我用 C 做了一个计算器,它可以工作,但我想消除一些错误,它与 scanf 有关。 我遇到的问题是:
- 如果我输入 5 5 ,数字 1 和数字 2 都将是 5。我可以忽略 space 并将数字作为 55 吗?
- 如果我输入 5c,它会将数字 1 读取为 5,然后它会触发故障保护(因为 'c')并关闭。
- 如果我输入一个非常大的数字,它会给出一个错误的结果。有什么方法可以限制 15 个号码吗?
我想我必须用 fgets 替换 scanf ,但由于我编写代码的方式,我不知道如何实现它。有什么想法吗?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void print_help(void);
int main (void)
{
float nr1, nr2, rezultat;
char operatia;
int failsafe; //failsafe
print_help(); //show help
printf("Salut! Am nevoie de un numar: "); //first number
failsafe = scanf("%f", &nr1);
if (failsafe == 1)
{
printf("Ok. Mersi!\r\n");
}
else
{
printf("bruh..");
sleep(2);
exit(-1);
}
printf("Am nevoie de inca un numar: "); //second number
failsafe = scanf("%f", &nr2);
if (failsafe == 1)
{
printf("Haha! foarte buna alegere.\r\n");
}
else
{
printf("bruh..");
sleep(2);
exit(-1);
}
printf("Bun. Ce operatie vrei sa aplic? (scrie doar unul dintre simbolurile prezentate mai sus)\n Raspunsul tau: "); //asking for the operation symbol
scanf(" %c", &operatia);
switch (operatia) //------calculare------
{
case '+':
rezultat = nr1 + nr2;
break;
case '-':
rezultat = nr1 - nr2;
break;
case '/':
if (nr2 == 0)
{
printf("nah man. im out.");
sleep(2);
exit(-2);
}
rezultat = nr1 / nr2;
break;
case '*':
rezultat = nr1 * nr2;
break;
default:
printf("bruh..");
sleep(2);
exit(-1);
}
printf("Rezultatul tau este: %.2f", rezultat); //afisare
sleep(1); //
printf("\r\nThank you and..."); //
sleep(1); //afisare rezultat
printf("Goodbye!"); //
sleep(3); //
return 0;
}
//-----------behind the scenes-----------
void print_help(void)
{
printf("-----------------------------\n\r");
printf("\tCalculator v1.2\r\n\r\n");
printf("-> simbolul pentru adunare este: + \r\n\r\n");
printf("-> simbolul pentru scadere este: - \r\n\r\n");
printf("-> simbolul pentru inmultire este: * \r\n\r\n");
printf("-> simbolul pentru impartire este: / \r\n\r\n");
printf("-----------------------------\n\r");
return;
}
根据 Weather Vane
的建议,您可以更改读取的数据类型,从而增加最大数量!
我建议阅读有关 C 数据类型的维基百科页面,以选择您最感兴趣且最适合您需求的类型!
(https://en.wikipedia.org/wiki/C_data_types)
如果您需要存储更大的数字,则需要实现自己的解决方案,例如存储 preferred_data_type
数组。
据我所知,scanf
不允许将 5 5
解析为 55
。
如果你想实现这个特性,你需要从命令行获取输入作为一个字符串,然后自己解析它:(
这是使用 getline
解析 int
s 所需行为的简单实现。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char *buffer = NULL;
char *number;
ssize_t response;
unsigned int j = 0;
size_t n = 0;
printf("> ");
response = getline(&buffer, &n, stdin);
number = calloc(1, strlen(buffer) + 1);
for (unsigned int i = 0; buffer[i]; i++) {
if (buffer[i] >= '0' && buffer[i] <= '9') {
number[j] = buffer[i];
j++;
}
}
printf("The number you entered: %d\n", atoi(number));
return 0;
}
输出:
➜ Desktop ./a.out
> 5 5
The number you entered: 55
➜ Desktop
您可以使用 fgets
将输入读取为字符串。然后,使用此字符串获取数字或任何您想要的内容。使用 scanf
无法读取整行输入,因为它从输入中逐字读取。
要删除字符串中的 space 个字符,您可以看到 Removing Spaces from a String in C。
要将字符串转换为浮点数,您可以使用 strtof
函数。查看更多 How to convert string to float?
获取输入字符串并用它做一些你想做的事情的小例子:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
void remove_spaces(char* str) {
const char* temp = str;
do {
while (*temp == ' ') {
++temp;
}
} while (*str++ = *temp++);
}
void copy_str(char *str) {
const char* temp = str;
int i = 0;
while (isdigit(*temp)) {
str[i] = *temp++;
i++;
}
str[i] = '[=10=]';
}
int main()
{
float number;
char str[30];
fgets(str, sizeof(str), stdin);
remove_spaces(str);
int len1 = strlen(str);
printf("remove_spaces: %s\n", str);
copy_str(str);
int len2 = strlen(str);
if(len1 > len2+1) {
number = strtof(str,NULL);
printf("FALSE -- number = %f\n", number);
return 0;
}
printf("copy_str: %s\n", str);
if(strlen(str) > 15) {
printf("too long\n");
return 0;
}
number = strtof(str,NULL);
printf("number = %f\n", number);
printf("Hello World");
return 0;
}
输出1:字符串内容space个字符。
55 55
remove_spaces: 5555
copy_str: 5555
number = 5555.000000
Hello World
输出2:字符串内容字母字符。
55 55c
remove_spaces: 5555c
FALSE number = 5555.000000
输出3:字符串太长。
123456789101111111
remove_spaces: 123456789101111111
copy_str: 123456789101111111
too long