Exercise #5 Chapter 6 of Programming in C - c

Write a program that acts as a simple "printing" calculator. The program should allow the user to type in expressions of the form: number operator. The following operators should be recognized by the program: +, -, *, /, S. E
The S operator tells the program to set the "accumulator" to the typed-in number.
The E operator tells the program that execution is to end.The arithmetic operations are performed on the contents of the accumulator with the number that was keyed in acting as the second operand.
The following is a "sample run" showing how the program should operate:
Begin Calculations
10 S Set Accumulator to 10
= 10.000000 Contents of Accumulator
2 / Divide by 2
= 5.000000 Contents of Accumulator
55 - Subtract 55
-50.000000
100.25 S Set Accumulator to 100.25
= 100.250000
4 * Multiply by 4
= 401.000000
0 E End of program
= 401.000000
End of Calculations.
Here's my code
#include <stdio.h>
int main(void)
{
char op;
float acc = 0, num;
printf("Begin Calculations\n");
while (op != 'E') {
scanf("%f %c", &num, &op);
switch (op) {
case '+':
acc += num;
printf("= %f\n", acc);
break;
case '-':
acc -= num;
printf("= %f\n", acc);
break;
case '*':
acc *= num;
printf("= %f\n", acc);
break;
case '/':
if (num == 0) {
printf("Division by zero\n");
}
else {
acc /= num;
printf("= %f\n", acc);
}
break;
case 'S':
acc = num;
printf("= %f\n", acc);
break;
case 'E':
printf("= %f\n", acc);
break;
default:
printf("Unknown operator\n");
break;
}
}
printf("End of Calculations");
}
My code work perfectly with the question input. However, when I input the following (and the output) (same input as question but without space between "number" and "operator"):
Begin Calculations
10S
= 10.000000
2/
= 5.000000
55-
-50.000000
100.25S
= 100.250000
4*
= 401.000000
0E
The program stuck when I input 0E. I have tried to change scanf("%f %c", &num, &op); to scanf("%f%c", &num, &op); but it didn't seem to solve my problem. Could you point out the problem in my code? Please give me a detail explaination because I'm relative new to C. Thank you in advance for any help you can provide.

You are reading a float value. So if scanf sees 0E, it awaits more digits as it thinks you are inputting an exponential as e.g. 0E5 (=0*10^5). That's why your program gets stuck at this point. I would suggest to use a different character to end to avoid this ambiguity.
If, on the other hand, scanf sees 0S, it will output 0.0 as float value and 'S' as character, as 'S' is never a valid part of a float value.

Related

I keep getting a segmentation fault in my C code

First off, I am relatively new to C programming, and wanted to write a program that would be able to accept user input and then pass that on to a switch/case and return output based on the initial choice. I was able to do this while using the int data type, but I would like some help doing the same while taking input as a char.
#include <stdio.h>
double x = 1;
double y = 3;
char inputLet[1];
double chooseEquation(char notLet){
char notNotLet = notLet;
printf("notLet here is: %c \n", notLet);
switch(notLet){
case 'A':
x += y;
printf("Case1 reached! \n");
break;
case '2':
x += -y;
break;
case '3':
x -= y;
break;
case '4':
x -= -y;
break;
case '5':
x *= y;
break;
case '6':
x *= -y;
break;
default :
printf("defaulting! btw: %c \n", notNotLet);
x = 0;
}
printf("x has been set? Here: %.2f\n", x);
return x;
}
int main(){
printf("Welcome, please pick a letter from A to F (uppercase for now) in order to choose an equation: \n");
scanf(" %c", &inputLet);
printf("The letter you chose is: %s \n", inputLet);
double outputLet = chooseEquation(inputLet);
printf("Your equation evaluated to: %.2f \n", outputLet);
return 0;
}
Somehow, no matter the input, the character that the switch looks at becomes Q
However, if I replace this line:
char inputLet[1];
with this line:
char inputLet;
The program segmentation faults.
Any help would be much appreciated.
printf("The letter you chose is: %s \n", inputLet);
When you use char inputLet then use %c. This is causing the error.
And also if it is a single character then just use char inputLet not a character array.
After changing it, I tested it locally and got this output for 'A'
Welcome, please pick a letter from A to F (uppercase for now) in order to choose an equation:
A
HelloThe letter you chose is: A
notLet here is: A
Case1 reached!
x has been set? Here: 4.00
Your equation evaluated to: 4.00

