Program not receiving required input - c

I have a problem with my homework. I have some code written by teacher and I suppose to edit it in order to make a calculator. So I added couple of lines i thought it will work, but sadly it's not the case. Program returns always that operands or operator is wrong. Can you have a look?
main.c
#include "stdio.h"
#include "evalexpression.h"
int main() {
char string[100];
int result;
result = InterCalc(string);
CalcFilter(result, string);
return 0;
}
evalexpression.c
#include "stdio.h"
#include "string.h"
#include "evalexpression.h"
#include "math.h"
#include "float.h"
static float f1, f2;
static char op;
int isValidExpression(const char *str) {
int res;
char ops[10];
res = sscanf(str, "%f %s %f", &f1, ops, &f2);
if (res == 3) {
if (ops[0] == '+' || ops[0] == '-' || ops[0] == '^' || ops[0] == '*' || ops[0] == '/') {
op = ops[0];
return 1;
} else
return 0;
} else
return 0;
}
int getOperator() {
return (op);
}
float getFstOperand() {
return (f1);
}
float getSecOperand() {
return (f2);
}
float getExprValue() {
int operation;
operation = getOperator();
switch (operation) {
case 1:
return (getFstOperand() + getSecOperand());
break;
case 2:
return (getFstOperand() - getSecOperand());
break;
case 3:
return (getFstOperand() / getSecOperand());
break;
case 4:
return (getFstOperand() * getSecOperand());
break;
case 5:
return (pow(getFstOperand(), getSecOperand()));
break;
default:
return 0;
}
}
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
if (strcmp(my_string, "exit\n") == 0) {
printf("Program ended\n");
return 0;
} else
if (isValidExpression(my_string) == 0) {
printf("Expression error\n");
return 0;
} else
return 1;
}
void CalcFilter(int a, char *str) {
float calculation_value;
printf("Press 'E' to display the invalid line or press 'V' to display the valid line\n");
int choice;
choice = getchar();
switch (choice) {
case 'E':
case 'e':
if (a == 0) printf("The line %s is invalid.\n", str);
else if (a == 1) printf("There's nothing wrong with the line %s\n", str);
break;
case 'V':
case 'v':
if (a == 1) {
calculation_value = getExprValue();
printf("The result of %s is %f.\n", str, calculation_value);
}
if (a == 0) printf("The line %s is invalid\n", str);
break;
default:
printf("You haven't chosen the valid option of the switch\n");
break;
}
}

You should pass the size of the destination buffer to function InterCalc(). As written, it can only read sizeof(char*) - 1 bytes at a time. You should also check for end of file.
int InterCalc(char *my_string, size_t size) {
if (fgets(my_string, size, stdin) == NULL
|| strcmp(my_string, "exit\n") == 0) {
printf("Program ended\n");
return 0;
} else
if (isValidExpression(my_string) == 0) {
printf("Expression error\n");
return 0;
} else {
return 1;
}
}
Invoke from main():
#include <stdio.h>
#include "evalexpression.h"
int main(void) {
char string[100];
int result;
result = InterCalc(string, sizeof(string));
CalcFilter(result, string);
return 0;
}
Notes:
you should use the <stdio.h> syntax for standard headers.
you should prevent buffer overflow by passing the maximum number of characters for %s formats in sscanf(): sscanf(str, "%f %9s %f", &f1, ops, &f2);
EDIT: There is another problem in GetExrValue(): you switch on values from 0 to 5 for op instead of the operation character. Here is a way to correct this:
float getExprValue(void) {
switch (getOperator()) {
case '+':
return getFstOperand() + getSecOperand();
case '-':
return getFstOperand() - getSecOperand();
case '/':
return getFstOperand() / getSecOperand();
case '*':
return getFstOperand() * getSecOperand();
case '^':
return pow(getFstOperand(), getSecOperand());
default:
return 0;
}
}

Related

How to output elements inside of stack during RPN Calculating

