Edit: I've fixed several things that were pointed out but the real problem remains unsolved.
This bash script:
set -vx
/usr/bin/llvm-gcc-4.2 -ansi -g -o mytest mytest.c
ls -l mytest
./mytest
file mytest
produces this output:
/usr/bin/llvm-gcc-4.2 -ansi -g -o mytest mytest.c
++ /usr/bin/llvm-gcc-4.2 -ansi -g -o mytest mytest.c
ls -l mytest
++ ls -l mytest
-rwxr-xr-x 1 jimslager wheel 37496 May 27 17:26 mytest
./mytest
++ ./mytest
error: unknown command ./mytest
file mytest
++ file mytest
mytest: Mach-O 64-bit executable x86_64
I've extracted this out of something larger that I've been using for several months but have never seen a result like this. How can gcc produce an object with no errors or warnings but the object is unknown?
I'll post test.c if someone asks but it's long and my question seems to me to be independent of what's in test.c.
Edit: Here is the code. Sorry it is so long.
/* Test Exercise 5-10: Write the program myexpr, which evaluates a reverse Polish expression from the command line, where each operator or operand is a separate argument. For example,
* expr 2 3 4 + *
* evaluates 2 x (3+4).
* */
#include <stdio.h>
#include <string.h>
#define MAXLINE 68
#define TABSIZE 8
#define TAB '`'
#define SPACE '-'
#define NEW '\\'
#define TRUE 1
#define FALSE 0
#define IN 1
#define OUT 0
#define FOLDLENGTH 20
#define MAXLEN 12
#define SMALLER(i, j) ((i) > (j) ? (j) : (i))
#define N(c) (c=='\0' ? '\\' : c)
/* #include "subs.c" */
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
int getop(char []);
void push(double);
double pop(void);
double top(void);
void dup(void);
void clear(void);
void stackswap(void);
double atof(char s[]);
int myisdigit(char c);
int myisspace(char c);
/* reverse Polish calculator */
int main(int argc, char *argv[])
{
int type;
double op2;
char s[MAXOP];
while (--argc>0)
while (type = getop(&(*++argv[0])))
printf("Just after while: type = %d, *argv[0] = %s\n", type, *argv);
switch (type) {
case NUMBER:
push(atof(*argv));
printf("NUMBER: atof(*argv[0]) = %g, *argv[0] = %s\n", atof(*argv), *argv);
break;
case '+':
printf("+ detected\n");
push(pop() + pop());
break;
case '*':
printf("* detected\n");
push(pop() * pop());
break;
case '-':
printf("- detected\n");
op2 = pop();
push(pop() - op2);
break;
case '/':
printf("/ detected\n");
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
printf("Modulo detected\n");
op2 = pop();
if (op2 != 0.0)
push((int) pop() % (int) op2);
else
printf("error: zero divisor\n");
break;
case 't':
printf("t detected\n");
printf("%g\n", top());
break;
case 'd':
printf("d detected\n");
dup();
break;
case 's':
printf("s detected\n");
stackswap();
break;
case 'c':
printf("c detected\n");
clear();
break;
case '\n':
printf("\\n detected\n");
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", *argv);
break;
}
return 0;
}
#define MAXVAL 100 /* maximum depth of val stack */
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
/* push: push f onto value stack */
void push(double f)
{
printf("push: Started. f = %g, sp = %d\n", f, sp);
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
printf("push: Finished. f = %g, sp = %d\n", f, sp);
}
/* dup: duplicate top of stack */
void dup(void)
{
printf("dup: Started. top = %g, sp = %d\n", top(), sp);
push(top());
printf("dup: Finished. top = %g, sp = %d\n", top(), sp);
}
/* pop: pop and return top value from stack */
double pop(void)
{
printf("pop: sp = %d, val[--sp] = %g\n", sp, val[sp-1]);
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
/* top: return top value from stack without changing sp */
double top(void)
{
printf("top: sp = %d, val[0] = %g\n", sp, val[0]);
if (sp > 0)
return val[sp-1];
else {
printf("error: stack empty\n");
return 0.0;
}
}
/* stackswap: swap the top 2 values in stack */
void stackswap(void)
{
printf("Starting stackswap: val[sp-1] = %g, val[sp-2] = %g\n", val[sp-1], val[sp-2]);
double op2, op3;
op2 = pop();
op3 = pop();
push(op2);
push(op3);
printf("Finishing stackswap: val[sp-1] = %g, val[sp-2] = %g\n", val[sp-1], val[sp-2]);
}
/* clear: clear the stack */
void clear(void)
{
sp = 0;
}
int getch(void);
void ungetch(int);
/* getop: get next character or numeric operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; /* not a number */
i = 0;
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = getch()))
;
if (c=='.') /* collect fraction part */
while (isdigit(s[++i] = c = getch())) ;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int getch(void) /* get a (possibly pushed-back) character */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) /* push character back on input */
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
/* atof: convert s to double */
double atof(char s[])
{
double val, power, epower, d;
int i, j, sign, esign=0, eval;
printf("atof: s = %s\n", s);
for (i = 0; myisspace(s[i]); i++); /* skip white space */
sign = (s[i] == '-') ? -1 : 1; /* Determine sign and strip it */
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; myisdigit(s[i]); i++) /* Determine value before dec point */
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; myisdigit(s[i]); i++) { /* include value after dec */
val = 10.0 * val + (s[i] - '0');
power *= 10; /* power is where . goes */
}
if (s[i]=='e' || s[i]=='E') { /* Exponential form */
esign = (s[++i]=='-') ? -1 : 1; /* Sign of exponent */
if (s[i]=='+' || s[i]=='-')
i++;
for (epower=0.1, eval=0.0; myisdigit(s[i]); i++) { /* Determine exponent */
eval = 10*eval + (s[i]-'0');
epower *= 10;
}
}
d = (sign*val / power); /* Place dec point in mantissa */
if (esign!=0) { /* If exp form then adjust exponent */
for (j=1; j<=eval; j++) {
d = (esign==1 ? d*10.0 : d/10.0);
}
}
return (d);
}
/* Determine is c is a digit */
int myisdigit(char c)
{
if (c>='0' && c<='9')
return TRUE;
else
return FALSE;
}
/* Returns 1 if c is whitespace, 0 otherwise */
int myisspace(char c)
{
return ((c==' ' || c=='\n' || c=='\t') ? 1 : 0);
}
It should probably be ./test.o to run it. Generally, UNIX systems don't have "." (the current dir) in the PATH by default.
Also, the ".o" extension is slightly misleading, because that is convention for an intermediate object file, not a stand-alone executable like you have produced here.
Make the last line ./test.o and everything should work.
If you only supply the file name but not a path, then only the search paths will be taken into account, and your current working directory in most cases isn't part of them (or rather definitely not, in your example).
. is not in $PATH, so you need to specify the path to the file. ./test.o
.o files are usually not executable; they must be linked before they can be run. Although this is not the case here.
Probably the local directory is not in your path (nor do you want it to be). You should be able to run it with ./test.o. Also, the .o suffix here is strange. You have a dynamically linked executable file, not an object file. (Try file test.o.) On Unix those normally don't have an extension, on Windows they normally have the extension .exe.
Doh! It finally occurred to me what is happening here. This program is exercise 5-10 from K&R which is to revise the Reverse Polish Calculator of page 76 to receive its input from the command line rather than from stdin. I was in the process of doing that when I got the "unknown command" message and thought it was coming from the compiler but it was actually coming from my own code!
Now I will go back and modify it to prefix all error messages with argv[0] (and use this from now on) so that this mistake will never happen again.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
This is program exercise from The C Programming Language by Kernighan and Ritchie (Chap 5).
In this program, when I use '*' as multiplication operator the the pointer **argv points to argv[0] i.e. 1st(Zeroth) argument and reads 1st character 'P' instead of '*'.
Upon execution, with arguments:
./ProgE5-10 +124 -3 * =
it returns incorrect answer instead of -372.
But if replace '*' with 'x' the program works fine.
All other operations (viz. +, -, /, =) are also working fine.
Please tell me why * makes argv to point to Program Name.
//Exercise 5-10. Write the program expr, which evaluates a reverse Polish
//expression from the command line, where each operator or operand is a
//separate argument. For example, expr 2 3 4 + *
//evaluates 2 x C+4).
//For multiplication character '*' is not working
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXLINE 1000
#define NUMBER 0
int sign = 1;
char s[MAXLINE];
void calc (int type);
int main(int argc, char *argv[])
{
if (argc < 4)
printf("Usage: ./<programName> op1 op2 operator\n");
else
{
int i, d;
int c;
while (--argc > 0 && (c = **++argv) != '\n')
{
i = 0;
printf("\nargc = %d\tc = %c:%d", argc, c, c);
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '\n')
{
printf("\nNon-Digit: %c : ", c);
if ((c == '+' || c == '-') && isdigit(d = *++(argv[0])))
{
printf("\tSign");
sign = (c == '-') ? -1 : 1;
c = d;
goto DOWN1;
}
else
{
printf("Operator");
printf("\nRead Operator: %c\n", c);
calc(c);
goto DOWN2; //To avoid re-executing calc(Number) which
//is outside any loop in main when operator
//is read and operation is performed.
}
}
DOWN1: while (isdigit(c = *argv[0]))
{
s[i++] = c;
c = *++(argv[0]);
if (**argv == '.')
{
s[i++] = **argv;
while (isdigit(*++(argv[0])))
s[i++] = **argv;
}
s[i] = '\0';
printf("\ns[] = %s", s);
}
calc(NUMBER); //Outside while to get single push of s[]
//after reading the complete number
DOWN2: ;
}
}
return 0;
}
void push (double f);
double pop(void);
void calc (int type)
{
double op2, res;
switch(type)
{
case NUMBER:
push(sign*atof(s));
sign = 1;
break;
case '+':
push(pop() + pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '*':
push(pop() * pop());
break;
case '/':
op2 = pop();
push(pop() / op2);
break;
case '=':
res = pop();
push(res);
printf("\t\t\t||Result = %lg||\n", res);
break;
case '\n':
break;
default:
printf("\nError: Invalid Operator!\n");
break;
}
}
#define STACKSIZE 1000
double val[STACKSIZE];
int sp = 0;
void push(double f)
{
if (sp >= STACKSIZE)
printf("\nError: Stack Overflow!\n");
else
val[sp++] = f, printf("\nNum %lg Pushed to Stack\n", f);
}
double pop(void)
{
if (sp != 0)
{
double ret = val[--sp];
printf("\nNum %lg Popped from the Stack\n", ret);
return ret;
}
else
{
printf("\nError: Stack Empty!\n");
return 0.0;
}
}
Your shell (e.g. bash) is treating the * character as a glob pattern, which gets replaced with a list of files in the current directory.
$ ls
file1
file2
$ echo *
file1 file2
This is why the * in your case gets replaced with ProgE5-10, which is a file in the current directory.
If you escape the * with a backslash when running your program, or surround it in single or double quotes, this will solve the issue
$ ./ProgE5-10 +124 -3 \* =
I have partially written code that scans in a file full of mathematical expressions in postfix and displays the number to the screen.
While it performs the computation, it will only read in one line and then exit. How do I modify the code to test all arithmetic expressions in the text file?
I've tried commanding the code to exit when EOF, NULL and '\0' are reached, but they all exit at one line.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
int top = -1;
float stack[500];
/* push the given data into the stack */
void push (int data) {
stack[++top] = data;
}
/* Pop the top element from the stack */
float pop () {
float data;
if (top == -1)
return -1;
data = stack[top];
stack[top] = 0;
top--;
return (data);
}
int main() {
char str[500];
FILE *p;
if((p=fopen("testfile1.txt","r"))==NULL){
printf("\n Unable to open file string.txt");
return 1;
}
while(fgets(str,500,p)!='\0'){
float data = -1, operand1, operand2, result;
for (int i = 0; i < strlen(str); i++) {
if (isdigit(str[i])) {
/*
* if the i/p char is digit, parse
* character by character to get
* complete operand
*/
data = (data == -1) ? 0 : data;
data = (data * 10) + (str[i] - 48);
continue;
}
if (data != -1) {
/* if the i/p is operand, push it into the stack */
push(data);
}
if (str[i] == '+' || str[i] == '-'
|| str[i] == '*' || str[i] == '/') {
/*
* if the i/p is an operator, pop 2 elements
* from the stack and apply the operator
*/
operand2 = pop();
operand1 = pop();
if (operand1 == -1 || operand2 == -1)
break;
switch (str[i]) {
case '+':
result = operand1 + operand2;
/* push the result into the stack */
push(result);
break;
case '-':
result = operand1 - operand2;
push(result);
break;
case '*':
result = operand1 * operand2;
push(result);
break;
case '/':
result = operand1 / operand2;
push(result);
break;
}
}
data = -1;
}
if (top == 0)
printf("Output:%3.2f\n", stack[top]);
else
printf("have given wrong postfix expression\n");
return 1;
}
}
Also, the equations I need to read in are:
13 1 - 2 / 3 155 + *
100 100 100 100 + + +
10.33 2 2 2 2 2 * * * * *
30 10 - 10 - 10 - 2 *
300 13.25 - 11 3 - / 4 5 - * 3 /
It works for the first equation only. What can I do in terms of loop structure to make it read all of these equations out of the text file?
Your while loop ends:
return 1;
}
This means it returns from the function after reading the first line of input.
The most plausible fix is to remove the return 1; altogether. An alternative might be:
if (top == 0)
printf("Output:%3.2f\n", stack[top]);
else
{
fprintf(stderr, "have given wrong postfix expression\n");
return 1;
}
}
However, exiting from an interactive calculator on the first mistake is a bit draconian. (It exits the program since the return is leaving main().) Note that errors should usually be reported on stderr. It might be a good idea to echo the faulty expression too:
fprintf(stderr, "have given wrong postfix expression (%s)\n", str);
The code looks ok, but you have a return statement inside the for loop. This return statement will leave the whole main function.
Hi there I was hoping to find help here. I don't understand the following behavior. Please note that this is an exercise from The C Programming Language (4-4).
It is about the double top(void) definition in the stack.c. It should return the top of the stack as a double.
When I try to print it (with the command p) then the number format is not correct.
If I put the printf(...) in the top function itself then the format is correct.
I don't understand why that is.
I am using NetBeans 8.0.2 with default gcc compiler.
main.c
#include <stdio.h>
#include <stdlib.h>
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
int getop(char []);
void push(double);
double pop(void);
/* reverse Polish calculator */
main() {
int type;
double op2;
char s[MAXOP];
while ((type = getop(s)) != EOF) {
switch (type) {
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
op2 = pop();
if (op2 != 0.0)
push((int) pop() % (int) op2);
else
printf("error: zero divisor\n");
break;
case 'p':
printf("\t%.8g\n", top());
break;
case 'd':
push(top());
break;
case 's':
printStack();
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
return 0;
}
stack.c
#include <stdio.h>
#define MAXVAL 100 /* maximum depth of val stack */
int sp = 0;
/* next free stack position */
double val[MAXVAL];
/* value stack */
/* push: push f onto value stack */
void push(double f) {
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can′t push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void) {
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
/* top: return top value from stack */
double top(void) {
if (sp > 0) {
return val[sp - 1];
} else {
printf("error: stack empty\n");
return 0.0;
}
}
/* swap two top values */
void swap(void) {
if (sp > 1) {
double t1 = pop();
double t2 = pop();
push(t1);
push(t2);
} else
printf("error: stack (almost) empty\n");
}
/* clear the stack */
void clear(void) {
sp = 0;
}
/* print the stack */
void printStack(void) {
int i;
for (i = sp - 1; i >= 0; i--)
printf("%g ", val[i]);
}
getop.c
#include <ctype.h>
#include <stdio.h>
#define NUMBER '0' /* signal that a number was found */
int getch(void);
void ungetch(int);
/* getop: get next operator or numeric operand */
int getop(char s[]) {
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.' && c != '-')
return c;
if (c == '-') { // possible negative number
if (!isdigit(s[0] = c = getch())) { // minus operator
ungetch(c);
s[0] = c = '-';
return c;
} else { // negative number
s[0] = '-';
s[1] = c;
i = 1;
}
} else
i = 0; // positive number
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /* collect fraction part */
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
getch.c
#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int getch(void) /* get a (possibly pushed back) character */ {
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) /* push character back on input */ {
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
Your main.c does not know how top is defined. It decides on a default return value of int, which leads to undefined behaviour when printing it with a format designed for double. If you enable warnings, which you should, you'll get something like "Implicit declaration of top".
You have written the declarations of the stack functions push and pop at the top of main.c, but not the declaration of top.
Including the required prototypes by hand is not good practice. It is better to declare the interface of a compilation unit in a header file:
// stack.h
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
void push(double f);
double pop(void);
double top(void);
void swap(void);
#endif
Include that header file from the code where you wish to use the interface. You will always have the correct and up-to-date version.
Include the header from stack.c, too, to ensure that the published interface and the actual implementation are consistent.
%g prints shorter of the two representations: f or e .
example:
1) printf( "%g", 3.1415926 );
OUTPUT: 3.1515926
2) printf( "%g", 93000000.0 );
OUTPUT: 9.3e+07
Where scientific notation is most appropriate.
I'm not sure where to post this but I think I found a pretty major bug in K&R's polish calculator program. Basically, when you perform an operation, two values get popped while only the result gets pushed. The problem is that the result isn't getting pushed to the top of the stack! Here's an illustration:
The full code for the polish calculator provided by the textbook is shown below:
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
int getop(char []);
void push(double);
double pop(void);
/* reverse Polish calculator */
main()
{
int type;
double op2;
char s[MAXOP];
while ((type= getop(s)) != EOF) {
switch (type) {
case NUMBER:
push(atof(s));
break;
case '+':
push (pop() + pop()) ;
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
system("Pause");
return 0;
}
#define MAXVAL 100 /* maximum depth of val stack */
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
/* push: push f onto value stack */
void push(double f)
{
if ( sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full. can't push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
#include <ctype.h>
int getch(void);
void ungetch(int);
/* getop: get next operator or numeric operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; /* not a number */
i = 0;
if (isdigit(c)) /*collect integer part*/
while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /*collect fraction part*/
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int getch(void) /* get a (possibly pushed back) character */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) /* push character back on input */
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
If you want to check for yourself, all I did was add
static int pass = 0;
int i, check;
i = check = 0;
inside the while loop in main() and
if(!check) {
printf("pass #%d\n",pass++);
while(val[i] != '\0') {
printf("val[%d]: %.2f\n",i,val[i]);
++i;
}
}
at the end of the while loop, just after the switch statement. I also put check = 1; in the case for '\n'.
As a possible workaround I re-wrote the pop function such that popped values are removed from the val array as soon as they are accessed. So instead of
double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
you'd have something like
double pop(void)
{
if (sp > 0) {
double temp = val[--sp];
val[sp] = '\0';
return temp;
}
else {
printf("error: stack empty\n");
return 0.0;
}
}
I also re-wrote the push function to ensure that values are always pushed to the end of the val array. So instead of
void push(double f)
{
if ( sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full. can't push %g\n", f);
}
you'd have
void push(double f)
{
if ( sp < MAXVAL) {
while (val[sp] != '\0')
++sp;
val[sp++] = f;
}
else
printf("error: stack full. can't push %g\n", f);
}
Even with these changes, I still had to re-write
case '\n':
printf("\t%.8g\n", pop());
break;
to retrieve the value at the top of the stack without popping it, which required replacing the printf statement with a simple function like
void print_top(void)
{
int i = 0;
while( val[i] != '\0' )
++i;
--i;
printf("\t%.8g\n",val[i]);
}
Only then does the polish calculator seem to function as intended, at least in terms of what the stack is doing behind the scenes. You can try it out for yourself with the modified code:
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <ctype.h>
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
#define MAXVAL 100 /* maximum depth of val stack */
int getop(char []);
void push(double);
double pop(void);
void print_top(void);
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
/* reverse Polish calculator */
main()
{
int type;
double op2;
char s[MAXOP];
while ((type= getop(s)) != EOF) {
static int pass = 0;
int i, check;
i = check = 0;
switch (type) {
case NUMBER:
push(atof(s));
break;
case '+':
push (pop() + pop()) ;
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '\n':
print_top();
check = 1;
break;
default:
printf("error: unknown command %s\n", s);
break;
}
if(!check) {
printf("pass #%d\n",pass++);
while(val[i] != '\0') {
printf("val[%d]: %.2f\n",i,val[i]);
++i;
}
}
}
system("Pause");
return 0;
}
/* push: push f onto value stack */
void push(double f)
{
if ( sp < MAXVAL) {
while (val[sp] != '\0')
++sp;
val[sp++] = f;
}
else
printf("error: stack full. can't push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void)
{
if (sp > 0) {
double temp = val[--sp];
val[sp] = '\0';
return temp;
}
else {
printf("error: stack empty\n");
return 0.0;
}
}
int getch(void);
void ungetch(int);
/* getop: get next operator or numeric operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; /* not a number */
i = 0;
if (isdigit(c)) /*collect integer part*/
while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /*collect fraction part*/
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int getch(void) /* get a (possibly pushed back) character */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) /* push character back on input */
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
void print_top(void)
{
int i = 0;
while( val[i] != '\0' )
++i;
--i;
printf("\t%.8g\n",val[i]);
}
Note that I had to move most of my #define statements and prototype declarations to the beginning in order to accommodate for the debugging printfstatement at the end of main().
*Edited out some of my audacious claims :P
You're thinking of the stack backwards - the top of the stack is in the highest valid index, not in val[0]. This behaviour is evident when you look at the pushes of the operands. Your output:
3 4 +
pass #0
val[0]: 3.00
pass #1
val[0]: 3.00
val[1]: 4.00
First, the 3 is pushed - going onto the top of the (previously empty) stack - it's in slot 0. Next 4 is pushed. As you can see, it goes into val[1], clearly showing that val[0] is not the top of the stack in this case.
You're printing the stack incorrectly, which is confusing you further. Change your print loop to:
while (i < sp) {
printf("val[%d]: %.2f\n",i,val[i]);
++i;
}
That is, print only the valid entries in the stack, and you'll see your error.
Your current comparison is looking for a 0 entry on the stack, which isn't how the program is identifying the free entries. That's what the sp variable is used for. In addition to looking for the wrong thing, it's doing it in a bizarro way - val is a an array of floating-point numbers - why are you comparing to a character literal \0?
Here's the complete corrected output:
3 4 +
pass #0
val[0]: 3.00
pass #1
val[0]: 3.00
val[1]: 4.00
pass #2
val[0]: 7.00
7
Now, you see the correct output - both the 3.00 and 4.00 are popped, and 7.00 is pushed back onto the stack. It's now the only valid entry.
Nah. It's just that the stack grows upwards, i. e. val[0] is the bottom (and the top too if there's only one element). And at the time you print the result, val[1] is invalid, it has already been popped.
There is no bug in the code given in K&R for reverse polish calculator.
It works only when the input is given in a single line.
If you press the enter then compiler will read '\n',which results in (case '\n':) of the code and the pop function will be called.
Code result is in the given image:
I'm doing a homework assignment in C. I have to build a calculator that takes in RPN, converts it to a double, adds / removes it from stack and prints what's left on the stack.
Everything seems to be going well until I run it. Upon entering my input, the char[] gets successfully converted to double (or so i think) and somewhere along the way (maybe in getop()) does the program think that i'm not entering digits. Here is the code and the output.
#include <stdio.h>
#define MAXOP 100 /* maximum size of the operand of operator */
#define NUMBER '0' /* signal that a number was found */
int getOp(char []); /* takes a character string as an input */
void push(double);
double pop(void);
double asciiToFloat(char []);
/* reverse polish calculator */
int main()
{
int type;
double op2;
char s[MAXOP];
printf("Please enter Polish Notation or ^d to quit.\n");
while ((type = getOp(s)) != EOF) {
switch (type) {
case NUMBER:
push(asciiToFloat(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error : zero divisor!\n");
break;
case '\n':
printf("\t%.2f\n", pop()); /* this will print the last item on the stack */
printf("Please enter Polish Notation or ^d to quit.\n"); /* re-prompt the user for further calculation */
break;
default:
printf("error: unknown command %s.\n", s);
break;
}
}
return 0;
}
#include <ctype.h>
/* asciiToFloat: this will take ASCII input and convert it to a double */
double asciiToFloat(char s[])
{
double val;
double power;
int i;
int sign;
for (i = 0; isspace(s[i]); i++) /* gets rid of any whitespace */
;
sign = (s[i] == '-') ? -1 : 1; /* sets the sign of the input */
if (s[i] == '+' || s[i] == '-') /* excludes operands, plus and minus */
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] = '.')
i++;
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
return sign * val / power;
}
#define MAXVAL 100 /* maximum depth of value stack */
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
/* push: push f onto value stack */
void push(double f)
{
if (sp < MAXVAL) {
val[sp++] = f; /* take the input from the user and add it to the stack */
printf("The value of the stack position is %d\n", sp);
}
else
printf("error: stack full, cant push %g\n", f);
}
/* pop: pop and return the top value from the stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
#include <ctype.h>
int getch(void);
void ungetch(int);
/* getOp: get next operator or numeric operand */
int getOp(char s[])
{
int i;
int c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.') {
printf("Neither a digit or a decimal.\n");
return c; /* neither a digit nor a decimal */
}
i = 0;
if (isdigit(c)) /* grab the integer */
while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /* grab the fraction */
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buffer */
/* getch: get a number that may or may not have been pushed back */
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
/* ungetch: if we read past the number, we can push it back onto input buffer */
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch: to many characters.\n");
else
buf[bufp++] = c;
}
Output :
Please enter Polish Notation or ^d to quit.
123
The value of the stack position is 1
Neither a digit or a decimal.
123.00
Please enter Polish Notation or ^d to quit.
Any thoughts regarding what's going on will be super helpful. It seems like then number is properly getting passed in, properly formatted from char to double, and then something goes wrong.
Thank you.
Rock
Change
printf("Neither a digit or a decimal.\n");
to
printf("Neither a digit or a decimal: %d 0x%x.\n", c, c);
so you can see what is causing the message.
Your output shows that getch() is returning the line feed ("\n", 0x0A) at the end of the line. Also, unless you were required to write asciiToFloat() for your homework assignment, you should use atof() or strtod() (both declared in "stdlib.h") from the Standard C Library. They are (usually?) implemented to avoid loss of precision and accuracy during the conversion; repeatedly multiplying by 10 causes a loss of same. Nice looking code, otherwise! :)