C: can't figure out what is causing an infinite loop

I'm a beginner, and as an exercise I have to code a very simple calculator that modifies the stack by the number and the operator the user inputs.
This is the code:
#include <stdio.h>
int main (void)
{
long double x, stack = 0;
char op;
printf("Input an operator and a number:\n");
while ( op != 'q' )
{
scanf("%Lf %c", &x, &op);
switch (op)
{
case '+':
stack += x;
printf("= %Lg", stack);
printf("\n");
break;
case '-':
stack -= x;
printf("= %Lg", stack);
printf("\n");
break;
case '*':
stack *= x;
printf("= %Lg", stack);
printf("\n");
break;
case '/':
if (x == 0)
{
printf("Can't divide by 0.");
printf("\n");
break;
}
stack /= x;
printf("= %Lg", stack);
printf("\n");
break;
case 's':
stack = x;
printf("stack set to %Lg", x);
printf("\n");
break;
case 'q':
printf("Bye!\n");
break;
default:
printf("Unknown operator.\n");
break;
}
}
printf("Bye!\n");
return 0;
}
Now the problem is that whenever x is not an number, the program keeps looping. Why?
And how could I prevent the user from inputing anything but a number for x? If x was a char I'd use isdigit(), but that's not the case.
(By the way, I want x to be a long double so I can input numbers with decimals).
scanf() will convert as many values from the string as it can. If one cannot be converted, it stops processing the string. Either way, the function returns a value indicating how many values were converted.
If the first value (x) is not a number and cannot be converted, it stops. And so the second value (op) does not change. That causes your loop to continue.
Check the value returned by scanf() to confirm this behavior yourself.
Also, "I want x to be a long double so I can input numbers with decimals" - Values of type float and double also support numbers with decimals.
Finally, as others have point out, you should initialize op at the start of your code before testing if it equals "q". This will ensure the value is what you expect it to be at that time.

Exercise #5 in Chapter 6 of Programming in C, "simple “printing” calculator"

