Simple Calculator: Solve Math Problems Easily

  • Context:
  • Thread starter Thread starter Arman777
  • Start date Start date
  • Tags Tags
    Calculator
Click For Summary

Discussion Overview

The discussion revolves around a simple calculator program written in C, focusing on issues related to input handling, operator recognition, and type conversions between integers and floating-point numbers. Participants explore the behavior of the program, particularly how input is processed and the implications of using different data types.

Discussion Character

  • Technical explanation
  • Conceptual clarification
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant reports that their calculator program stops after prompting for an operation symbol, indicating a potential issue with input handling.
  • Another participant suggests that the input for the operation might not have been provided correctly, leading to the program's halt.
  • It is noted that entering "23+" as the second number allows the program to function, raising questions about input parsing.
  • A hint is provided regarding the contents of the stdin stream, suggesting that line breaks may affect input reading.
  • One participant proposes a fix by changing the scanf format to read the operation symbol, which resolves the issue.
  • Another participant discusses the advantages of using a switch statement over multiple if statements for better error handling and clarity in the code.
  • A participant expresses interest in converting the program to handle decimal calculations but encounters issues with scanf and data types.
  • Concerns are raised about the relationship between data types (int, float, double) and their corresponding format specifiers in scanf, particularly regarding the use of %f and %lf.
  • Clarifications are provided about the consequences of mismatched data types in memory and the importance of using the correct format specifiers.

Areas of Agreement / Disagreement

Participants generally agree on the issues related to input handling and type conversions, but there are varying opinions on the best practices for structuring the code and handling errors. The discussion remains unresolved regarding the optimal approach to implementing the calculator functionality.

Contextual Notes

Limitations include the potential misunderstanding of how scanf interacts with different data types and the implications of using incorrect format specifiers. The discussion does not resolve the nuances of input parsing and error handling in C programming.

Arman777
Insights Author
Gold Member
Messages
2,163
Reaction score
191
Code:
# include <stdio.h>

int main()

{
    int n1,n2;
    char s;
    printf("Enter the first number:");
    scanf("%d",&n1);
    printf("Enter the second number:");
    scanf("%d",&n2);
    printf("Type the operation symbol that you want to do:");
    scanf("%c",&s);
    printf("%c",s);
    if (s == '+'){
        printf("The sum is %d",n1+n2);
    }
    if (s == '-'){
        printf("The sub is %d",n1-n2);
    }
    if (s == '/'){
        printf("The div is %d",n1/n2);
    }
    if (s == '*'){
        printf("The mul is %d",n1*n2);
    }
    return 0;
}

This is not working and I couldn't figure out why ..
Code:
Enter the first number:12
Enter the second number:23
Type the operation symbol that you want to do:

Process returned 0 (0x0)   execution time : 1.976 s
Press any key to continue.

It stops here. Anyone can see why it doesn't go further ?
 
Technology news on Phys.org
What did you input for the operation?
 
Orodruin said:
What did you input for the operation?
Nothing I cannot put it, it prints the statement and code stops.
 
What happens if you put "23+" in the previous input?

Edit: Note that there should be no space in between 23 and +
 
Orodruin said:
What happens if you put "23+" in the previous input?

Edit: Note that there should be no space in between 23 and +
It works yeah, but why ?
Now it looks like this. But I edited a bit my code
Code:
Enter the first number:12
Enter the second number:23+
Type the operation symbol that you want to do:
The sum is 35
Process returned 0 (0x0)   execution time : 4.444 s
Press any key to continue.
 
Arman777 said:
It works yeah, but why ?
What do you think?
Hint: Consider what is in the stdin stream.
 
Okay I fixed it ..
Code:
 scanf("\n%c",&s);
Thanks.
 
Right. Your stdin input was "12\n23\n" so after reading the number 12 you asked it to read another number, which becomes 23 from "\n23", leaving you with "\n". So when you asked it to read another character, the current buffer in stdin had enough characters (one) to let you do that. That character was a line break and none of your operators. Hence, none of the if statements were true and your program returned zero as it should.
 
  • Like
