您的位置:首页 > 其它

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

2018-01-04 17:41 204 查看
练习 4-5

给计算器程序增加访问 sin、exp 与 pow 等库函数的操作。有关这些库函

数的详细信息,参见附录 B.4 节中的头文件math.h。

代码重构了一下,

将功能性的指令和函数调用从 main 里拿出来了

getop 函数也简单的改了一下

执行操作 :

/*根据 s 执行操作*/
void command(char s[])
{
double op2;

if (strstr(s, "copy") != -1)
{
op2 = copy();
if (op2 != 0)
printf("%g to be copied\n", op2);
}
else if (strstr(s, "clear") != -1)
{
op2 = clear();
if (op2 != 0)
printf("The %d elements were deleted\n", (int)op2);
}
else if (strstr(s, "print") != -1)
printtop();
else if (strstr(s, "swop") != -1)
swop();
else if (strstr(s, "del") != -1)
{
op2 = pop();
printf("%g deleted\n", op2);
}
else if (strstr(s, "count") != -1)
{
printf("%d\n", count());
}
else
printf("error: unknown command %s\n", s);
}


调用函数 :

/*根据函数名 s 调用函数*/
void function(char s[])
{
double op;

if (strstr(s, "sin") != -1)
{
if (count() >= 1)
push(sin(pop()));
else
argerror(1, count());
}
else if (strstr(s, "exp") != -1)
{
if (count() >= 1)
push(exp(pop()));
else
argerror(1, count());
}
else if (strstr(s, "pow") != -1)
{
if (count() >= 2)
{
op = pop();
push(pow(pop(), op));
}
else
argerror(2, count());
}
else
printf("error: unknown function name %s\n", s);
}


getop 函数 :

int getop(char s[])
{
int i, c, c2;
while (isspace(c = getch())) //去除多余的空白字符
;
i = 0;

if (c == '~' || c == '$') //这是一个指令或函数
{
c2 = c;
while (!isspace(c = getch()) && c != EOF) // 将空白符前的字符看作 指令 或 函数名
s[i++] = c;
s[i] = '\0';

return c2;
}
else if ((c == '-' || c == '+') && isdigit(peekch()))// '-'或'+' 下一位的值若是数字,则当做符号位
{
s[i++] = c;
c = getch();
}

if (!isdigit(c))
return c;
else
{
s[i++] = c;
//数字的格式为 "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 (!isspace(c))
ungetch(c);

return NUMBER;
}

}


main :

