c- reverse polish notation calculator error - c

So i keep getting the message invalid expression "..." Bus Error (core dumped)if i type ./rpcalc "..." also if i just type in the command line ./rpcalc 1 i get the Segmentation Fault(core dumped) message. This is my entire code i would appreciate any help.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define max 10
#define NUMBER 'n'
int main(int argc, char *argv[])
{
double tmp;
char c;
if(argc <= 1) {
fprintf(stderr,"invalid call\n");
return 1;
}
while(--argc)
{
c = getop(*++argv);
switch(c)
{
case NUMBER:
push(atof(*argv));
break;
case '+':
push(pop() + pop());
break;
case '-':
tmp = pop();
push(pop() - tmp);
break;
case '*':
push(pop() * pop());
break;
case '/':
tmp = pop();
if(!tmp){
printf("can't divide by 0\n");
}
else{
push(pop()/tmp);
}
break;
default:
printf("invalid expression %s\n", *argv);
}
}
printf("%g\n",pop());
return 0;
}
int push (int stack[max], int *top, int *data)
{
if(*top == max -1)
return(-1);
else
{
*top = *top +1;
stack[*top] = *data;
return(1);
}
}
int pop(int stack[max], int *top, int *data)
{
if(*top == -1)
return(-1);
else
{
*data = stack[*top];
*top = *top - 1;
return(1);
}
}
static int isNumber(const char *s){
if(*s == '-' || *s == '+') s++;
if(*s == '\0'){
return 0;
}
while (isdigit(*s)) s++;
if(*s == 'e' || *s == 'E'){
s++;
while(isdigit(*s)) s++;
}
return *s == '\0';
}
int getop(const char *op){
return isNumber(op) ? NUMBER : *op;
}

gcc -Wall -ansi -pedantic
First, you probably shouldn't be returning a static int. Return either a char or an int or unsigned int.
Next: You're invoking functions with incorrect parameters:
Line 28:
push(atof(*argv));
This is not how you've defined your function.
int push (int stack[max], int *top, int *data);
It requires an array of stack[max], an int pointer, and another int pointer
Passing in a float is not correct.
Actually it looks almost like all of your function calls are with incorrect parameters.

Related

How is "++argv" correct in this program from "The C programming Language by Dennis Ritchie"?

The main function has second parameter as char * argv[] , that is an array of pointers.In the same book it has been mentioned that we can't use operations like "++" on array names. But, here we can see ++argv has been used.
#include <stdio.h>
#include <string.h>
#define MAXLINE 1000
int getline(char* line, int max);
/* find: print lines that match pattern from 1st arg */
int main(int argc, char* argv[])
{
char line[MAXLINE];
long lineno = 0;
int c, except = 0, number = 0, found = 0;
while (--argc > 0 && (*++argv)[0] == '-')
{
while (c = *++argv[0])
{
switch (c)
{
case 'x': {
except = 1;
}
break;
case 'n': {
number = 1;
}
break;
default: {
printf("find: illegal option %c\n", c);
argc = 0;
found = -1;
}
break;
}
}
}
if (argc != 1)
{
printf("Usage: find -x -n pattern\n");
}
else
{
while (getline(line, MAXLINE) > 0)
{
lineno++;
if ((strstr(line, *argv) != NULL) != except)
{
if (number)
{
printf("%ld:", lineno);
}
printf("%s", line);
found++;
}
}
}
return found;
}
An array as a parameter to a function is automatically converted to a pointer. So this:
char *argv[]
Is exactly the same as:
char **argv
That's why you're allowed to do argv++.

Infix to postfix function error: control may reach end of non-void function

