2

So i made a calculator in C and it works, but i want to get rid of some bugs and it has to do with scanf. The problems i encountered are:

  1. if i enter 5 5 , both number 1 and number 2 will be 5. Any way i can ignore the space and take the number as 55?
  2. if i enter 5c, it will read number 1 as 5 then it will trigger the failsafe (because of the 'c') and close.
  3. if i enter a very large number, it will give a false result. Any way i can make a limit of 15 numbers?

I think i have to replace scanf with fgets , but i dont know how to implement this because of how i wrote my code. Any ideas?

#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;
}
HyperOni
  • 81
  • 5
  • 2
    It would be better to use `double` instead of `float`, and change `scanf("%f", &nr1);` to `scanf("%lf", &nr1);` If you want to read `"5 5"` as `"55"` you'll have to process the input yourself. – Weather Vane Apr 30 '20 at 14:43
  • Why would it be better to use ```double``` instead of ```float```? Is the precision and more memory worth for such an example like this? – Gerhard Stein May 09 '20 at 05:56

2 Answers2

2

As suggested by Weather Vane you can change the data type read and therefore increase the maximum number!

I suggest reading the Wikipedia page on C data type to pick the type you're most interested in and which fits your needs the most! (https://en.wikipedia.org/wiki/C_data_types) If you need to store even bigger numbers you will need to implemented your own solution like storing an array of preferred_data_type for example.

To my knowledge, scanf doesn't allow parsing 5 5 as 55. If you wish to implement this feature you will need to fetch the input from the command line as a string and then parse it yourself :(

This is a simple implementation of the desired behaviour using getline for parsing 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;
}

Outputs:

➜  Desktop ./a.out
> 5 5     
The number you entered: 55
➜  Desktop 
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Diego ROJAS
  • 509
  • 1
  • 7
  • 14
2

You can use fgets to read the input as the string. Then, get the number or whatever you want with this string. Using scanf can not read whole the line of input because it read word by word from the input.

For removing space character in string you can see Removing Spaces from a String in C.

For converting the string to float you can use strtof function. See more at How to convert string to float?

The small example for you to get input string and do something you want with it:

#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] = '\0';
}

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;
}

The output 1: string contents space character.

55 55                                                                                                                     
remove_spaces: 5555                                                                                                       

copy_str: 5555                                                                                                            
number = 5555.000000                                                                                                      
Hello World 

The output 2: string contents alpha character.

55 55c                                                                                                                  
remove_spaces: 5555c                                                                                                    

FALSE number = 5555.000000 

The output 3: string is too long.

123456789101111111                                                                                                      
remove_spaces: 123456789101111111                                                                                       

copy_str: 123456789101111111                                                                                            
too long
Hitokiri
  • 3,607
  • 1
  • 9
  • 29