Simple calculator

  • C/++/#
  • Thread starter Arman777
  • Start date
  • #1
1,730
138

Main Question or Discussion Point

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 couldnt 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 doesnt go further ?
 

Answers and Replies

  • #2
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
What did you input for the operation?
 
  • #3
1,730
138
What did you input for the operation?
Nothing I cannot put it, it prints the statement and code stops.
 
  • #4
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
What happens if you put "23+" in the previous input?

Edit: Note that there should be no space in between 23 and +
 
  • #5
1,730
138
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.
 
  • #6
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
It works yeah, but why ?
What do you think?
Hint: Consider what is in the stdin stream.
 
  • #7
1,730
138
Okay I fixed it ..
Code:
 scanf("\n%c",&s);
Thanks.
 
  • #8
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
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.
 
  • #9
Ibix
Science Advisor
Insights Author
5,951
4,519
...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
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
...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.
 
  • #11
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
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
1,730
138
We didnt learn switch or case things. But it seems much cooler and nice.
 
  • #13
1,730
138
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
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
Did you perhaps get any warnings when you tried to compile that?
 
  • #15
1,730
138
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
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
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).
 
  • #17
1,730
138
Thanks a lot I was using online compiler maybe thats why, Idk.
 
  • #18
33,262
4,963
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
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
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
jim mcnamara
Mentor
3,782
2,104
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
Orodruin
Staff Emeritus
Science Advisor
Homework Helper
Insights Author
Gold Member
16,666
6,444
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.
 

Related Threads on Simple calculator

Replies
8
Views
2K
Replies
1
Views
2K
Replies
6
Views
3K
Replies
8
Views
3K
Top