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

练习 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();
            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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值