我用 C 做了一个计算器,但我想修复一些关于 scanf 的错误

I made a calculator in C, but i want to fix some bugs regarding scanf

所以我用 C 做了一个计算器,它可以工作,但我想消除一些错误,它与 scanf 有关。 我遇到的问题是:

  1. 如果我输入 5 5 ,数字 1 和数字 2 都将是 5。我可以忽略 space 并将数字作为 55 吗?
  2. 如果我输入 5c,它会将数字 1 读取为 5,然后它会触发故障保护(因为 'c')并关闭。
  3. 如果我输入一个非常大的数字,它会给出一个错误的结果。有什么方法可以限制 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 解析 ints 所需行为的简单实现。

#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