I implemented an RPN Calculator in C. Now I want to output the current iteration meaning
Iteration 1: Contents: [5, 5]
Iteration 2: Contents: [25]
I am not quite sure how i am going to print them. I tried Printing them in the main function, but the output was coming
Iteration 1: Contents: 5
Iteration 2: Contents: 5
10
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_SIZE 100
int stack[MAX_SIZE];
int top = 0;
void makeEmpty()
{
top = 0;
}
bool isEmpty()
{
return top == 0;
}
bool isFull()
{
return top == MAX_SIZE;
}
void push(int value)
{
stack[top++] = value;
}
int pop()
{
if(isEmpty())
{
printf("Not enough operands in expression\n");
exit(EXIT_FAILURE);
}
return stack[--top];
}
//adds 2 integers
int add(int a, int b)
{
return a + b;
}
//subtracts 2 integers
int sub(int a, int b)
{
return a - b;
}
//multiplies 2 integers
int mul(int a, int b)
{
return a * b;
}
//divides 2 integers
int divide(int a, int b)
{
return a / b;
}
int main(void)
{
char ch;
while(1)
{
//Emptying the stack before the user enters another expression
makeEmpty();
printf("Enter an RPN expression: ");
//Reads expression from user
scanf("%c", &ch);
//parse all characters until a newline is reached
while(1)
{
if(ch == '\n')
break;
//if character is an integer
if(ch >= 48 && ch <= 57)
{
if(!isFull())
{
//convert char to int and push integer onto stack
printf("Iteration %d: Contents: %d \n", (top+1), (ch-48));
push(ch - 48);
}
else
{
//stack ran out of space, print error and exit program
printf("Expression is too complex\n");
exit(EXIT_FAILURE);
}
}
switch(ch)
{
case '+':
push(add(pop(), pop()));
break;
case '-':
push(sub(pop(), pop()));
break;
case '*':
push(mul(pop(), pop()));
break;
case '/':
push(divide(pop(), pop()));
break;
case '=':
printf("%d\n", pop());
break;
}
//get next character
scanf("%c", &ch);
}
}
return 0;
}
You can easily workaround it in your program without creating temporary stacks:
void print_stack(void)
{
printf("[");
for(int index = top -1; index >= 0; index--)
{
printf("%d%s", stack[index], index ? ", " : "");
}
printf("]\n");
}

How do I ignore spaces in a string input?

