《C程序设计语言》练习 4-5
2018-01-04 17:41
204 查看
练习 4-5
给计算器程序增加访问 sin、exp 与 pow 等库函数的操作。有关这些库函
数的详细信息,参见附录 B.4 节中的头文件math.h。
代码重构了一下,
将功能性的指令和函数调用从 main 里拿出来了
getop 函数也简单的改了一下
执行操作 :
调用函数 :
getop 函数 :
main :
完整代码 :
待补充
by 2018-1-4
给计算器程序增加访问 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程序设计语言》练习 2-8
- 《C程序设计语言》练习 3-3
- 《C程序设计语言》学习笔记——练习1-20
- 《C程序设计语言》学习笔记——练习3-1
- 《C程序设计语言》练习 2-6
- 《C程序设计语言》练习 3-4
- 《C程序设计语言》练习 1-12
- 《C程序设计语言》------练习7-7、7-8
- 《C程序设计语言》练习 4-2
- 《C程序设计语言》练习 4-3
- 《C程序设计语言》练习 3-6
- 《C程序设计语言》练习3-3
- 《C程序设计语言》练习 4-4
- 《C程序设计语言》练习 2-9
- 《C程序设计语言》练习 2-10
- 《C程序设计语言》学习笔记——练习4-1
- 《C程序设计语言》练习 1-6,1-7
- 《C程序设计语言》学习笔记——练习2-3
- 《C程序设计语言》练习 3-1
- 《C程序设计语言》学习笔记——练习3-2