How can I take several figures as once from my terminal - c

I'm trying to take several figures from my terminal to make my calculator work correctly. I would have to take every figures before a space : eg. 160 + 23 I have to get 160 for my first variable, "+" for my second one and 23 for my last one.
Here is the code :
`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER 25
void calculatrice(double,char,double);
int main(){
char *str;
printf("************************************************\n");
printf("ecrire sous la forme x + y avec les espaces pour avoir un resultat\n");
printf("quit pour quitter\n");
printf("************************************************\n");
char *text = calloc(1,1), buffer[BUFFER];
while( fgets(buffer, BUFFER , stdin)){
if (!strncmp(buffer, "quit",strlen("quit"))){
break;
}
if (!strncmp(buffer, "flush",strlen("flush"))){
system("clear");
}
text = realloc( text, strlen(text)+1+strlen(buffer) );
if( !text ){
strcat( text, buffer);
printf("%s\n", buffer);
}
double nb1 = strtol(&buffer[0], &str, 10);
double nb2 = strtol(&buffer[3], &str, 10);
calculatrice(nb1, buffer[2], nb2);
}
return 0;
}
void calculatrice(double value_1, char operator, double value_2){
double result = 0;
switch (operator)
{
case '+':
result = value_1 + value_2;
printf("resultat : %f\n",result);
break;
case '-':
result = value_1 - value_2;
printf("resultat : %f\n",result);
break;
case '*':
result = value_1 * value_2;
printf("resultat : %f\n",result);
break;
case '/':
result = value_1 / value_2;
printf("resultat : %f\n",result);
break;
case '%':
result = (int)value_1 % (int)value_2;
printf("resultat : %f\n",result);
break;
default:
break;
}
}
`
I tried to make loops and conditions which triggers when there is a space to get each part necessary for my calculator, but the result was completely wrong.

Given the user input of
160 + 23
then
&buffer[0] will be the string "160 + 23\n",
&buffer[3] will be the string " + 23\n", and
buffer[2] will be the character '0'.
strtol converts the initial part of a string to a long. With base-10, the string may begin with an arbitrary amount of whitespace, and then an optional sign character of '+' or '-'.
For "160 + 23\n", the converted value will be 160 as it stops on the first non-digit character encountered (a ' ' after '0').
For " + 23\n", the converted value will be 0, after skipping the initial whitespace, reading the sign character '+', and stopping on the first non-digit character encountered (a ' ' after '+').
These resulting values are then implicitly converted to double during the assignment.
Note, to convert a string directly to a double, use strtod.
The effect is that, with the given user input, calculatrice is called as:
calculatrice(160.0, '0', 0.0);
There is no match for '0' in the switch, and thus the function quietly returns.
You must find the correct string tokens more carefully, but how this is done depends greatly on the requirements of your program. Two interesting functions in the standard library are:
strtok can be used to break a string into tokens, based on a set of delimiting characters.
sscanf can be use to convert well formatted strings into data.
Here is a cursory example of using sscanf.
#include <stdio.h>
#include <stdlib.h>
double calculatrice(double, char, double);
int main(void)
{
puts("************************************************");
puts("ecrire sous la forme x + y avec les espaces pour avoir un resultat");
puts("quit pour quitter");
puts("************************************************");
char buffer[128];
while (fgets(buffer, sizeof buffer, stdin)) {
if ('q' == *buffer)
break;
if ('f' == *buffer) {
system("clear");
continue;
}
char op;
double lhs, rhs;
if (3 == sscanf(buffer, "%lf %c%lf", &lhs, &op, &rhs))
printf("Result: %f\n", calculatrice(lhs, op, rhs));
}
}
double calculatrice(double a, char operator, double b)
{
switch (operator) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
if (0 == b) {
fprintf(stderr, "Division by zero detected.\n");
break;
}
return a / b;
case '%':
if (0 == (int) b) {
fprintf(stderr, "Division by zero detected.\n");
break;
}
return (int) a % (int) b;
default:
fprintf(stderr, "Invalid operator [%c].\n", operator);
break;
}
return 0.0;
}
************************************************
ecrire sous la forme x + y avec les espaces pour avoir un resultat
quit pour quitter
************************************************
160 + 23
Result: 183.000000
The purpose of text here is unclear, but the use of
if (!text) {
strcat(text, buffer);
/* ... */
is surely wrong, as it guarantees Undefined Behaviour by passing the NULL pointer value to strcat. Otherwise, text is unused until this failure state.

Related

Calculator with user defined variables in C language

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!");
}
}
}
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 of float
scanf_s("%c", &situation, 1); is not portable: the Microsoft version of this function expects the size argument 1 as an UNSIGNED whereas the Standard C function defined as optional in Annex K specifies that the size argument 1 must be passed as a size_t, hence as (size_t)1. Avoid using this function and read user input as a line with fgets() and use the standard function sscanf() 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 write
scanf(" %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 type int or size_t, not char.
the format string in printf("\n\n % d - % c = % d\n\n", ...); is incorrect: the space between the % and the c 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];
/* the function skip_spaces() updates `*pos`, skipping any white
* space in `str` at the corresponding index
*/
void skip_spaces(const char *str, int *pos) {
while (isspace((unsigned char)str[*pos]))
*pos += 1;
}
/* the function trim_spaces() updates `*pos`, skipping any white
* space in `str` at the corresponding index. In addition, it
* removes trailing white space from the string, ie: newlines,
* spaces, TABs and other white space characters
*/
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);
}
/* the function parse_operand() reads the next operand from `str`
* at index `*pos`. It recognises floating point numbers and
* variable names, which are replaced with their value. The value is
* stored into `*value`. `*pos` is updated past the operand and any
* white space after it.
*/
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_expression: parse an expression with basic operators,
* no precedence: the function expects at least one operand and
* keeps parsing and evaluating as long as there is a supported
* operator that follows. The result is stored into `*result`.
*/
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;
/* strip trailing whitespace, skip initial whitespace */
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)