Likes   Reactions: jim mcnamara, Arman777 and Ibix
...which, incidentally, is an excellent example of why it's usually (always?) a bad idea to write
C:
if(something) {
}
if(something_else) {
}
if the language will let you write
C:
if(something) {
} else if(something_else) {
} else {
    printf("Helpful error message");
}
In this case, the error message would be something like "Unrecognised operator %c", with s supplied as the character. Then you immediately have a clue what went wrong.
 
  • #10
Ibix said:
...which, incidentally, is an excellent reason to never write
C:
if(something) {
}
if(something_else) {
}
if the language will let you write
C:
if(something) {
} else if(something_else) {
} else {
    printf("Helpful error message");
}
In this case, the error message would be something like "Unrecognised operator %c", with s supplied as the character.
Also, it is good to end your printf statements with a line break to avoid nasty output ... In this case, I would use the error message:
C:
printf("The operation in your input was %c and is not a standard operation.\n",s);
which would produce the output
Code:
The operation in your input was 
 and is not a standard operation.
 
  • Like
Likes   Reactions: Ibix
  • #11
Also, this particular code would do better as a switch statement than a multiple if-else if-else:
C:
int main(){
    int n1,n2;
    char s;
    printf("Enter the first number: ");
    scanf("%d",&n1);
    printf("Enter the second number: ");
    scanf("%d",&n2);
    printf("Type the operation symbol that you want to do: ");
    scanf("\n%c",&s);
    switch (s) {
        case '+':
            printf("The sum is %d\n",n1+n2);
            return 0;
        case '-':
            printf("The sub is %d\n",n1-n2);
            return 0;
        case '*':
            printf("The mul is %d\n",n1*n2);
            return 0;
        case '/':
            printf("The div is %d\n",n1/n2);
            return 0;
        default:
            printf("The operation in your input was %c and is not a standard operation.\n",s);
            return 1;
    }
}
 
  • #12
We didnt learn switch or case things. But it seems much cooler and nice.
 
  • #13
I am trying to turn it into the decimal calculations I made it by turning the int to float and every %d to %f.

but when I define function as double I cannot do any proper calculation. Like for example
Code:
#include <stdio.h>

int main()
{
    double n,n1,n2;
    scanf("%f",&n1);
    scanf("%f",&n2);
    n = n1/n2;
    printf("%f",n);
    return 0;
}

For example I tried most of the things but cannot seem to work this out. I am thinking that we are using %d only for integers %f for only float numbers but when I convert %d to %f nothing happens.

Like If I run this code and say n1 = 12 and n2 = 2 I get 131061 ... smthing like that.
 
Last edited:
  • #14
Did you perhaps get any warnings when you tried to compile that?
 
  • #15
Orodruin said:
Did you perhaps get any warnings when you tried to compile that?
Nope I get no warning. I didnt quite understand the relationship between float/int/double and %d/%f .

For floats we can use %f in all cases and works, for int we use %d. what about doubles ? appereantly %f does not work.
 
  • #16
Arman777 said:
Nope I get no warning. I didnt quite understand the relationship between float/int/double and %d/%f .

For floats we can use %f in all cases and works, for int we use %d. what about doubles ? appereantly %f does not work.
It is strange that your compiler does not warn you about this. You are passing a double pointer when the scanf function should be expecting a float pointer. My gcc compiler gives this for your code
Code:
>>gcc test.c 
test.c:14:16: warning: format specifies type 'float *' but the argument has type
      'double *' [-Wformat]
    scanf("%f",&n1);
          ~~  ^~~
          %lf
test.c:15:16: warning: format specifies type 'float *' but the argument has type
      'double *' [-Wformat]
    scanf("%f",&n2);
          ~~  ^~~
          %lf
2 warnings generated.
int, double, and float are all different ways of storing numbers in your computer's memory. For example, an int is a way of representing an integer in your computer's memory with a specific pattern meaning a particular integer. In the same way, double and float are two different ways of representing floating point numbers. The double data type uses twice the memory of a float (hence double) and generally will therefore give you more precision. However, floats are sufficient for what you are doing here. When you tell scanf to read something, you need to give it a pointer to where in the computer's memory it should be storing the result. This is why you are putting the & in the argument - this is a reference operator so &n literally means "the place in memory where n is stored".

