1
\$\begingroup\$

I wrote this simple calculator and I want to know if there is any problems in it or if there is any way to enhance the code and make it simpler and easier and I also want to know if I'm starting to get into the intermediate level instead of beginners level and thank you

#include<stdio.h>

void main()

{
int mode, n1, n2;
float num1, num2, rslt;
char op;

puts("a simple calculator");
printf("enter the first number : ");
scanf("%f", &num1);
printf("which operation you want '+ - / * or mode' : ");
scanf(" %c", &op);
printf("enter the second number : ");
scanf("%f", &num2);

switch(op)
    {
    case '+' :
        rslt = num1 + num2;
        printf("\n %f + %f = %.3f\n\n", num1, num2, rslt);
        break;
    case '-' :
        rslt = num1 - num2;
        printf("\n %f - %f = %.3f\n\n", num1, num2, rslt);
        break;
    case '*' :
        rslt = num1 * num2;
        printf("\n%f * %f = %.3f\n\n", num1, num2, rslt);
        break;
    case '/' :
        rslt = num1 / num2;
        printf("\n%f / %f = %.3f\n\n", num1, num2, rslt);
        break;
    case '%' :
        n1 = num1;
        n2 = num2;
     
        switch(n1%n2)
            {
            case 0 :
                printf("\n%d can be devided by %d\n\n", n1, n2);
                break;
            case 1 :
                printf("\n%d can not be devided by %d\n\n", n1, n2);
                break;
            }
        break;  
    default :
        printf("\ninvalid input\n\n");
    }
}   
\$\endgroup\$

3 Answers 3

2
\$\begingroup\$

Your code is OK, for a beginner, so please don't worry too much about these comments. I bet you program is fine until you enter the data "break me". The reason I can list these points so easily, is because I've done them more times than I care to think of, and I've probably done some of them today. Code Review is always a case of do what I say, not what I do. I hope that helps, if there is anything that isn't clear please say and I will try and make it clearer.

  1. Your code lacks comments. There are all sorts of wise people who say you should have x% comments in your code, but all you need to do is to explain what your code does. Sound stupid, but when you look at this in a years time, you will know what I mean.
  2. Variable names should be descriptive, it means you don't need to write so many comments. n1, n2, num1, num2 and op are all examples of variable names I think could be more descriptive/precise. You shouldn't have to think when you read code, firstNumber and secondNumber are easier to understand than n1 and n2.
  3. Initialise variables unless you are 100% certain you don't need to. rslt is not initialised when op is % or default. This could cause a crash or at least garbage data. Also check what happens if scanf fails (can it fail?), is the output parameter set to a certain safe value?
  4. Only declare a single variable per line. It makes it easier to check what has been initialised and what hasn't and to change types.
  5. why did you use puts() and the printf()? Why not just printf() to make the code more uniform?
  6. The printf statements inside the switch statements could be moved to the end to 'refactor' you code slightly.
  7. Putting a switch inside a switch increases the complexity of the code massively. In this case it might be better to replace the whole block with:

.

{
  int n1 = (static_cast<int>(num1); 
  int n2 = (static_cast<int>(num2);   
  printf("\n%d can %sbe divided by %d\n\n", n1, ((n1%n2)?"":"not"), n2); 
}

EDIT To move the printf outside of the switch, you just need to place the opcode in the general string using the variable you already have op:

printf("\n%f / %f %c %.3f\n\n", num1, num2, op, rslt);

The problem is with the % and default branches of the switch, but you can just use return after their printfs to skip the general one.

\$\endgroup\$
1
  • \$\begingroup\$ @cede gorilla thank you very much for your time in the tip number 6 you mentioned to move the printf outside of the switch , I really don't know how to do that , because in each case there if a different operation '* - / %', and I also didn't understand any of the example that you gave me in tip number 7 and thanks again \$\endgroup\$
    – UnderScore
    Commented Jan 5, 2022 at 13:15
1
\$\begingroup\$

regarding:

void main()

results in: untitled.c:3:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]

There are also 3 other compiler warnings:

gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" -o "untitled.o"

results in:

untitled.c:3:6: warning: return type of ‘main’ is not ‘int’   [-Wmain]
3 | void main()
  |      ^~~~

untitled.c: In function ‘main’:

untitled.c:37:14: warning: conversion from ‘float’ to ‘int’ may change value [-Wfloat-conversion]

37 | n1 = num1; | ^~~~

untitled.c:38:14: warning: conversion from ‘float’ to ‘int’ may change value [-Wfloat-conversion]

38 | n2 = num2; | ^~~~

untitled.c:6:5: warning: unused variable ‘mode’ [-Wunused-variable]
6 | int mode, n1, n2;
  |     ^~~~
\$\endgroup\$
5
  • \$\begingroup\$ @user36292449 thank you for your help I didn't get any of the errors and about return type of main is not error I think I already typed "void main()" isn't that for not returning any thing or I should type int main void and in the end of my program I type return 0; \$\endgroup\$
    – UnderScore
    Commented Jan 5, 2022 at 13:21
  • 2
    \$\begingroup\$ @UnderScore It will help you learn if you crank the warnings up to full when you compile, but it might be worth doing it in stages, because 1000+ warnings can be quite disheartening :) \$\endgroup\$ Commented Jan 6, 2022 at 8:10
  • \$\begingroup\$ I thought I let that until I start learning about debuggers \$\endgroup\$
    – UnderScore
    Commented Jan 6, 2022 at 13:33
  • 1
    \$\begingroup\$ if the 'main()' function does not have a 'return value' statement,, then (modern) C creates a 'return 0;' statement. BTW: is is very risky to have warnings because that means the compiler made a 'best guess' about what you actually wanted.. That 'best guess' may or may not be what you intended \$\endgroup\$ Commented Jan 7, 2022 at 7:05
  • \$\begingroup\$ thank you I appreciate your help \$\endgroup\$
    – UnderScore
    Commented Jan 11, 2022 at 13:16
1
\$\begingroup\$

Use floating point

Rather than convert to int and risk problems when the float value is outside the int range, use fmodf() via <math.h>.

case '%' :
    rslt = fmodf(num1, num2);  
    printf("\n%f % %f = %.3f\n\n", num1, num2, rslt);  
    break;      
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.