Validate user's input to check if input is in the right format in C

The program will prompt the user to enter a simple expression. After splitting the string and assigning the variables, i want to check to see if what the user entered is a an integer so it can be calculated in the switch statement. What would be the best way to validate the data inside num1 and num2 to make sure they are integers and not letters or any other character.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*This function will display the user's desired expression to be calculated */
char* expressionDisplay(char* input)
{
char *str = input;
printf("The expression entered is: %s\n", str);
}
int main()
{
char str[50];
char operator[6] = "+-*/%";
int num1,num2;
char calculation;
char *oldstr = malloc(sizeof(str));
printf("This program will solve a simple expression in the format 'value' 'operator' 'value'\n ");
printf("Example 2+6 or 99 * 333\n");
printf("Enter the simple expression to be calculated: \n");
scanf("%[^\n]%*c", str); //this will scan the whole string, including white spaces
strcpy(oldstr, str);
for(int i = 0; i < strlen(operator); i++)
{
char *position_ptr = strchr(str, operator[i]);
int position = (position_ptr == NULL ? -1 : position_ptr - str);
if(str[position] == operator[i])
{
calculation = operator[i];
char *num1_ptr = strtok(str, operator);
int num1 = atoi(num1_ptr);
char * num2_ptr = strtok(NULL, operator);
int num2 = atoi(num2_ptr);
break;
}else
calculation = position;
}
switch(calculation)
{
case '+':
expressionDisplay(oldstr);
printf("Sum\n");
break;
case '-':
expressionDisplay(oldstr);
printf("Subtract\n");
break;
case '*':
expressionDisplay(oldstr);
printf("Multiply\n");
break;
case '/':
expressionDisplay(oldstr);
printf("Division\n");
break;
case '%':
expressionDisplay(oldstr);
printf("Modulus\n");
break;
default:
printf("Sorry unable to calculate the expression entered. Try again.\n");
printf("Enter a simple expression - number operator number - ");
break;
}
}
In this case you can use the strtol function of standard c library.
You can see more detail about it at this link : strtol - c++reference.

Calculator with Decimal, Octal and Hexadecimal Numbers