So, what you are asking scanf to do is to write down a float in the position where n1 is stored. But doubles and floats are different ways of storing floating point numbers and if you pass the address of a memory position where a double is stored to a function that is going to write a float there, the following will happen:
  • Only the first half of the memory will be changed since a float is half the size of a double. Whatever was in the last part of the memory representing the double will remain there.
  • The pattern of 0s and 1s representing your float will typically mean something entirely different as a double. Add this on top of the non-writing to the latter part of the double.
  • Taken together, the final result in the memory representing a double cannot be expected to represent anything similar to the number that its first half would represent as a float.
Your options are:
  • Use floats: Your intended usage probably does not need double precision.
  • Use doubles: You then need to specify to scanf that you want to read a double, not a float. The specifier for reading a double is "%lf" (long float).
 
  • Like
Likes   Reactions: jim mcnamara and Arman777
  • #17
Thanks a lot I was using online compiler maybe that's why, Idk.
 
  • #18
It's always the case in C programs that if you use scanf() to input a number, and then afterwards use scanf() to input a character, the input to the character variable will be the newline character that results from pressing Enter after you have typed the digits of the number.

Some alternatives to scanf("\n%c",&s); that @Orodruin suggested, these will work:

C:
scanf("%d", &n2);
getchar();           // Reads and discards the newline character
printf("Type the operation symbol that you want to do:");
scanf("%c", &s);
or
C:
scanf("%d", &n2);
fflush(stdin);           // Flushes the stdin input buffer
printf("Type the operation symbol that you want to do:");
scanf("%c", &s);

BTW, s is not a good name for a variable that should hold a character. A better choice would be op or opChar or some other name that suggests that it holds an operator (like +, -, etc.) that is a single character.
 
  • #19
Mark44 said:
Some alternatives to scanf("\n%c",&s); that @Orodruin suggested, these will work
To be fair, the OP figured this out by himself (post #7). I just guided him to the issue.
 
  • #20
My heart sinks when I see beginners using code they got in class that abuses scanf and other C standard library calls.

FWIW. scanf is very hard to use in code safely and correctly. For reasons I do not get, teachers and some texts for beginning C classes use scanf in example code. Not completely correct code.

For example, scanf has a return code. No code posted here recognizes that. Is there checking for overflow or other conditions? Seems not.

To be fair, if you are just writing code to solve Physics/Engineering problems for yourself and you do not market the code or put it in a textbook - go for it. Just know better when it counts.

I'm not faulting the posters, they are going with the flow. But if you write code that is subject to undefined behavior, as this code is, it can misbehave and give wrong answers. In Linux gcc-compiled code, the result for buffer overflow is usually a segfault. Which is mostly annoying more than anything. Other common problems with scanf mess up numbers by not actually reading and converting number text for you. You already saw that.

This is the man page for Linux C scanf - check out the examples on how to use it correctly on Linux and POSIX systems:
http://man7.org/linux/man-pages/man3/scanf.3.html

PS: compile with warnings and fix any problems so you get no warnings.
Code:
gcc -Wall mycode.c -o mycode
-Wall turns on all warnings. Good idea.
 
  • #21
jim mcnamara said:
FWIW. scanf is very hard to use in code safely and correctly. For reasons I do not get, teachers and some texts for beginning C classes use scanf in example code. Not completely correct code.
I think it is very easy to see the appeal to be honest. Beginner programmers are likely to want to make interactive programs that do something based on input to get a feeling that they are "doing something". Use (or misuse) of scanf becomes a shortcut to enabling this and handling the return of scanf is likely to be secondary to what the examples are intended to do or demonstrate, i.e., it is not the input itself that is of interest for the example, but what you do with it later.
 

Similar threads

Replies
7
Views
2K
  • · Replies 9 ·
Replies
9
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K
Replies
14
Views
4K
  • · Replies 6 ·
Replies
6
Views
6K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 4 ·
Replies
4
Views
1K
  • · Replies 3 ·
Replies
3
Views
2K
Replies
4
Views
3K
Replies
47
Views
5K