Skip to content

Commit 827e0fa

Browse files
committed
Initial commit
This is a scanf and sscanf version of getop.
1 parent 51c60ab commit 827e0fa

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

chapter07/7-5a.c

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Exercise 7-5. Rewrite the postfix calculator of Chapter 4 to use scanf
3+
* and/or sscanf to do the input and number conversion.
4+
*
5+
* Note: scanf and sscanf version
6+
*
7+
* Faisal Saadatmand
8+
*/
9+
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <string.h>
13+
14+
#define MAXOP 100 /* max size of operand or operator */
15+
#define NUMBER '0' /* signal that a number was found */
16+
#define MAXVAL 100 /* maximum depth of val stack */
17+
#define BUFSIZE 100
18+
19+
/* functions */
20+
void push(double);
21+
double pop(void);
22+
int getop(double *);
23+
void ungetns(char *, int );
24+
25+
/* globals */
26+
int sp = 0; /* next free stack position */
27+
double val[MAXVAL]; /* value stack */
28+
29+
/* push: push f onto value stack */
30+
void push(double f)
31+
{
32+
if (sp < MAXVAL)
33+
val[sp++] = f;
34+
else
35+
printf("error: stack full, can't push %g\n", f);
36+
}
37+
38+
/* pop: pop and return top value from stack */
39+
double pop(void)
40+
{
41+
if (sp > 0)
42+
return val[--sp];
43+
else {
44+
printf("error: stack empty\n");
45+
return 0.0;
46+
}
47+
}
48+
49+
/* getop: get next operator or numeric operand - scanf and sscanf version */
50+
int getop(double *number)
51+
{
52+
char c;
53+
int n; /* number of reaf characters */
54+
static char s[MAXOP];
55+
56+
if (scanf("%c", &c) < 0)
57+
return EOF;
58+
59+
if (c == '\n')
60+
return c;
61+
62+
ungetc(c, stdin);
63+
scanf("%s", s); /* parse string from input stream */
64+
if (!sscanf(s, "%lf %n", number, &n)) { /* match number from string */
65+
sscanf(s, "%c", &c); /* not a number */
66+
if (strlen(s) > 1) /* check for unread characters */
67+
ungetns(s, 1);
68+
return c;
69+
}
70+
71+
if (n != (int) strlen(s)) /* check unread char from match */
72+
ungetns(s, n);
73+
74+
return NUMBER;
75+
}
76+
77+
/* ungetns: push back a string starting at position n onto input stream */
78+
void ungetns(char *s, int n)
79+
{
80+
int i;
81+
82+
for (i = strlen(s) - 1 ; i >= n; --i)
83+
ungetc(s[i], stdin);
84+
}
85+
86+
/* reverse polish calculator - scanf/sscanf version */
87+
int main(void)
88+
{
89+
int type;
90+
double op2, op;
91+
92+
while ((type = getop(&op)) != EOF) {
93+
switch (type) {
94+
case (NUMBER):
95+
push(op);
96+
break;
97+
case '+':
98+
push(pop() + pop());
99+
break;
100+
case '*':
101+
push(pop() * pop());
102+
break;
103+
case '-':
104+
op2 = pop();
105+
push(pop() - op2);
106+
break;
107+
case '/':
108+
op2 = pop();
109+
if (op2 != 0.0)
110+
push(pop() / op2);
111+
else
112+
printf("error: zero division\n");
113+
break;
114+
case '\n':
115+
printf("\t%.8g\n", pop());
116+
break;
117+
default:
118+
printf("error: unknown command %c\n", type);
119+
break;
120+
}
121+
}
122+
return 0;
123+
}

0 commit comments

Comments
 (0)