/*
This is a code that changes infix notation to postfix notation.
I used FILE/IO to get infix notations and the infix.txt file looks like
3
2+4*2-1;
9+3^2^(3-1)*2;
2*((7-2)/3+4)^2%3;
My question is I get error saying "control may reach end of non-void function" on the last two functions, icp and isp. How can I fix this?
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_SIZE 100
#define ENTER 0x000d
void infixtopostfix(char expression[]);
char get_token(char expression[], int *index);
void push(int *top, char token);
int pop(int *top);
int icp(char op);
int isp(char op);
char stack[MAX_SIZE];
int main(void) {
int i, num;
FILE *file;
char expression[MAX_SIZE];
if((file=fopen("infix.txt","r")) == NULL) {
printf("No file.\n");
}
fgets(expression, MAX_SIZE, file);
num = atoi(expression);
for(i=0; i < num; i++) {
fgets(expression, MAX_SIZE, file);
printf("%s", expression);
infixtopostfix(expression);
}
fclose(file);
}
void infixtopostfix(char expression[]) {
char token;
char element;
int top=0;
int index=0;
for(token=get_token(expression, &index); token!=';'; token=get_token(expression, &index)) {
if(isdigit(token)) printf("%c", token);
else if(token == ')') {
while (stack[top] != '(') {
element = pop(&top);
printf("%c", element);
}
pop(&top);
}
else {
while (isp(stack[top])>=icp(token)) {
element = pop(&top);
printf("%c", element);
}
push(&top, token);
}
}
while((token=pop(&top))!=0) printf("%c", token);
printf("\n");
}
char get_token(char expression[], int *index) {
char token=expression[(*index)++];
return token;
}
void push(int *top, char data) {
if(*top < (MAX_SIZE-1)) stack[++(*top)] = data;
}
int pop(int *top) {
if(*top > -1) return stack[(*top)--];
else return 0;
}
int icp(char op) {
switch (op){
case '(' : return 20; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
int isp(char op) {
switch (op){
case '(' : return 0; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
While you may believe that your methods will only ever get one of these 6 characters, the compiler has to assume that any character can be passed in. At the moment, these methods will not return anything if you pass in, for example, 'x'.
You need to specify a default action for all characters not otherwise covered by your switch. Whether this is returning a default value or throwing an exception, that is up to you. But it's nonetheless a possibility your code needs to handle.
like this:
}//end switch
fprintf(stderr, "\nunrecognized OP(%c) is specified.\n", op);// '/', '^'...
return -1;//or exit(-1);

RPN calculator program getting an error C

I'm creating a reverse polish notation calculator that can also do a couple of other things using argv[] to enter options. But right now, I just have the RPN calculator option and I'm getting a strange error that I need help on.
I am getting the error:
Undefined first referenced
symbol in file
fmod /var/tmp//ccGTG20S.o
ld: fatal: Symbol referencing errors. No output written to project
collect2: ld returned 1 exit status
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
void push(float stack[], float value, int *currStack)
{
int i = *currStack;
while (i != 0)
{
stack[i] = stack[i-1];
i--;
}
stack[0] = value;
*currStack += 1;
}
void pop(float stack[], char operation, int *currStack)
{
int i;
switch (operation)
{
case 'A':
stack[0] = stack[1] + stack[0];
break;
case 'S':
stack[0] = stack[1] - stack[0];
break;
case 'X':
stack[0] = stack[1] * stack[0];
break;
case 'D':
stack[0] = stack[1] / stack[0];
break;
case 'M':
stack[0] = fmod(stack[1], stack[0]);
break;
default:
printf("error: the symbol %c is neither a supported operator nor an integer\n", operation);
break;
}
for (i=1;i<*currStack;i++)
{
stack[i] = stack[i+1];
}
*currStack -= 1;
}
void decode(char **instring, float *outval, int size)
{
int i=0, currStack=0;
float stack[size/2];
for (i=1;i<size;i++)
{
if (atof(instring[i]))
push(stack, atof(instring[i]), &currStack);
else
pop(stack, *instring[i], &currStack);
*outval = stack[0];
}
}
int evaluate(int argc, char *argv[])
{
float result;
decode(argv, &result, argc);
printf("%.2f\n", result);
return 0;
}
int
main(int argc, char *argv[])
{
if( (argc>1 )&&(strcmp(argv[1],"-e")!=0) && (strcmp(argv[1],"-c")!=0) && (strcmp(argv[1],"-g")!=0)){
fprintf(stderr, "%s: option %s is unsupported\n", argv[0], argv[1]);
}
if ((argc>1) && strcmp(argv[1], "-e")==0)
{
evaluate(argc, argv);
}
else if ((argc>1) && strcmp(argv[1],"-c")==0)
{
}
else if ((argc>1) && strcmp(argv[1],"-g")==0)
{
}
return EXIT_SUCCESS;
}

*** glibc detected *** invalid pointer: 0x00000031bee21188

I've looked through similar questions on stackoverflow, but I'm still not sure how to fix it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
extern char * pop();
extern void push(char *);
int i;
int j=0;
//Resize the array to 1.1 it's size
void reSize(char* tag){
char *temp = malloc(1.1*sizeof(tag));
for (i=0;i<(sizeof(tag)/sizeof(tag[0]));i++){
*(temp+i) = *(tag+i);
}
free(tag);
tag = temp;
}
int compare(char* tag, char* popVal){
i=0;
while (i<sizeof(tag)/sizeof(tag[0])){
if (*(tag+i) == *(popVal+i)){
i++;
}else{
return 0;
}
}
return 1;
}
void dothis(){
int ch;
int n=0;
char *tag = malloc(10* sizeof(char));
char *popVal;
while ((ch = getchar()) != '>'){
tag[n] = ch;
n++;
if (n > (sizeof(tag)/sizeof(tag[0]))-1 ){
reSize(tag);
}
}
if (*tag == '/'){
popVal = malloc(sizeof(tag));
popVal = pop();
j--;
if (!(compare(tag,popVal))){ // Compare will return 1 if the same
printf("Invalid");
exit(1);
}
}else{
push(tag);
j++;
}
free(tag);
free(popVal);
}
int main(int argc, char * argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (!(isalpha(ch) || ch == '<'))
continue;
dothis();
}
if (j != 0){
printf("Invalid\n");
exit(1);
}
printf("Valid\n");
exit(0);
}
then the external methods:
#include <stdio.h>
#include <stdlib.h>
static int top = 0;
static char * stack[100];
int isEmpty()
{
return !(top);
}
char * pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return (char *) stack[top];
}
void push(char * thing2push)
{
if (top == 100){
fprintf(stderr, "Too many things in the stack");
exit(1);
}else{
stack[top] = thing2push;
top++;
}
}
In a previous question, the selected answer was "passing a pointer to memory you haven't allocated with malloc will definitely not do good things.", but I"m pretty sure I allocated everything
Here's a bug:
popVal = malloc(sizeof(tag));
popVal = pop();
You malloc an area and then immediately lose that value, replacing it with something from pop().
This is most definitely a bug:
while ((ch = getchar()) != '>'){
tag[n] = ch;
n++;
if (n > (sizeof(tag)/sizeof(tag[0]))-1 ){
You assign to tag[n] before checking the range of n. When you do check the range of n after the fact you use sizeof(tag). tag is a pointer. It's size is 4 (32 bit) or 8 (64 bit). Neither size has anything to do with how big n can be before tag[n] writes into invalid memory.
Another bug:
char * pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return (char *) stack[top];
}
If you're a beginning C programmer, never cast a pointer. Because I doubt that you have learned enough yet to know if this is a good or bad idea.
The type system exists for good reasons and if it complains about some types not matching, it is far more likely to be right than you are.

Segmentation fault (core dumped) runtime error in C

Hi so I am new to C and just wrote my first program in the language and keep getting the segmentation fault error when I try to run it. I'm sure there are multiple small mistakes I have made throughout the code. I have gone through it and I can't figure out where my mistake is. Here is my code:
// $Id: crpn.c,v 1.1 2013-10-22 13:28:04-07 - - $
#include <assert.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
int exit_status = EXIT_SUCCESS;
#define EMPTY (-1)
#define SIZE 16
typedef struct stack stack;
struct stack {
int top;
int capacity;
int size;
double numbers[SIZE];
};
void bad_operator (const char *oper) {
fflush (NULL);
fprintf (stderr, "oper=\"%s\"\n", oper);
fflush (NULL);
exit_status = EXIT_FAILURE;
printf("%s: invaild operator\n", oper);
}
void push (stack *the_stack, double number) {
if (the_stack->size == the_stack->capacity) {
printf("%a:stack overflow", number);
}
else {
the_stack->numbers[the_stack->size++]=number;
}
}
void do_binop (stack *the_stack, char oper) {
if ((the_stack->top)<1) {
printf("oper=\"%c\":stack underflow\n", oper);
}
else {
double right = the_stack->numbers[the_stack->size--];
double left = the_stack->numbers[the_stack->size--];
switch (oper) {
case '+': push (the_stack, left + right); break;
case '-': push (the_stack, left - right); break;
case '*': push (the_stack, left * right); break;
case '/': push (the_stack, left / right); break;
}
}
}
void do_print (stack *the_stack) {
if (the_stack->top == -1) {
printf("stack is empty\n");
}
else {
int pos;
for (pos = 0; pos <= the_stack->top; ++pos) {
printf("%a\n",the_stack->numbers[pos]);
}
}
}
void do_clear (stack *the_stack) {
the_stack->top = -1;
}
void do_operator (stack *the_stack, const char *oper) {
switch (oper[0] ) {
case '+': do_binop (the_stack, '+'); break;
case '-': do_binop (the_stack, '-'); break;
case '*': do_binop (the_stack, '*'); break;
case '/': do_binop (the_stack, '/'); break;
case ';': do_print (the_stack); break;
case '#': do_clear (the_stack); break;
default : bad_operator (oper); break;
}
}
int main (int argc, char **argv) {
if (argc != 1) {
fprintf (stderr, "Usage: %s\n", basename (argv[0]));
fflush (NULL);
exit (EXIT_FAILURE);
}
stack the_stack;
the_stack.top = EMPTY;
char buffer[1024];
for (;;) {
int scanrc = scanf ("%1023s", buffer);
if (scanrc == EOF) break;
assert (scanrc == 1);
if (buffer[0] == '#') {
scanrc = scanf ("%1023[^\n]", buffer);
continue;
}
char *endptr;
double number = strtod (buffer, &endptr);
if (*endptr == '\0') {
push (&the_stack, number);
}else if (buffer[1] != '\0') {
bad_operator (buffer);
}else {
do_operator (&the_stack, buffer);
}
}
return exit_status;
}
Let me "teach you to fish":
A debugger will tell you exactly where the fault is. If you're using an IDE (Xcode, Eclipse, VS) it has a nice interface to one and you should use that. If not:
Compile your program with the -g switch: gcc -g mycode.c. This adds debugging information to the executable (makes the debugger give you much better info).
$ gdb my_executable
...
> run
...
Segmentation fault
> where
This will give you the exact location (which function on which line number).
You're never initializing the_stack.size and the_stack.capacity.
stack the_stack;
the_stack.top = EMPTY;
the_stack.size = 0;
the_stack.capacity = SIZE;
It's also not clear what the intended difference between top and size is. The push function increments size, but do_binop and do_print use top, which is never incremented.
The problem is this, in your push() function:
the_stack->numbers[the_stack->size++]=number;
You never initialize the size member of your struct, so it's just random garbage, and you're going way out of bounds on the array. It also doesn't seem to make a lot of sense, since you also have a top member, which won't be updated if you do this. Seems like you should stick to either a top or a size member.

Resources