Exercise #5 in Chapter 6 of Programming in C, by Kochan
Write a program that acts as a simple "printing" calculator. The program should allow the user to type in expressions of the form: number operator. The following operators should be recognized by the program: +, -, *, /, S. E
- The S operator tells the program to set the "accumulator" to the typed-in number.
- The E operator tells the program that execution is to end.The arithmetic operations are performed on the contents of the accumulator with the number that was keyed in acting as the second operand.
The following is a "sample run" showing how the program should operate:
Begin Calculations
10 S Set Accumulator to 10
= 10.000000 Contents of Accumulator
2 / Divide by 2
= 5.000000 Contents of Accumulator
55 - Subtract 55
-50.000000
100.25 S Set Accumulator to 100.25
= 100.250000
4 * Multiply by 4
= 401.000000
0 E End of program
= 401.000000
End of Calculations.
Make certain that the program detects division by zero and also checks for unknown operators.
If I enter * 2 it returns inf. This is what I did:
#include <stdio.h>
int main(void)
{
float number1, number2;
char operator;
do
{
printf("Enter your number with S sign that set it as your accumulator \n");
scanf("%f %c", &number1, &operator);
} while (operator != 'S');
do
{
printf("Enter your expression with the correct format\n");
scanf("%f %c", &number2, &operator);
if ( operator == '+' || operator == '-' || operator == '/' || operator == '*')
{
switch (operator)
{
case '+':
number1 = number1 + number2;
printf("=%.6f\n", number1);
break;
case '-':
number1 = number1 - number2;
printf("=%.6f\n", number1);
break;
case '*':
number1 = number1 * number2;
printf("=%.6f\n", number1);
break;
case '/':
if( number2 == 0)
printf("Division by Zero\n");
else
{
number1 = number1 / number2;
printf("%.6f\n", number1);
}
break;
default:
printf("not a valid operator\n");
break;
}
}
else
printf("Retry.\n");
} while (operator != 'E');
printf("End of Calculations\n");
return 0;
}
For the scanf("%f %c", &number2, &operator); statement, * is not a valid character for %f. The scanf fails but the do block tries again and again tries to read * into %f.
Replace the statement with
if ( ( scanf("%f %c", &number2, &operator)) != 2) {
number2 = 1.0f;
operator = 0;
scanf ( "%*[^\n]");
}
scanf will return the number of items successfully read. If scanf does not return 2, then set the values to some appropriate value and scanf ( "%*[^\n]); will read and discard everything in the buffer that is not a newline.
Do something similar for the first scan for number1

Making a Calculator

How do I make it that when I divide by 2 numbers(10/2/2) it will give me the right solution. Also how do I make it find the remainder when one number is divided by another.
How would I begin with being able to divide by 2 or more numbers? With if-else statements.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
void main()
{
char operation = 0;
double num1=0.0 ;
double num2=0.0 ;
printf("Enter the calculation\n");
scanf("%f %c %f", &num1, &operation, &num2);
switch (operation) {
case '+':
printf("= %f\n", num1 + num2);
break;
case '-':
printf("= %f\n", num1 - num2);
break;
case '*':
printf("= %f\n", num1*num2);
break;
case '/':
printf("= %f\n", num1 /(double)num2);
break;
case '%':
printf("= %f\n", num1 % (double)num2);
break;
default:
printf("Error!\n");
break;
}
system("pause");
}
To get the remainder that you're looking for, you have to cast both sides to int:
printf("= %d\n", (int)num1 % (int)num2);
To parse complex expressions, you need something completely different. Right now your code only does a single operation, and so can ignore operator precidence. But when you chain operations, you need to pay attention to that. Like 1 - 2 * 3, your code should do the 2*3 and then add in the 1. The easiest way to do this is a recursive decent parser: http://en.wikipedia.org/wiki/Recursive_descent_parser
Here are the basic/simple rule concepts:
line -> expression <EOF>
expression -> factor + expression
factor - expression
factor
factor -> term * factor
term / factor
term % factor
term
term -> ( expression )
<number>
Then the code for each of these rules these looks vaguely like this:
double read_factor(...) {
double first = read_term(...);
double second = 0.0;
switch(peek_next_symbol()) {
case '*':
consume_symbol();
second = read_term();
return first * second;
case '/':
consume_symbol();
second = read_term();
if (second == 0)
throw std::logic_error("div/0");
return first / second;
case '%':
consume_symbol();
second = read_term();
if (second == 0)
throw std::logic_error("mod/0");
return (double)((int)first % (int)second);
default:
return first;
}
}
And then term looks vaguely like this:
double read_term() {
double first = 0.0;
switch(peek_next_symbol()) {
case '(':
consume_symbol();
first = read_expression();
if (peek_next_symbol() != ')')
throw std::logic_error("missing )");
consume_symbol();
default:
return read_number();
}
}
And each of these functions I reference are all relatively complicated, and there's plenty of state being passed around. Now that I've briefly explained the theory, here's a tiny working sample: http://ideone.com/wVqRw
You can get the remainder with the % operator
case '%':
printf("= %d\n", (int)num1 %(int)num2);
break;
As for dividing the number multiple times, you will need to improve your input parsing, create a loop to do multiple operations and save the results (to possibly num1).
Remainder and modulo are similar though often subtly different.
In C, % is the remainder after division. In C, modulo is not defined for integers.
fmod() exists for FP numbers and it is also "floating-point remainder of x/y."
To get a floating point "remainder operator", code could use
case '%':
{
printf("= %f\n", fmod(num1, num2));
break;
}
In mathematics, the result of the modulo operation is often defined as the remainder of Euclidean division. If code wanted to do a Euclidean division to get the modulo:
case 'M':
{
double quot = floor(num1/num2);
double rem = num1 - quot * num2;
printf("= %f\n", rem);
break;
}
Note: Suggest using "%g" or "%e" for printing.

Can the argument for Switch statement have an expression to eliminate a variable used for comparison? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This program simulates a simple menu driven calculator with +, -, *, and / operations
#include <stdio.h>
#include <conio.h>
int main()
{
float a = 0, b = 0;
printf(" Enter two numbers: ");
scanf(" %f %f",&a ,&b);
puts(" Enter choice number of operation: ");
puts(" 1)Addition ");
puts(" 2)Subtraction ");
puts(" 3)Multiplication ");
puts(" 4)Division ");
flushall(); //To clear the trailing '\n'
switch( getchar() - 48 )
{
case 1: printf("The Sum of %.2f and %.2f is : %.2f",a,b,(a+b));
break;
case 2: printf("The Difference of %.2f and %.2f is : %.2f",a,b,(a-b));
break;
case 3: printf("The Product of %.2f and %.2f is : %.2f",a,b,(a*b));
break;
case 4: if ( b != 0 ) printf("The Quotient of %.2f and %.2f is : %.2f",a,b,(a/b));
else puts("Error, divide by zero not possible.");
break;
default: puts("Error, Invalid choice");
}
return 0;
}
Is it better this way? As I have avoided the usage of a variable, and equivalently described why the program crashes when the last input is not a valid choice, I don't think there is any need to add info about what was entered. It adds an extra variable into the picture.
Yes, switch statement can take an expression for the value on which you switch. Your code should work fine, except that getchar() would read the leftover '\n' character from scanf of the operands.
Add another call to getchar() before the switch to read and discard that extra character.
While the code is valid and correct, I'd do the following to make it more readable:
switch(getchar()) {
case '1': // ...
case '2': // ...
case '3': // ...
case '4': // ...
}
Or
switch(getchar() - '0') {
case 1: // ...
case 2: // ...
}
This is to avoid using the magic number 48, which may not be understood easily by readers.
Furthermore, you can discard input until the next \n using a simple while loop:
while(getchar() != '\n') ;
In addition to the \n, this will also read and discard anything before the newline.
switch ( expression )
So you have a valid expression and you can have a expression like you have if you really have a need for something like this.
Else
char ch = getchar(); /* or scanf(" %c",&ch); (Better)*/
int a = ch - '0';
switch(a)
{
}
For your answer : Yes the switch can accept an expression in its arguments but it should returns only one of these types char int short long int long long int it can be also signed or unsigned !
There is no need to make a cast for the expression getchar() - 48 because getchar() returns int and 48 is an int so th result would be an int
now after compiling you have to add 3 number one for the variable a and the second for the variable b and the third for the switch statement... for instance
$./executable_file
Enter two numbers: 1 2 3
Switch formatting
This is a suggested formatting of your switch statement. I disagree with the idea of using getchar() in the switch statement (though it is technically legal, it is simply a bad idea in practice), so I've replaced that with c:
int c;
/* c is set by some input operation.
** It might be char c; if you read its value with scanf(), but it must be int if you use getchar()
*/
switch (c)
{
case 1:
printf("The Sum of %.2f and %.2f is : %.2f", a, b, (a+b));
break;
case 2:
printf("The Difference of %.2f and %.2f is : %.2f", a, b, (a-b));
break;
case 3:
printf("The Product of %.2f and %.2f is : %.2f", a, b, (a*b));
break;
case 4:
if (b != 0)
printf("The Quotient of %.2f and %.2f is : %.2f",a, b, (a/b));
else
fputs("Error, divide by zero not possible.\n", stderr);
break;
default:
fprintf(stderr, "Error, Invalid choice %c\n", c);
break;
}
Note the use of break; after the default: label too; it protects you against future additions to the code and is completely uniform. (The default: label does not have to be last, though that is the conventional place for it to go.) Commas get a space after them; so do if, for, while, switch, but function calls do not get a space between the name and the open parenthesis. You don't normally need a space after an open parenthesis or before a close parenthesis. Errors are reported to standard error.
Personally, I like the actions of the switch to be indented just one level, not two levels, so I'd use:
switch (c)
{
case 1:
printf("The Sum of %.2f and %.2f is : %.2f", a, b, (a+b));
break;
case 2:
printf("The Difference of %.2f and %.2f is : %.2f", a, b, (a-b));
break;
case 3:
printf("The Product of %.2f and %.2f is : %.2f", a, b, (a*b));
break;
case 4:
if (b != 0)
printf("The Quotient of %.2f and %.2f is : %.2f",a, b, (a/b));
else
fputs("Error, divide by zero not possible.\n", stderr);
break;
default:
fprintf(stderr, "Error, Invalid choice %c\n", c);
break;
}
Many people disagree, so you're certainly not under an obligation to do that.

Resources