C语言:(新)四则计算器(支持括号和次方运算)

来源:互联网 发布:上海雨人软件 编辑:程序博客网 时间:2024/05/29 02:52

之前已经写过一个计算器,每次回顾都觉得很复杂,一直在考虑重新写一个
支持小数运算
存储数据改为了double类型
支持整数次方
运算中乘法可以用x或者*表示,两个都支持
平台visual studio 2015
另外:输入的时候输入法最好是英文状态

这次的存储模式如下:
这里写图片描述

大概说一下计算流程:
1:将输入的文本提取出运算符,数字,次方和等级四类
2:每次运算找到当前的最高等级,先计算次方,再计算四则运算
3:计算结果覆盖至第二个aNum结构体的data,并废弃第一个结构体
4:2、3循环

输入的公式拆分成data,oper(operator)和class三类 data:即为公式中的每个数字 oper:+-*/运算符
class:符号的运算等级(类似于优先级)

讲一下我构造class的这个思路:
在括号外的公式中,+-的运算等级(class)为1,*/的运算等级为2
在括号内的公式中,+-对应等级为3(大于括号外的/等级),而/的等级为4

在这次的计算中,我把计算单独拿了出来
函数:float compute(float num1, float num2, char opt)
一次只运算一对数字,而每对计算的先后顺序就根据class等级值

每一个struct aNum用了链表来连接,利于计算后的数据处理

例:

3+5x(2+1)-7
第一次运算时,找到最高的class,即存储“data=2,oper=’+’,class=3”的struct,2+1=3,而当前struct就不能再留下了,此时就把结果3覆盖到下一个struct的data上,然后抛弃当前存储“data=2”的struct,即p_front->next=p->next;每次计算如此循环

#include <stdio.h>#include <stdlib.h>#include <math.h>#define INIT_STRING_SIZE 100#define True 1#define False 0int saved_class[4] = { 0, 0, 0, 0 };typedef struct aNum {    double data;    char oper;    int dataClass;    int power;    struct aNum *next;}num;typedef struct {    char *formula;    int length;}string;void setNULL(char *num)//清空一个字符串{    int i = 0;    while (i<5)    {        num[i] = NULL;        ++i;    }}int countOperators(string *input, int &counter)//processing step 1{//计算运算符个数    int i = 0;    while (input->formula[i] != '\0')    {        switch (input->formula[i++])        {        case '+':        case '-':        case '*':        case '/':++counter; break;        default:break;        }        ++input->length;    }    return 1;}int getData(string *input, num *nums)//processing step 2{//把数字,符号和class存入nums的结构体    int i = 0;    //counter of input->formula    int k = 0;  //counter of temp;    int power = 0;    char temp[5];    int inBracket = False;    num *p = nums;    num *body;    while (i <= input->length)    {        if ((input->formula[i]<'0' || input->formula[i]>'9')&&input->formula[i]!='.'&&input->formula[i]!='^')        {//进入此处时数据已经收集完毕            if (input->formula[i] == '(')            {                inBracket = True;                ++i;                continue;            }            if (input->formula[i] == ')')            {                inBracket = False;                ++i;                continue;            }            body = (num *)calloc(1, sizeof(num));            body->data = atof(temp);    //得到数字            setNULL(temp);              //归零temp            k = 0;            switch (input->formula[i])            {            case '+':body->dataClass = inBracket == False ? 1 : 3;  //计算当前运算符的等级                ++saved_class[body->dataClass - 1];                 //在等级数组里记录一次                body->oper = input->formula[i];                     //得到运算符                break;            case '-':body->dataClass = inBracket == False ? 1 : 3;                ++saved_class[body->dataClass - 1];                body->oper = input->formula[i];                break;            case 'x':            case '*':body->dataClass = inBracket == False ? 2 : 4;                ++saved_class[body->dataClass - 1];                body->oper = input->formula[i];                break;            case '/':body->dataClass = inBracket == False ? 2 : 4;                ++saved_class[body->dataClass - 1];                body->oper = input->formula[i];                break;            default:break;            }            if (power != 0)            {                body->power = power;                power = 0;            }            p->next = body;            p = p->next;        }        else if (input->formula[i] == '^')        {            power = input->formula[++i] - 48;        }        else        {            temp[k++] = input->formula[i];        }        ++i;    }    return 1;}double compute(double num1, double num2, char opt){//每次运算单独提取    double result;    switch (opt)    {    case '-':result = num1 - num2; break;    case '+':result = num1 + num2; break;    case 'x':    case '*':result = num1 * num2; break;    case '/':result = num1 / num2; break;    }    return result;}int processingData(num *nums)//processing step 3{//nums作为头结点是没有数据的    int s = 3;//saved_class    int i = 0;    num *p = nums;    num *p_front;    while (saved_class[s] == 0&&s>0)        --s;    while (p->next->next != NULL)//class oper next 都可以    {        if (p->next->dataClass != s + 1)        {            p = p->next;            continue;        }        p_front = p;        p = p->next;//p此时指向待计算的第一个struct aNUm        if(p->power != 0)        {            p->data = pow(p->data, p->power);            p->power = 0;        }        if (p->next->power != 0)        {            p->next->data = pow(p->next->data, p->next->power);            p->next->power = 0;        }        p->next->data = compute(p->data, p->next->data, p->oper);        p_front->next = p->next;        free(p);        --saved_class[s];        while (saved_class[s] == 0&&s!=0)            --s;        p = nums;    }    if (nums->next->power != 0)//处理单个数字输入的情况,比如2^2    {        nums->next->data = pow(nums->next->data, nums->next->power);    }    printf("result=%lf", nums->next->data);    return 1;}int main(){    int counter = 0;    num *nums = NULL;    string *input;    input = (string *)calloc(1, sizeof(string));    input->formula = (char *)calloc(INIT_STRING_SIZE, sizeof(string));    puts("Input formula:");    scanf("%s", input->formula);    //得到运算符和运算符个数    countOperators(input, counter);    //根据运算符个数申请存储数字的空间    nums = (num *)calloc(1, sizeof(num));    //存储数字和运算符    getData(input, nums);    processingData(nums);    free(input->formula);    free(input);    free(nums->next);    free(nums);    system("pause");    return 0;}

测试数据不多,有错误欢迎指出^^

阅读全文
1 0
原创粉丝点击