I want to make a calculator that is capable of calculation with decimal numbers and is able to return the decimal values in their respective binary, octal or hexadecimal representation.
So far in the main method the program reads the command line and I can invoke the program by two ways.
The first way would be with 3 values:
"number1" "operator" "number2".
And the second way would be with 4 values:
"wished numeral system for the output" "number1" "operator" "number2".
Where for the wished numeral system output b would stand for for binary, o for octal and h for hexadecimal. In both ways the user should be able to input decimal, octal and hexadecimal numbers for the inputs number1 and number2.
#include "zahlen.h"
#include <stdio.h>
#include "stringTOint.h"
int main(int argc, char *argv[]) {
char o,op,sx[DIGITS+1],sy[DIGITS+1],sz[DIGITS+1];
int x,y,z;
char flag_x,flag_y;
/* 1) Read Commandline */
if (argc != 4 && argc != 5) {
printf("Aufruf: %s -o <x> <op> <y> \n",argv[0]);
return 1;
} else if(argc == 4) {
x = stringTOint(argv[1]);
op = argv[2][0];
y = stringTOint(argv[3]);
} else if(argc == 5) {
o = argv[1][0];
x = stringTOint(argv[2]);
op = argv[3][0];
y = stringTOint(argv[4]);
if(o != 'b' && o != 'o' && o != 'h') {
printf("Wrong Operation\n");
return 1;
}
}
/* 2) Solve the equation */
if(argc==4) {
printf("solve: %s %c %s \n", argv[1], op, argv[3]);
z = solve(x, op, y);
} else if(argc==5) {
printf("solve: %s %c %s \n", argv[2], op, argv[4]);
z = solve(x, op, y);
}
/* 3) Calculate the Representation of the wished Numeral System */
switch(o) {
case 'b':
intTObinaer(x, sx);
intTObinaer(y, sy);
intTObinaer(z, sz);
break;
case 'o':
intTOoctal(x,sx);
intTOoctal(y,sy);
intTOoctal(z,sz);
break;
case 'h':
intTOhexal(x,sx);
intTOhexal(y,sy);
intTOhexal(z,sz);
break;
default:
intTObinaer(x, sx);
intTObinaer(y, sy);
intTObinaer(z, sz);
break;
}
/* 4) Return the results */
printf("\n %s %d\n%c %s %d\n= %s %d\n", sx,x,op,sy,y,sz,z);
return 0;
}
The methods intTObinaer, intTOoctal and intTOhexal only differ by the base with which the decimal number gets divided.
intTObinaer(int i, char str[]) {
unsigned int zahl = i;
int j;
/* Fill Array with zeros */
int x = 0;
for (x; x < DIGITS+1; x++) {
str[x] = '0';
}
/*Calculate the Binary representation of the given Decimal integer */
for (j = DIGITS-1; j > 0; j--) {
/* This base gets changed to 8 or 16 for octal and hexal representation */
str[j] = (char) (zahl % 2) + '0';
zahl = zahl / 2;
if (zahl == 0) {
break;
}
}
/* Set the end of the Array */
str[DIGITS] = '\0';
}
The actual equation gets solved in the solve method, where the right operation for number1 and number2 gets chosen by an switchcase where the different cases can be selected by the char op that the user had input between the two numbers.
#include <stdio.h>
int solve(int x, char op, int y) {
int ergebnis = 0;
switch(op) {
case '+':
ergebnis = x + y;
break;
case '-':
ergebnis = x - y;
break;
case '*':
ergebnis = x * y;
break;
case '/':
ergebnis = x / y;
break;
case '&':
ergebnis = x & y;
break;
case '|':
ergebnis = x | y;
break;
default:
printf("Wrong input\n");
}
return ergebnis;
}
My question now is due to the fact the the user should be able to input different numeral systems(e.g. decimal, octal or hexadecimal) how can I identify the different numeral systems and then transfer them into decimal so that I can calculate the result. After that these decimal Numbers have to be converted back into the desired numeral system that the user wanted.
Looks like you only need to add two lines to do that:
#include "stdlib.h"
#define stringTOint(arg) ((int)strtol(arg,NULL,0))
Or better yet, replace those invocations of stringTOint() with corresponding strtol() invocations (and add the #include, of course).
strtol() uses the same prefixes as for C literals: 0 for octal, 0x for hex, no prefix is decimal.
I would like to suggest another approach to this problem.
Many of the parsing you perform can be performed directly by the sscanf function, the only case is the binary case that needs to be implemented differently.
The implementation follows 3 main step:
Parse the input using the sscanf function (or the ConvCharToBinfor binary values) and store the values in the variables a and b;
Perform the operation and store the result in the res variable;
Print the output result by using the printf parsing (or loop for the binary case).
An implementation would be the following:
#include<stdio.h>
#include<string.h>
typedef struct stack {
unsigned char data[32];
int size;
} stack_t;
int ConvCharToBin(char* input);
int main(int argc, char *argv[]) {
char numSys = 'd', op;
char** param = argv;
int a, b, res;
param++;
//error case
if(argc != 4 && argc != 5) {
//not a valid input
printf("Not a valid input");
return -1;
}
if(argc == 5) {
numSys = param[0][0];
param++;
}
op = param[1][0];
switch(numSys) {
case 'b':
a = ConvCharToBin(param[0]);
b = ConvCharToBin(param[2]);
break;
case 'd':
sscanf(param[0], "%d", &a);
sscanf(param[2], "%d", &b);
break;
case 'h':
sscanf(param[0], "%x", &a);
sscanf(param[2], "%x", &b);
break;
case 'o':
sscanf(param[0], "%o", &a);
sscanf(param[2], "%o", &b);
break;
default:
//no viable number system
return -1;
}
switch(op) {
case '+':
res = a + b;
break;
case '-':
res = a - b;
break;
case '/':
res = a / b;
break;
case '*':
res = a * b;
break;
case '&':
res = a & b;
break;
case '|':
res = a | b;
break;
default:
//no valid operand
printf("invalid operation\n");
return -1;
}
stack_t tmp;
tmp.size = 0;
int i;
switch(numSys) {
case 'b':
while (res) {
if (res & 1) {
tmp.data[tmp.size] = '1';
tmp.size++;
} else {
tmp.data[tmp.size] = '0';
tmp.size++;
}
res >>= 1;
}
for(i = tmp.size - 1; i >= 0; i--) {
printf("%c", tmp.data[i]);
}
printf("\n");
break;
case 'd':
printf("%d\n", res);
break;
case 'h':
printf("%x\n", res);
break;
case 'o':
printf("%o\n", res);
break;
}
return 0;
}
int ConvCharToBin(char* input) {
char* idx;
int res = 0x00000000;
for(idx = input; idx < input + strlen(input); idx++) {
res <<= 1;
if(*idx == '1') {
res |= 0x00000001;
}
}
return res;
}
The sscanf reads formatted data from a string (in you case the argv strings)
This can be parsed using the following:
%d for decimal;
%x for hexadecimal;
%o for octal.
Unfortunately there is no C standard for parsing binary using sscanf, so this is done apart using the stdout.
I would also point out that this implementation has two limitation
Input/output limited to 32 bit unsigned (so from 0 to 4294967295), but with some slight modifications it can be extended;
No error checking for the input values, this can also be easily implemented.

How do I evaluate decimals & floating point numbers in scientific e notation - e.g. {1.23e4}. in postfix?

I have written my code to evaluate from postfix to result. However, I am stuck at how to do it when the postfix is going to be in decimals & floating point numbers in scientific e notation - e.g. {1.23e4}. Any specific suggestion would be highly appreciated. Thanks.
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#define SIZE 50 /* Size of Stack */
double s[SIZE];
int top=-1; /* Global declarations */
int flag=0;
double pop()
{ /* Function for POP operation */
return(s[top--]);
}
double push(double elem)
{ /* Function for PUSH operation */
if(flag==1){
int num;
num=pop();
s[++top]=elem+10*num;
}
else if(flag==0){
s[++top]=elem;
flag=1;
}
}
void main()
{ /* Main Program */
char pofx[50],ch;
int i=0;
double op1,op2;
printf("Enter the Postfix Expression:");
fgets(pofx,100,stdin);
while( (ch=pofx[i++]) != '\n')
{
if(isdigit(ch)) push(ch-'0'); /* Push the operand */
else if(ch==' ')
flag=0;
else
{ /* Operator,pop two operands */
flag=0;
op2=pop();
op1=pop();
switch(ch)
{
case '+':push(op1+op2);break;
case '-':push(op1-op2);break;
case '*':push(op1*op2);break;
case '/':push(op1/op2);break;
case '^':push(pow(op1,op2));break;
default:
printf("Input invalid ... give proper input\n");
return 0;
}
}
}
printf("Result: %lf\n",s[top]);
}
How do I evaluate decimals & floating point numbers in scientific e notation ... (?)
To convert a string into FP value use strtod() #M Oehm
Yet code has other problems in that the operator symbols '-' and '+' may also begin valid value tokens like -123.45.
// insufficient test to determine if the next part of the string is a number or operator.
if(isdigit(ch))
push(ch-'0');
Use strtod() to convert text to double and determine if the next part of the string is a double.
Alternative code:
const char *st = pofx;
while (*st) {
char *end; //location to store end of FP parsing
double value = strtod(st, &end);
if (end > st) {
push(value);
st = end;
} else if (isspace((unsigned char) *st)) {
st++;
} else {
switch (*st) {
case '+':push(pop() + pop());break; // pop order irrelevant
case '-':{ double t = pop(); push(pop() - t);break; } // pop order relevant
case '*':push(pop() * pop());break;
...
default: {
printf("Input invalid operator: character code %d\n", *st);
return 0;
}
} // end switch
st++;
}
}
Re-write push()
void push(double elem) {
if (top + 1 >= SIZE) {
printf("Stack overflow\n");
return;
}
s[++top] = elem;
}
Wrong argument to fgets()
char pofx[50];
// fgets(pofx,100,stdin); // 100??
fgets(pofx, sizeof pofx, stdin); // better
The function strtod from <stdlib.h> will parse a double for you. It takes the string to parse and a pointer to a string, that will begin with the first unparsed character. (There's a similar function for long integers, strtol.)
Here's an example of how this might work in your case. (The code just prints out the tokens and doesn't do any calculations.)
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int is_number(const char *p)
{
if (*p == '-' || *p == '+') p++;
if (*p == '.') p++;
return isdigit((unsigned char) *p);
}
int main(void)
{
const char *line = " .1 20.1* 1.0e-3+2e+7 * -1.0*";
const char *p = line;
while (isspace((unsigned char) *p)) p++;
while (*p) {
if (is_number(p, after_op)) {
char *end;
double x = strtod(p, &end);
if (p == end) {
puts("Illegal number");
p++;
} else {
printf("Number %g\n", x);
p = end;
}
} else {
int c = *p++;
switch (c) {
case '+': puts("Operator add"); break;
case '-': puts("Operator sub"); break;
case '*': puts("Operator mult"); break;
case '/': puts("Operator div"); break;
case '^': puts("Operator pow"); break;
default: printf("Illegal char '%c'\n", c);
}
}
while (isspace((unsigned char) *p)) p++;
}
return 0;
}
This is still very crude, mind you. Strings like 20x21 will be parsed as number 20, unknown character x and number 21. While this code is bad at detecting and reporting errors (which really should be done, but it's left as an exercise, yadda, yadda), it works for valid input.
[Edit: I've incorporated chux's suggestions and also made the code compatible to read numbers with explicit signs, but that means that the binary operators - and + cannot immediately be followed by a digit. Pick your poison. I've also allowed the abridged version that leaves out a leading zero, e.g. .12, a format that I'm not very fond of.]

Why and how to know when the scanf("%c") store extra data in memory? [C]

I wrote a simple program to make basic operation in prefix notation (operator operand1 operand2):
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
float operando(char s[], float precedente);
float operazione(float o1, float o2, char operatore);
int main(void)
{
char operatore;
char operando1[MAX], operando2[MAX];
float precedente = 0;
float o1, o2;
printf("Scrivi l'operazione con questo formato: operatore operando1 operando2;\nPREV al posto di uno dei due operandi per usare l'ultimo risultato.\nLettera qualunque per terminare\n");
do
{
scanf("%c %s %s", &operatore, operando1, operando2);
o1 = operando(operando1, precedente);
o2 = operando(operando2, precedente);
precedente = operazione(o1, o2, operatore);
printf("%c %f %f = %f\n\n", operatore, o1, o2, precedente);
scanf("%*c");
} while(operatore == '+' || operatore == '-' || operatore == '*' || operatore == '/');
return 0;
}
float operando(char s[], float precedente)
{
if (strcmp(s, "PREV") == 0)
return precedente;
else
return atof(s);
}
float operazione(float o1, float o2, char operatore)
{
switch (operatore)
{
case '+':
return o1 + o2;
break;
case '-':
return o1 - o2;
break;
case '*':
return o1*o2;
break;
case '/':
return o1 / o2;
break;
}
}
If I run this program, it works only the first time, then it takes '\n' as character and put it in operator variable. So I add after the last printf a simple line:
scanf("%*c");
With this line the program works correctly.
I don't understand: why without discarding '\n' it doesn't use the last character read? How can I know, before running a program, when to discard a character?
The %c format specifier to scanf will ready any character, including whitespace characters like spaces or newlines. You need to add a space before the %c which will absorb any whitespace characters:
scanf(" %c %s %s", &operatore, operando1, operando2);

Resources