您的位置:首页 > 编程语言 > C语言/C++

《C程序设计语言》练习 4-3

2018-01-04 09:52 232 查看
练习 4-3

在有了基本框架后,对计算器程序进行扩充就比较简单了。在该程序中加入

取模(%)运算符,并注意考虑负数的情况。

然而书上那个代码并不能用,

可能是因为我是windows系统的原因

windows的控制台敲回车才能输入,但回车自带换行

所以我改了一下代码

主要改的是 main 函数 和 getop函数

我在处理取模运算时,要判断两个数是否都为整形,所以加了一个变量

main()
{
int type;
double op2, op3;
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();
op3 = pop();
if (op2 != (int)op2 || op3 != (int)op3) //要保证取模的两个数都是整数
printf("error: Only integers can get the modulus\n");
else if (op2 == 0)
printf("error: zero divisor\n");
else if (op2 < 0)
push(0);
else
push((int)op3 % (int)op2);
break;
case '=': //等于号用来取出栈中最上面的值
printf("\t%.8g\n", pop());
break;
case '.':
printf("error: There's no number in front of the decimal point");
break;
case ' ' : //空白字符不处理
case '\n':
case '\t':
break;
default:
printf("error: unknown command %s\n", s);
break;
}

}

int getop(char s[])
{
int i, c, c2;
while ((c = getch()) == ' ' || c == '\n' || c == '\t') //去除多余的空白字符
;
if (c == '-' || c == '+')   // '-' 和 '+' 有可能作为符号位
if (isdigit(c2 = getch()))//所以读取下一位,若是数字,则当做符号位
{
s[i++] = c;
c = c2;
}
else
{
ungetch(c2);
return c;
}

if (isdigit(c))
{
s[0] = c;
i = 1;
//数字的格式为 "xxx.xxx"
// x 是数字
while (isdigit(c = getch()))
s[i++] = c;
if (c == '.')
{
s[i++] = c;
while (isdigit(c = getch()))
s[i++] = c;
}

//数字结束
s[i] = '\0';
if (c != '\n' && c!= ' ' && c != '\t')
ungetch(c);

return NUMBER;
}
else
return c;
}


我将空白字符作为分隔符看待

比如 想计算 11 + 1 等于几

就输入 11’ ‘1 + =

控制台便会打印 2

要注意的是 ‘+’ 和 ‘-’ 如果后面直接跟数字,会被看作符号位

完整代码 :

/*练习 4-3 在有了基本框架后,对计算器程序进行扩充就比较简单了。在该程序中加入
取模(%)运算符,并注意考虑负数的情况。*/

#include <stdio.h>

//--------------main------------------------------------------------

#define MAXOP 100 //操作数与操作符的最大值
#define NUMBER '0' //getop得到数字或小数点时返回的值

int getop(char[]);
void push(double);
double pop(void);

double atof(char s[]);
int isspace(int);
int isdigit(int);

main()
{
int type;
double op2, op3;
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();
op3 = pop();
if (op2 != (int)op2 || op3 != (int)op3) //要保证取模的两个数都是整数
printf("error: Only integers can get the modulus\n");
else if (op2 == 0)
printf("error: zero divisor\n");
else if (op2 < 0)
push(0);
else
push((int)op3 % (int)op2);
break;
case '=': //等于号用来取出栈中最上面的值
printf("\t%.8g\n", pop());
break;
case '.':
printf("error: There's no number in front of the decimal point");
break;
case ' ' : //空白字符不处理
case '\n':
case '\t':
break;
default:
printf("error: unknown command %s\n", s);
break;
}

}

//--------------------------------------------------------------

//-------------获取字符-------------------------------------------------

int getch(void);
void ungetch(int);
int getop(char s[])
{
int i, c, c2;
while ((c = getch()) == ' ' || c == '\n' || c == '\t') //去除多余的空白字符
;
if (c == '-' || c == '+')   // '-' 和 '+' 有可能作为符号位
if (isdigit(c2 = getch()))//所以读取下一位,若是数字,则当做符号位
{
s[i++] = c;
c = c2;
}
else
{
ungetch(c2);
return c;
}

if (isdigit(c))
{
s[0] = c;
i = 1;
//数字的格式为 "xxx.xxx"
// x 是数字
while (isdigit(c = getch()))
s[i++] = c;
if (c == '.')
{
s[i++] = c;
while (isdigit(c = getch()))
s[i++] = c;
}

//数字结束
s[i] = '\0';
if (c != '\n' && c!= ' ' && c != '\t')
ungetch(c);

return NUMBER;
}
else
return c;
}

#define BUFSIZE 100

char buf[BUFSIZE]; //缓存的字符数组
int bufp = 0; //缓存数组指针

int getch(void)
{
if (bufp > 0)
return buf[--bufp];
else
return getchar();
}
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}

//--------------------------------------------------------------

//----------------栈操作----------------------------------------------

#define MAXVAL 100 //栈的最大长度

int op = 0;
double val[MAXVAL];

void push(double d)
{
if (op < MAXVAL)
val[op++] = d;
else
printf("error: stack full, can't push %g\n", d);
}

double pop(void)
{
if (op > 0)
return val[--op];
else
printf("error: stack empty\n");
return 0.0;
}

//--------------------------------------------------------------

//---------------转换成数字-----------------------------------------------

double atof(char s[])
{
double power, val;
int sign, i, sign2, j, n;
for (i = 0; isspace(s[i]); i++)
;

sign = (s[i] == '-') ? -1 : 1;

if (s[i] == '-' || s[i] == '+')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = val * 10 + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++)
{
val = val * 10 + (s[i] - '0');
power *= 10;
}

if (s[i] == 'e' || s[i] == 'E')
{
i++;
sign2 = (s[i] == '-') ? 1 : 0;
if (s[i] == '-' || s[i] == '+')
i++;

for (n = 0; isdigit(s[i]); i++)
n = n * 10 + (s[i] - '0');

for (j = 0; j < n; j++)
power = (sign2) ? (power * 10) : (power / 10);

}
return val * sign / power;
}
int isspace(int x)
{
return (x == ' ' || x == '\t' || x == '\n') ? 1 : 0;
}
int isdigit(int x)
{
return (x >= '0' && x <= '9') ? 1 : 0;
}

//--------------------------------------------------------------


发现 getop函数在处理 ‘+’ 和 ‘-’ 时写的代码有问题,

已修改

by 2018-1-4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息