ch4-files (Calculator) - Headers, C files, makefile

Chapter_4     Exercise_4-10 Exercise_4-11







files     K&R, p. 82




The folder files contains the following files (download):
readme.txt     makefile     compute.txt
number.h     getop.h     calc.h
getch.c     stack.c     getop.c     calc.c




readme.txt         download


Compile (and assemble) source files (without linking):
gcc -c getch.c
gcc -c stack.c
gcc -c getop.c
gcc -c calc.c

Link all object files (*.o) and output executable `calc':
gcc *.o -o calc

You can also use the makefile:
make
gcc -c getch.c
gcc -c stack.c
gcc -c getop.c
gcc -c calc.c
gcc *.o -o calc

Delete object files:
rm *.o

Or:
make clean

Run program with input from the keyboard:
./calc

Run program with input from a file:
./calc < compute.txt





makefile         download


all: calc
calc: getch.o stack.o getop.o calc.o
gcc *.o -o calc
getch.o: getch.c
gcc -c getch.c
stack.o: stack.c
gcc -c stack.c
getop.o: number.h getop.h getop.c
gcc -c getop.c
calc.o: number.h calc.h calc.c
gcc -c calc.c
clean:
rm *.o





compute.txt         download


1 2 +
1 2 * 3 + 5 -
-1 2 +
-1 -2 -
4 3 %
2 0 %
1 3 /
1 0 /











number.h         download


#define NUMBER '0' // signal that a number has been found




getop.h         download


int getch(void); // get the next input character
void ungetch(int); // push the last read character back on input




calc.h         download


int getop(char []); // get the next operand or operator

void push(double); // push operand on stack
double pop(void); // pop operand from stack











getch.c         download


#include <stdio.h> // for getchar(), EOF

// buffer for ungetch():
int buf = EOF-1; // not a real character, not even EOF

int getch(void) // get a (possibly pushed-back) character
{
if (buf < EOF)
{
return getchar();
}

int temp = buf; // buf >= EOF
buf = EOF-1; // reset buf

return temp;
}
// push character back on input (make it available for the next getch()):
void ungetch(int c)
{
buf = c;
}





stack.c         download


#include <stdio.h> // for printf()

#define MAXVAL 100 // stack size
// stack pointer (0 is top of stack):
int sp = 0; // next free stack position
double val[MAXVAL]; // value stack

void push(double f) // push f on (top of) stack
{
if (sp < MAXVAL) {val[sp++] = f;}
else {printf("Error: stack full, can't push %g\n", f);}
}

double pop(void) // pop and return top value from stack
{
if (sp > 0) {return val[--sp];}
else
{
printf("Error: stack empty\n");
return 0.0;
}
}





getop.c         download


#include <ctype.h> // for isdigit()
#include "number.h" // for NUMBER
#include "getop.h" // for getch(), ungetch()

int getop(char s[]) // get next operator or numeric operand
{
int c, i;

while ((s[0] = c = getch()) == ' ' || c == '\t') // skip beginning whitespace (' ', '\t')
{} // last value read in s[0] is not ' ' or '\t', but could be '\n' or EOF
s[1] = '\0'; // end string

if (!isdigit(c) && c != '.' && c != '+' && c != '-')
{return c;} // not a number, probably an operator (or '\n' or EOF)
// here c is digit or '.' or '+' or '-'

i = 0;

if (c == '+' || c == '-') // unary or binary sign
{
c = getch();
if (!isdigit(c) && c != '.')
{
ungetch(c);
return s[0]; // binary '+' or '-'
}
else // c is digit or '.'
{
if (s[i] == '-') {i++;} // s[0]
// if (s[i] == '+') {} // skip adding '+' to s[]
s[i] = c; // digit or '.'
}
}

if (isdigit(c)) // collect integer part
{ // s[i] contains c (digit)
while (isdigit(s[++i] = c = getch()))
{}
} // here s[i] is not a digit
if (c == '.') // collect fraction part
{ // s[i] contains c (s[i] == '.')
while (isdigit(s[++i] = c = getch()))
{}
} // here s[i] is not a digit
s[i] = '\0'; // end string containing number (operand)

ungetch(c); // if (c == EOF), the next getop() will return EOF, ending the program

return NUMBER;
}











calc.c         download


#include <stdio.h> // for printf(), EOF
#include <stdlib.h> // for atof()

#include "number.h" // for NUMBER
#include "calc.h" // for getop(), push(), pop()

#define MAXOP 100 // max size of operand or operator

int main()
{
int type, i1, i2;
double op2; // second operand for -, /, %
char s[MAXOP]; // operand or operator

while((type = getop(s)) != EOF)
{ // nonempty line ending with EOF will not be executed
switch(type)
{
case NUMBER :
push(atof(s));
break;
case '+' :
push(pop() + pop());
break;
case '-' :
op2 = pop();
push(pop() - op2);
break;
case '*' :
push(pop() * pop());
break;
case '/' :
op2 = pop();
if (op2 != 0.0)
{push(pop() / op2);}
else {printf("Error: zero divisor\n");}
break;
case '%' :
i2 = pop(); // automatic conversions
i1 = pop(); // from double to int
if (i2 != 0.0)
{push(i1 % i2);} // automatic conversion from int to double, argument of push()
else {printf("Error: zero divisor\n");}
break;
case '\n' :
printf("\t%.8g\n", pop()); // top of stack
break;
default :
printf("Unknown command: %s\n", s);
break;
}
}

return 0;
}
/*
gcc -c getch.c // compile (and assemble) without linking
gcc -c stack.c // compile (and assemble) without linking
gcc -c getop.c // compile (and assemble) without linking
gcc -c calc.c // compile (and assemble) without linking
gcc *.o -o calc // link all object files (*.o) and output executable `calc'
./calc // run program with input from the keyboard
1 2 +
3
1 2 + 3 * 4 /
2.25
-1 2 +
1
-1 -2 +
-3
-1 2 + 3 *
3
2 0 /
Error: zero divisor
2 // pop() called by '\n' returns first operand, still on stack
1 2 /
0.5
2 3 %
2
4 2 %
0
4 1 %
0
4 3 %
1
4 0 %
Error: zero divisor
Error: stack empty // nothing pushed, '\n' calls pop():
0 // value returned by pop() for an empty stack
a b +
Unknown command: a
Unknown command: b
Error: stack empty // nothing pushed, pop() called by +
Error: stack empty // pop() called by '\n'
0 // value returned by pop() for an empty stack
1 2 9
9 // pop() called by '\n'
+
3 // 1 + 2
1 2 c
Unknown command: c
2 // pop() called by '\n'
3 +
4 // 1 + 3
CTRL^D (EOF) or CTRL^C in Linux, CTRL^Z + Enter in Windows

// Run program with input from a file:
./calc < compute.txt
3 // 1 2 +
0 // 1 2 * 3 + 5 -
1 // -1 2 +
1 // -1 -2 -
1 // 4 3 %
Error: zero divisor // 2 0 %
Error: stack empty // nothing pushed, '\n' calls pop():
0 // value returned by pop() for an empty stack
0.33333333 // 1 3 /
Error: zero divisor // 1 0 /
1 // pop() called by '\n' returns first operand, still on stack
*/









Chapter_4     Exercise_4-10 BACK_TO_TOP Exercise_4-11



Comments

Popular posts from this blog

Contents

Blogger Page Margins in Contempo