main()
{
int type;
double op2, op3;
char s[MAXOP];

while ((type = getop(s)) != EOF)
switch (type)
{
case NUMBER:
push(atof1(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();

4000
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 '~':
command(s);
break;
case '$':
function(s);
break;
case ' ': //空白字符不处理
case '\n':
case '\t':
break;
default:
printf("error: unknown input %s\n", s);
break;
}
}


完整代码 :

/*练习 4-5 给计算器程序增加访问 sin、exp 与 pow 等库函数的操作。有关这些库函
数的详细信息,参见附录 B.4 节中的头文件<math.h>。*/

#include <stdio.h>
#include <math.h>
//--------------main------------------------------------------------

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

#define CMD '~' //命令符号,表示后面跟着的是命令
#define FUNC '$' //函数符号,表示后面跟着的是函数

int getop(char[]);
void push(double d);
double pop(void);
void printtop(void);
double copy(void);
double peek(void);
int swop(void);
int clear(void);
int count(void);

void command(char s[]);
void function(char s[]);

double atof1(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(atof1(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 '~':
command(s);
break;
case '$':
function(s);
break;
case ' ': //空白字符不处理
case '\n':
case '\t':
break;
default:
printf("error: unknown input %s\n", s);
break;
}

}

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

//-----------处理命令与调用函数---------------------------------------------------

int strstr(char s[], char t[]);
void argerror(int, int);

/*根据 s 执行操作*/ void command(char s[]) { double op2; if (strstr(s, "copy") != -1) { op2 = copy(); if (op2 != 0) printf("%g to be copied\n", op2); } else if (strstr(s, "clear") != -1) { op2 = clear(); if (op2 != 0) printf("The %d elements were deleted\n", (int)op2); } else if (strstr(s, "print") != -1) printtop(); else if (strstr(s, "swop") != -1) swop(); else if (strstr(s, "del") != -1) { op2 = pop(); printf("%g deleted\n", op2); } else if (strstr(s, "count") != -1) { printf("%d\n", count()); } else printf("error: unknown command %s\n", s); }

/*根据函数名 s 调用函数*/ void function(char s[]) { double op; if (strstr(s, "sin") != -1) { if (count() >= 1) push(sin(pop())); else argerror(1, count()); } else if (strstr(s, "exp") != -1) { if (count() >= 1) push(exp(pop())); else argerror(1, count()); } else if (strstr(s, "pow") != -1) { if (count() >= 2) { op = pop(); push(pow(pop(), op)); } else argerror(2, count()); } else printf("error: unknown function name %s\n", s); }

/*输出参数不足错误信息,ac 为需要的参数个数, ac2 为实际参数数*/
void argerror(int ac, int ac2)
{
printf("Expect %d parameters, %d elements in the stack\n", ac, ac2);
}
//--------------------------------------------------------------

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

int getch(void);
void ungetch(int);
int peekch(void);

/*将输入放进 s 中,
类型------返回值
数字------NUMBER
指令------'~'
函数名----'$'
其他------原字符
*/
int getop(char s[]) { int i, c, c2; while (isspace(c = getch())) //去除多余的空白字符 ; i = 0; if (c == '~' || c == '$') //这是一个指令或函数 { c2 = c; while (!isspace(c = getch()) && c != EOF) // 将空白符前的字符看作 指令 或 函数名 s[i++] = c; s[i] = '\0'; return c2; } else if ((c == '-' || c == '+') && isdigit(peekch()))// '-'或'+' 下一位的值若是数字,则当做符号位 { s[i++] = c; c = getch(); } if (!isdigit(c)) return c; else { s[i++] = c; //数字的格式为 "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 (!isspace(c)) ungetch(c); return NUMBER; } }
#define BUFSIZE 100

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

/*弹出缓冲栈中最上面的字符,若缓冲区为空,则返回控制台输入的字符*/
int getch(void)
{
if (bufp > 0)
return buf[--bufp];
else
return getchar();
}

/*将 c 压入缓冲区栈*/
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}

/*返回缓冲栈中最上面的字符的值,若缓冲区为空,则返回控制台输入的字符并将其压入缓冲栈*/
int peekch(void)
{
int c;
if (bufp > 0)
return buf[bufp - 1];
else
{
buf[bufp++] = c = getchar();;
return getchar();
}
}

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

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

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

int op = 0;
double val[MAXVAL];

/*将 d 压入栈顶*/
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;
}

/*打印栈顶元素*/
void printtop(void)
{
if (op > 0)
printf("%g\n", val[op - 1]);
else
printf("error: stack empty\n");
}

/*复制栈顶元素 如果成功返回被复制元素的值*/
double copy(void)
{
double n;
if (op > 0)
{
push(n = val[op - 1]);
return n;
}
else
{
printf("error: stack empty\n");
return 0.0;
}
}

/*获得栈顶元素的值*/
double peek(void)
{
if (op > 0)
return val[op - 1];
else
printf("error: stack empty\n");
return 0.0;
}

/*交换栈顶的两个元素的值 成功返回 1 ,否则返回 0 */
int swop()
{
double t;
if (op > 1)
{
t = val[op - 1];
val[op - 1] = val[op - 2];
val[op - 2] = t;
return 1;
}
else
{
printf("The number of elements in the stack is insufficient\n");
return 0;
}
}

/*清空栈 返回被清空的元素数*/
int clear()
{
int n;
if (op > 0)
{
n = op;
op = 0;
return n;
}
else
{
printf("error: stack empty\n");
return 0;
}
}

/*返回栈中元素的数量*/
int count(void)
{
return op;
}
//--------------------------------------------------------------

//---------------字符判断与处理-----------------------------------------------
/*将字符串转换成浮点型*/
double atof1(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;
}

/*若传入的字符为空白字符返回 1, 否则返回 0 */
int isspace(int x)
{
return (x == ' ' || x == '\t' || x == '\n') ? 1 : 0;
}

/*若传入的字符为数字返回 1, 否则返回 0 */
int isdigit(int x)
{
return (x >= '0' && x <= '9') ? 1 : 0;
}

/*返回 s 中 t 的位置,若没有则返回 -1*/
int strstr(char s[], char t[])
{
int i, j, k;
for (i = 0; s[i] != '\0'; i++)
{
for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
;
if (t[k] == '\0')
return i;
}
return -1;
}
//--------------------------------------------------------------


待补充

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