I am creating a program that evaluates a postfix expression contained in a single line of a text file. I'm having some trouble dealing with blank spaces in the scanned file. What I've done so far is scan the single line from the file into a buffer, and then process the string one character at a time. How do I ignore blank spaces once I've read the line into a string? For example:
2 4 3 * +
Here is the full program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int stack[1000];
int top = -1;
void push(int x);
int pop();
bool isOperator(char ch);
int performOperation(int op1, int op2, char op);
int main()
{
char exp[1000], buffer[15];
int i, num, op1, op2, len, j, x;
int stack[1000];
char fileName[20];
FILE *inFile;
char *e;
printf("Please enter text file:");
scanf("%s", fileName);
inFile = fopen(fileName, "r");
if (inFile == NULL) {
printf("Error\n");
return -1;
}
int N = 0; i = 0, temp;
while (!feof(inFile)) {
fgets(buffer, 15, inFile);
N++;
}
printf("Postfix expression:\n");
printf("%s", buffer);
e = buffer;
while (*e != '\0') {
if (isdigit(*e)) {
num = *e - 48;
push(num);
} else {
op1 = pop();
op2 = pop();
if (isOperator(*e)) {
int ans;
ans = performOperation(op1, op2, *e);
}
push(ans);
}
e++;
}
printf(" The value of the expression is %d\n", ans);
}
void push(int x)
{
stack[++top] = x;
}
int pop()
{
return stack[top--];
}
bool isOperator(char ch) {
if (ch == '+' || ch == '-' || ch == '*'|| ch == '/')
return true;
else
return false;
}
int performOperation(int op1, int op2, char op) {
int ans;
switch (op) {
case '+':
ans = op2 + op1;
break;
case '-':
ans = op2 - op1;
break;
case '*':
ans = op2 * op1;
break;
case '/':
ans = op2 / op1;
break;
}
return ans;
}
Any help is appreciated.
I forgot to mention that we are only dealing with single-digit numbers.
You can remove the spaces so you don't have to deal with them
void remove_spaces(char* s) {
const char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
If I have understood correctly the problem is processing embedded white spaces.
To resolve the problem you can rewrite the while loop at least the following way
int ans = 0;
for ( e = buffer; *e != '\0'; ++e ) {
if ( !isspace( ( unsigned char )*e ) )
{
if ( isdigit( ( unsigned char )*e ) ) {
num = *e - '0';
push(num);
} else if ( isOperator(*e) ) {
op1 = pop();
op2 = pop();
ans = performOperation(op1, op2, *e);
push(ans);
}
}
}
ans = pop();
printf(" The value of the expression is %d\n", ans);
Pay attention to this statement before the printf call
ans = pop();
You have to pop the answer from the stack before printing it. Also you should process invalid characters and check whether the stack is empty.
Also this loop
int N = 0; i = 0, temp;
while (!feof(inFile)) {
fgets(buffer, 15, inFile);
N++;
}
seams does not make sense and the condition of the loop is incorrect. For example for an empty file the variable buffer will not contain a valid data.
There are multiple problems in your code:
The loop while (!feof(inFile)) is incorrect. You should instead use:
while (fgets(buffer, sizeof buffer, inFile)) {
/* handle the string expression in buffer */
you should not push the number immediately when encountering a digit, you should parse the number that may have more than one digit.
once you parse numbers correctly, you can discard any white space encountered in the parser.
Here is a modified version:
#include <stdio.h>
bool isOperator(char ch) {
if (ch == '+' || ch == '-' || ch == '*'|| ch == '/')
return true;
else
return false;
}
int performOperation(int op1, int op2, char op) {
int ans;
switch(op) {
case '+':
ans = op2 + op1;
break;
case '-':
ans = op2 - op1;
break;
case '*':
ans = op2 * op1;
break;
case '/':
ans = op2 / op1;
break;
}
return ans;
}
int main() {
char fileName[100];
char buffer[100];
FILE *inFile;
printf("Please enter text file:");
if (scanf("%99s", fileName) != 1) {
printf("No input\n");
return 1;
}
inFile = fopen(fileName, "r");
if (inFile == NULL) {
printf("Error\n");
return -1;
}
while (fgets(buffer, sizeof buffer, inFile);
printf("Postfix expression:\n");
printf("%s", buffer);
char *e = buffer;
while (*e != '\0') {
if (isdigit((unsigned char)*e)) {
int num = 0;
while (isdigit((unsigned char)*e)) {
num = num * 10 + *e++ - '0';
}
push(num);
} else
if (isspace((unsigned char)*e) {
e++; // ignore white space
} else
if (isOperator(*e)) {
int op1 = pop();
int op2 = pop();
int ans = performOperation(op1, op2, *e++);
push(ans);
} else {
printf("Invalid character in expression: %c\n", *e++);
}
}
int ans = pop();
printf(" The value of the expression is %d\n", ans);
}
fclose(inFile);
return 0;
}

Changing gets() to txt file input [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I need to covert this code from a user input using gets() to scanning in an input txt file.
It would also be helpful to find a way to count the number of letters in every word. Starting with 1 letter words and on.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
int acount, bcount, ccount, dcount, ecount, fcount, gcount, hcount, icount, jcount, kcount, lcount, mcount, ncount, ocount, pcount, qcount, rcount, scount, tcount, ucount, vcount, wcount, xcount, ycount, zcount = 0;
char *str;
printf("Enter any string : ");
gets(str);
while (*str != '\0')
{
if(isalpha(*str))
{
toupper(*str);
switch(*str)
{
case 'A':
++acount;
break;
case 'B':
++bcount;
break;
case 'C':
++ccount;
break;
case 'D':
++dcount;
break;
case 'E':
++ecount;
break;
case 'F':
++fcount;
break;
case 'G':
++gcount;
break;
case 'H':
++hcount;
break;
case 'I':
++icount;
break;
case 'J':
++jcount;
break;
case 'K':
++kcount;
break;
case 'L':
++lcount;
break;
case 'M':
++mcount;
break;
case 'N':
++ncount;
break;
case 'O':
++ocount;
break;
case 'P':
++pcount;
break;
case 'Q':
++qcount;
break;
case 'R':
++rcount;
break;
case 'S':
++scount;
break;
case 'T':
++tcount;
break;
case 'U':
++ucount;
break;
case 'V':
++vcount;
break;
case 'W':
++wcount;
break;
case 'X':
++xcount;
break;
case 'Y':
++ycount;
break;
case 'Z':
++zcount;
break;
}//Close case
}//Close if
}//Close while
printf("Number of A's: %d", acount);
}
Many errors in your code
You don't initialize all the (x)count variables to 0, read about the coma operator.
You used gets() which is a mean and deprecated function.
You passed an uninitialized pointer to gets() which is undefined behavior.
toupper(*str) does not modify *str.
Try this one
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
/* You need an array of int's with size equal to the number of letters
* int the alphabet
*/
int count['Z' - 'A' + 1];
/* You need some space to store the text, `str' will become a poitner
* when you pass it to `fgets()' pointing to an array of 1000 `chars'
*/
char str[1000];
/* Initialize all the counters to 0 */
for (int i = 0 ; i < sizeof(count) / sizeof(*count) ; ++i)
count[i] = 0;
printf("Enter any string : ");
/* Read the string, use `fgets()` and prevent a buffer overflow */
if (fgets(str, sizeof(str), stdin) == NULL)
return -1;
/* Now count the letters */
for (int i = 0 ; ((str[i] != '\0') && (str[i] != '\n')) ; ++i)
{
/* If it's not a letter, go to the next one */
if (isalpha((int) str[i]) == 0)
continue;
/* It's a letter, count it at the correct position */
count[toupper((int) str[i]) - 'A'] += 1;
}
/* Print the count of each letter, skipping those that did not appear */
for (int i = 0 ; i < sizeof(count) / sizeof(*count) ; ++i)
{
if (count[i] == 0)
continue;
fprintf(stderr, "Number of %c's : %d\n", i + 'A', count[i]);
}
return 0;
}
All remarks in iharob response are correct. Read my comment on his response for extra problems. Here is a simple solution:
#include <stdio.h>
int main(void) {
int counts[256] = { 0 };
int c;
printf("Enter any string: ");
while ((c = getchar()) != EOF && c != '\n') {
counts[c & 255]++;
}
printf("Number of A's: %d", counts['a'] + counts['A']);
return 0;
}
EDIT: here is a solution to handle a file instead of a line of input:
#include <stdio.h>
int main(int argc, char **argv) {
long long int counts[256] = { 0 };
int c;
FILE *f;
if (argc < 2) {
fprintf(stderr, "usage: %s FILE\n", argv[0]);
exit(2);
}
if ((f = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]);
exit(1);
}
while ((c = getc(f)) != EOF) {
counts[c & 255]++;
}
fclose(f);
printf("Number of A's: %lld", counts['a'] + counts['A']);
return 0;
}

Calculator Program using stack

I am writing a calculator program in c using stack, In below program I used concept of infix to postfix conversion and next postfix evaluation.
I am getting correct answer for 1+2 answer is 3 but for 11+1 or any two and more digit i am getting wrong answer.
Can anyone help me what I will include in my code so that it work for more than two digit like 28+25 or any?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define SIZE 50 /* Size of Stack */
int top = -1;
char pofx[50];
char s[SIZE];
int infix_to_postfix() {
char infx[50], ch;
int i = 0, k = 0;
void push(char elem) { /* Function for PUSH operation */
s[++top] = elem;
}
char pop() { /* Function for POP operation */
return (s[top--]);
}
int pr(char elem) { /* Function for precedence */
switch (elem) {
case '#':
return 0;
case '(':
return 1;
case '+':
case '-':
return 2;
case '*':
case '/':
return 3;
}
return -1;
}
printf("\n\nEnter a Value to calculate : ");
gets(infx);
push('#');
while ((ch = infx[i++]) != '\0') {
if (ch == '(') push(ch);
else if (isalnum(ch)) pofx[k++] = ch;
else if (ch == ')') {
while (s[top] != '(')
pofx[k++] = pop();
char elem = pop(); /* Remove ( */
} else { /* Operator */
while (pr(s[top]) >= pr(ch))
pofx[k++] = pop();
push(ch);
}
}
while (s[top] != '#') /* Pop from stack till empty */
pofx[k++] = pop();
pofx[k] = '\0'; /* Make pofx as valid string */
printf("\n\nGiven Infix Expn: %s Postfix Expn: %s\n", infx, pofx);
return (int) pofx[k];
}
void postfix_evaluate() {
char ch;
int i = 0, op1, op2;
void pushit(int elem) { /* Function for PUSH operation */
s[++top] = elem;
}
int popit() { /* Function for POP operation */
return (s[top--]);
}
infix_to_postfix();
while ((ch = pofx[i++]) != '\0') {
if (isdigit(ch)) pushit(ch - '0'); /* Push the operand */
else { /* Operator,pop two operands */
op2 = popit();
op1 = popit();
switch (ch) {
case '+':
pushit(op1 + op2);
break;
case '-':
pushit(op1 - op2);
break;
case '*':
pushit(op1 * op2);
break;
case '/':
pushit(op1 / op2);
break;
}
}
}
printf("\n Given Postfix Expn: %s\n", pofx);
printf("\n Result after Evaluation: %d\n", s[top]);
}
int main() {
postfix_evaluate();
return 0;
}
part of my own code that might be useful:
if (isdigit(gi.n.nch))
{
gi.x = chr2num(gi.n.nch);
gi.n= nextchar( gi.n, len, instr);
while(isdigit(gi.n.nch))
{
gi.x *= 10;
gi.x += chr2num(gi.n.nch);
gi.n= nextchar( gi.n, len, instr);
}
}

How do I detect an operator vs. int in C using scanf?

How do I read in the following input in my RPN calculator so that it will find the operator no matter what order?
2
2+
4
As of now my scanf only sees the first char in the string and I can only do this:
2
2
+
4
I'm also trying to add an option for integer vs floating point mode. (ex. when 'i' is entered, operate in floating point and vice versa.)
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int *p;
int *tos;
int *bos;
void push(int i);
int pop(void);
int main (void)
{
int a, b;
//float c, d;
char s[80];
//char op; //declare string of 80 chars
p = (int *) malloc(MAX*sizeof(int)); //get stack memory
if (!p){
printf("Allocation Failure\n");
exit(1);
}
tos = p;
bos = p + MAX-1;
printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
do {
printf("> ");
// gets(s);
// scanf("%s", s); //read integer
scanf("%s", s);
// switch (*s) {
switch(*s) {
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case '+':
a = pop();
b = pop();
printf("%d\n", a+b);
push(a+b);
break;
case '-':
a = pop();
b = pop();
printf("%d\n", b-a);
push(b-a);
break;
case '*':
a = pop();
b = pop();
printf("%d\n", a*b);
push(a*b);
break;
case '/':
a = pop();
b = pop();
if(a == 0){
printf("Cannot divide by zero\n");
break;
}
printf("%d\n", b/a);
push(b/a);
break;
case '.':
a = pop();
push(a);
printf("Current value on top of stack: %d\n", a);
break;
default:
push(atoi(s));
}
} while (*s != 'q');
return 0;
}
// Put an element on the stack
void push (int i)
{
if (p > bos){
printf("Stack Full\n");
return;
}
*p = i;
p++;
}
// Get the element from the top of the stack
int pop (void)
{
p--;
if(p < 0) {
printf("Stack Underflow\n");
return 0;
}
return *p;
}
Your scanf reads the whole string. It's the following switch that judges by the first character and misses that + in 2+.
To improve it you can use the strtol function. It will parse an integer out of the string and return to you the location where the integer ended - if that's still not the end of the string, there may be an operator there.
A similar function for floating point numbers is strtod.
Here's some sample code of strtol applicable to your example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* input = "25+";
char* endptr;
int val = strtol(input, &endptr, 10);
if (*endptr == '\0')
{
printf("Got only the integer: %d\n", val);
}
else
{
printf("Got an integer %d\n", val);
printf("Leftover: %s\n", endptr);
}
return 0;
}
I'm not sure if I fully understood your question, but you could iterate through the string like this:
for(i = 0; i < strlen(s); i++)
{
// Here comes your switch section like this
switch(s[i]) {
.....
}
}
Remember also to include string.h.
I really didn't understand your code.
If expect the user to enter one character each time, I mean one character + enter, you should use a simple char instead of char[]. And if you pretend to use a string you should receive it and parse it pzico said.
You could do something like that. The problem would be in the treatment of numbers with multiple digits, but thinking a little bit you can fix this problem. I wrote an attempt, but I'm pretty sure it's not going to work.
printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
scanf("%c", s);
switch(*s){
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case 'q':
printf("Bye Bye\n");
return;
break;
}
printf("Enter the expression one character each time\n");
do {
scanf("%c", s);
switch(s) {
case '+':
a = pop();
b = pop();
printf("%d\n", a+b);
push(a+b);
break;
case '-':
a = pop();
b = pop();
printf("%d\n", b-a);
push(b-a);
break;
case '*':
a = pop();
b = pop();
printf("%d\n", a*b);
push(a*b);
break;
case '/':
a = pop();
b = pop();
if(a == 0){
printf("Cannot divide by zero\n");
break;
}
printf("%d\n", b/a);
push(b/a);
break;
case '.':
a = pop();
push(a);
printf("Current value on top of stack: %d\n", a);
break;
default:
a = pop()*10+atoi(s);
push(a);
}
} while (s != 'q');
Another problem in your code is in your pop function. What do you want to do with this test:
if(p < 0) {
printf("Stack Underflow\n");
return 0;
}
You are expecting your pointer to reach the address 0?
Anyway I hope this is not your homework.

Resources