I hope you are having a nice day. Thank you for taking the time to read my question.
I am still a beginner in the C language. My professor has asked me to program a scientific calculator. The calculator should be able to read and store user-defined variables and work with them. for example, I should be able to enter a=5 b=9
etc. after that the program should calculate, for instance, a 1= 6
, or a b=14
and show it to the user. Of course, the user decides if the operation is addition, subtraction, division or multiplication.
The user should also be able to enter such input: e.g. c=5 9
.
I have started working on the calculator, unfortunately, I have just been able to only allow the user to define one variable at a time and work with it.
For example:
a=7
7 a=14
That's all I could do. I asked my professor for help and he keeps telling me that I have to to teach the program how to separate between what is before the "=" and what's after it. Thank you in advance for every help or piece of advice you give This is the code I came up with
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main() {
char situation;
float operand1, operand2;
char i = 0;
char ch;
char op;
int operand = 0;
int j, digit, number[10] = {};
int j2 = 0;
char str[100] = { 0 };
while (1) {
printf("\n\na) To calculate choose me :)");
printf("\n\nb) If you want to calculate with variables, choose me:");
printf("\n\nc) To Exit choose me :(\n\n");
scanf_s("%c", &situation, 1);
while ((getchar()) != '\n');
switch (situation) {
case 'a':
printf("type in some arithmetic terms : \n");
scanf_s("%f", &operand1);
scanf_s("%c", &op, 1);
scanf_s("%f", &operand2);
while ((getchar()) != '\n');
switch (op) {
case ' ':
printf("\n\n%.2f %.2f = %.2f\n\n", operand1, operand2, operand1 operand2);
break;
case '-':
printf("\n\n%.2f - %.2f = %.2f\n\n", operand1, operand2, operand1 - operand2);
break;
case '*':
printf("\n\n%.2f * %.2f = %.2f\n\n", operand1, operand2, operand1 * operand2);
break;
case '/':
printf("\n\n%.2f / %.2f = %.2f\n\n", operand1, operand2, operand1 / operand2);
break;
default:
printf("\n\nERROR!\n\n");
}
break;
case 'b':
printf("\n\nTo return to the main menu please enter any capital letter of your choosing\n\n");
printf("\n\nWhen calculating with a variable, please always write the variable on the right side, Thank you. You may start:\n\n");
do {
scanf_s("%s", &str, 99);
for (i = 0; i < 100; i ) {
if (str[i] == '=') {
for (j = 0; j < strlen(str); j ) {
ch = str[j];
if (ch >= '0' && ch <= '9') {
digit = ch - '0';
number[j2] = j2 * 10 digit;
//printf("%d", number);
}
}
scanf_s("%d", &operand);
scanf_s("%c", &op, 1);
scanf_s("%d", &number[j2]);
while ((getchar()) != '\n');
switch (op) {
case ' ':
printf("\n\n%d %c = %d\n\n", operand, str[0], operand number[j2]);
break;
case '-':
printf("\n\n % d - % c = % d\n\n", operand, str[0], operand - number[j2]);
break;
case '*':
printf("\n\n % d * % c = % d\n\n", operand, str[0], operand * number[j2]);
break;
case '/':
printf("\n\n % d / % c = % d\n\n", operand, str[0], operand / number[j2]);
break;
default:
printf("\n\nERROR!\n\n");
}
break;
}
}
} while (islower(str[0]));
while ((getchar()) != '\n');
break;
case 'c':
printf("\n\goodbye\n\n");
exit(0);
break;
default:
printf("\n\nThis is not an acceptable input. Please Try again!");
}
}
}
CodePudding user response:
There are multiple problems in your code:
int number[10] = {};
is an invalid initializer in C. You should write:int j, digit, number[10] = { 0 };
you should use
double
instead offloat
scanf_s("%c", &situation, 1);
is not portable: the Microsoft version of this function expects the size argument1
as anUNSIGNED
whereas the optional Standard C function defined in Annex K specifies that the size argument1
must be passed as asize_t
, hence as(size_t)1
. Avoid using this function and read user input as a line withfgets()
and use the standard functionsscanf()
instead and do test the return value to detect and report invalid and/or missing input.Add these lines before including
<stdio.h>
at the top of your source file to prevent compiler warnings:#ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif
scanf_s("%c", &op, 1);
does not skip white space, such as spaces and newlines. You should writescanf(" %c", &op);
while ((getchar()) != '\n');
is risky: this loop will run forever if the end of file occurs before a newline can be read.instead of
j < strlen(str)
, which may rescan the string at every iteration, you should write:for (j = 0; str[j] != '\0'; j )
i
is used as an index, it should have typeint
orsize_t
, notchar
.the format string in
printf("\n\n % d - % c = % d\n\n", ...);
is incorrect: the space between the%
and thec
is not supported. You probably meant to write this anyway:printf("\n\n%d - %c = %d\n\n", operand, str[0], operand - number[j2]);
printf("\n\goodbye\n\n");
is incorrect:\g
is an invalid escape sequence. You should write:printf("\n\nGoodbye\n\n");
Here is a modified version using functions to parse the line and handle variable assignment separately from evaluating expressions:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 26 global variables */
double variables['z' - 'a' 1];
void skip_spaces(const char *str, int *pos) {
while (isspace((unsigned char)str[*pos]))
*pos = 1;
}
void trim_spaces(char *str, int *pos) {
int len = strlen(str);
while (len > *pos && isspace((unsigned char)str[len - 1]))
str[--len] = '\0';
skip_spaces(str, pos);
}
int parse_operand(char *str, int *pos, double *value) {
char *endp;
skip_spaces(str, pos);
char ch = str[*pos];
if (ch >= 'a' && ch <= 'z') {
*value = variables[ch - 'a'];
*pos = 1;
skip_spaces(str, pos);
return 1; // variable
}
*value = strtod(str *pos, &endp);
if (endp > str *pos) {
*pos = endp - str;
skip_spaces(str, pos);
return 2; // number
}
return 0;
}
/* parse an expression with basic operators, no precedence */
int parse_expression(char *str, int *pos, double *result) {
double operand2;
char op;
if (!parse_operand(str, pos, result)) {
printf("missing operand: %s\n", str *pos);
return 0;
}
while ((op = str[*pos]) == ' ' || op == '-' || op == '*' || op == '/' || op == '%') {
*pos = 1;
if (!parse_operand(str, pos, &operand2)) {
printf("missing operand: %s\n", str *pos);
return 0;
}
switch (op) {
case ' ':
*result = operand2;
break;
case '-':
*result -= operand2;
break;
case '*':
*result *= operand2;
break;
case '/':
*result /= operand2;
break;
case '%':
*result = fmod(*result, operand2);
break;
}
}
return 1;
}
int main() {
char str[100];
printf("type some expressions:\n");
while (fgets(str, sizeof str, stdin)) {
double result, result2;
int pos = 0;
trim_spaces(str, &pos);
if (!str[pos]) {
/* stop on empty line */
break;
}
/* test for a variable assignment */
if (str[pos] >= 'a' && str[pos] <= 'z' && str[pos 1] == '=') {
/* variable assignment */
int v = str[pos] - 'a';
pos = 2;
if (parse_expression(str, &pos, &result) && !str[pos]) {
variables[v] = result;
printf("%s -> %.2f\n", str, result);
} else {
printf("invalid expression: %s\n", str);
}
} else {
/* other expression */
if (parse_expression(str, &pos, &result)) {
skip_spaces(str, &pos);
if (str[pos] == '\0') {
printf("%s -> %.2f\n", str, result);
} else
if (str[pos] == '=') {
/* comparison of expressions */
pos = 1;
if (parse_expression(str, &pos, &result2) && !str[pos]) {
if (result == result2) {
printf("%s -> true (%.2f == %.2f)\n", str, result, result2);
} else {
printf("%s -> false (%f != %f, delta: %e)\n",
str, result, result2, result2 - result);
}
} else {
printf("invalid expression: %s\n", str);
}
} else {
printf("invalid syntax: %s\n", str);
}
}
}
}
return 0;
}
Output:
b=2/3
b=2/3 -> 0.67
2/3=b
2/3=b -> true (0.67 == 0.67)
20/3=10*b
20/3=10*b -> false (6.666667 != 6.666667, delta: -8.881784e-16)