用C语言写一个计算器

用C语言写一个计算器,除了四则混合运算之外,还支持三角函数和绝对值等函数。

PS E:\Code\PL\calc> .\a.exe     
abs(3*5-4^2)
abs(3*5-4^2)=1.000000
25-7+6*(4-5)
25-7+6*(4-5)=12.000000
  • 最新修改版(非VIP博客)
  • 源代码:C语言实现计算器源代码,支持四则混合运算以及三角函数

文章目录

    • 1. 加减法运算
    • 2. 加法和乘法
    • 3. 四则混合运算
    • 4. 浮点型计算器程序
    • 5. 加入三角函数

在计算器中,至少包含两类变量,即数字和运算符。例如,如果希望实现 a + b × ( c − d ) a+b\times (c-d) a+b×(cd)这样一个简单的功能,要求编译器可以识别出 + , × , − , ( , ) +,\times,-,(,) +,×,,(,)这五个符号,并理清彼此的计算顺序,最后生成一棵语法树,然后实现输出。

1. 加减法运算

万事开头难,所以我们选择一个简单到无脑的开头。首先,我们考虑实现 a + b a+b a+b这样简单的两数运算,即如下所示,十分简单且无脑。

void douCalc(){
   
    while (1){
   
        double i, j, s;
        char k;
        scanf("%lf%c%lf", &i, &k, &j);
        switch (k){
   
        case '+':
            s = i+j;
            break;
        case '-':
            s = i-j;
            break;
        case '*':
            s = i*j;
            break;
        case '/':
            s = i/j;
            break;
        default:
            break;
        }
        printf("%lf\n", s);
    }
}

然后,我们考虑,如何实现一个连加器,旨在解决 a + b + c + . . . a+b+c+... a+b+c+...的计算问题。这里虽然不涉及到运算次序,但仍旧需要处理多个不确定个数的变量,所以我们不再可以直接用类似scanf("%lf%c%lf", &i, &k, &j);的方案来实现数据的输入,而必须建立一个链表来存储变量。

C语言输入输出

在C语言中,可以通过至少三种方式来读取键盘输入的值:

  • scanf():和 printf() 类似,scanf() 可以输入多种类型的数据。
  • getchar()getche()getch():这三个函数都用于输入单个字符。
  • gets():获取一行数据,并作为字符串处理。

其中,scanf是格式化扫描的意思,可以通过格式控制符对输入字符进行格式化,并赋值给相关变量。

格式控制符 说明
%c 读取单一字符
%s 读取一个字符串(以空白符为结束)
%f、%lf 读取十进制形式小数,赋值给float、double 类型
%e、%le 读取指数形式小数,赋值给 float、double 类型
%g、%lg 读取十进制或指数形式的小数,
并分别赋值给 float、double 类型
  • 整数格式化
    ||short|int|long|
    |-|-|-|-|-|
    |十进制|%hd|%d|%ld
    |八进制|%ho|%o|%lo
    |十六进制|%hx|%x|%lx|
    |无符号|%hu|%u|%lu|

getchar()等价于scanf("%c", c),相对来说更加简单。getchegetch是Windows独有的函数,在头文件conio.h中故不赘述。

getsscanf(%s,s)的区别在于,后者在使用的过程中会把空格当作终止符,而前者不会。

所以,我们在实现连加的过程中,会使用gets作为交互方法。

由于我们实现的是一个连加器,所以输入字符中只包含数字和加号,那么接下来,我们需要遍历输入字符,通过加号来将数字分开。我们可以很方便地写下一个简单而丑陋的小程序。

void adds(){
   
    char str[100];
    char numStr[20];
    int num[20];       
    int val;
    int i,j,k;
    while (1){
   
        gets(str);
        i = 0;j = 0;k = 0;
        while (str[i]!='\0'){
   
            if (str[i]=='+'){
   
                num[k] = atoi(numStr);
                k++;
                j = 0;
            }else{
   
                numStr[j] = str[i];
                j++;
            }
            i++;
        }
        num[k]=atoi(numStr);
        val = 0;
        for (int i = 0; i < k+1; i++){
   
            val += num[i];
        }
        printf("%d\n",val);
    }
}

int main(){
   
    adds();
    return 0;
}

由于加减法具有相同的运算优先级,在实现上不过是为后续的数字加上一个负号而已,故可十分方便地在原有程序上修改。

此外,adds代码乍看上去没什么问题,但str的值在更新之前,并不会自动清零,由此带来的bug需要创建一个字符串清零的函数。修改之后的代码如下

#include 
#include 
#include 
#include 

void strClear(char *str,int n){
   
    for (int i = 0; i < n; i++){
   
        str[i]=NULL;
    }
}

void adds(){
   
    char str[100];
    char numStr[20];
    int num[20];       
    int val;
    int i,j,k;
    while (1){
   
        gets(str);
        i = 0;j = 0;k = 0;
        while (str[i]!='\0'){
   
            if (str[i]=='+'){
   
                num[k] = atoi(numStr);
                strClear(numStr,20);
                k++;
                j = 0;
            }else if (str[i]=='-'){
   
                num[k] = atoi(numStr);
                strClear(numStr,20);
                k++;
                numStr[0] = str[i];
                j = 1;
            }else{
   
                numStr[j] = str[i];
                j++;
            }
            i

你可能感兴趣的:(C&C++,C语言,计算器,编译原理,语法生成树,字符串)