四则运算表达式求值程序(C语言版)

简介: 废话不说,见代码。 《Compute.h》头文件 #include   #include   #include   /*以下为本程序涉及到的函数的声明*/ int CheckString(const char *Str);   /*检查字符串中有否除了0-9,+,-,*,/,(,),之外的其他字符*/ void  DealString(char *OperatorArr, double *DigitalArr, int CurrPosition); /*将当前已经完成运算的运算符消去,同时将数值数组的位置调整以进行下一次运算。

废话不说,见代码。

《Compute.h》头文件

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 


/*以下为本程序涉及到的函数的声明*/
int CheckString(const char *Str);   /*检查字符串中有否除了0-9,+,-,*,/,(,),之外的其他字符*/


void  DealString(char *OperatorArr, double *DigitalArr, int CurrPosition); /*将当前已经完成运算的运算符消去,同时将数值数组的位置调整以进行下一次运算。*/


double DealNumber(const char *Str);  /*对于输入的字符串,先将其小数点以前的部分复制到tempStr[]数组中*/


double ComputeString(const char *Str); /*对输入的字符串进行处理,是本程序最重要的一个函数*/


《Compute.c》函数实现程序

#include <stdio.h>   
#include <string.h> 
#include <stdlib.h>  
#include "Compute.h"


/*以下为本程序中各函数的实现*/
/**************************************************************************
* 函数名:  int CheckString(char *Str)
* 输入参数:char *Str: 输入的字符串
* 返回参数:
            0:字符串中有不符合规定的字符
            1: 字符串字符符合规定,没有不符合规定的字符.
* 功能:
            检查字符串中有否除了0-9,+,-,*,/,(,),之外的其他字符,
            如果有,则返回0, 表示出现错误。
            若没有,则返回1,表式字符串符合规定。
**************************************************************************/
int CheckString(const char *Str)
{
int iFlag         = 0;      //k用于检查括号是否配对
int iCharacterNum = 0;      //iCharacterNum用于统计输入的字符的个数
    while ((*Str) != '\0')
{
if (((*Str)>='0' && (*Str)<='9') || ((*Str)=='+') || 
           ((*Str)=='-') || ((*Str)=='*') || ((*Str)=='/') || 
           ((*Str)=='.') || ((*Str)=='(') ||  ((*Str)==')') )
{
iCharacterNum ++;
}
else
{
printf("Input error, there have the char not the math expression char!\n");
return 0;
}

if ((*Str) == '(')
{
iFlag++;
}
else if ((*Str) ==')')
{
iFlag--;
}
Str++;
}


if (iFlag != 0)
{
printf("Input error, there is not have correct bracket '()'!\n");
return 0;
}
printf("You input %d characters in total!\n", iCharacterNum);


return 1;
}


/*****************************************************************************************************************
* 函数名: void  DealString(char *OperatorArr, double *DigitalArr, int CurrPosition) 
* 输入参数:
           char *OperatorArr :  运算符数组
           double *DigitalArr:  数值数组
           int CurrPosition:    当前运算符数组位置
* 返回参数:无
* 功能:
           将当前已经完成运算的运算符消去,同时将数值数组的位置调整以进行下一次运算。
           传入值CurrPosition若为3,则当前符号的数组位置为3.
           OperatorArr[3]=OperatorArr[3+1].......OperatorArr[len-2]=OperatorArr[len-1]  OperatorArr[len-1]='\0';
           DigitalArr[i]=DigitalArr[i+1].......DigitalArr[len-1]=DigitalArr[len]  因为数值比运算符多一个。
******************************************************************************************************************/
void  DealString(char *OperatorArr, double *DigitalArr, int CurrPosition)  
{
int iFlag = 0;
int iOperatorArrLen = strlen(OperatorArr);
for (iFlag = CurrPosition; iFlag < iOperatorArrLen; iFlag ++)   /*将已经运算过的符号,空出来的位置用后面的符号来填充,即把乘和除号的位置用后面的加和减号填充*/      
{   
OperatorArr[iFlag] = OperatorArr[iFlag+1];
DigitalArr[iFlag] = DigitalArr[iFlag+1];
}
DigitalArr[iFlag] = DigitalArr[iFlag+1];
    OperatorArr[iOperatorArrLen-1] = '\0';
}


/************************************************************************************
* 函数名:  double DealNumber(char *Str)
* 输入参数:char *Str :由数字和小数点组成的字符,用以转换成double型的数值。
* 返回参数:dValueReturn:返回转换好的值。
* 功能:
            对于输入的字符串,先将其小数点以前的部分复制到tempStr[]数组中,
            若有小数点,则将将小数点之后的数值,也就是小数部分先进行计算,值存入dValueReturn中
            计算完成后,再对整数部分进行计算,值加上小数部分的值,存入dValueReturn中。
*************************************************************************************/
double DealNumber(const char *Str)
{
double dValueReturn = 0.0;
double dFlag = 1.0;
int    iLoop = 0;
int    iFloat = 0;
int    iStrLen = 0;
char   tempStr[100] = {0};
    int    iTempi = 0;
    int    iStart = 0;
    int    iFlag = 1;            /*正负符号指示器,若为1则为正数,为-1,此数为负数*/
 
    iStrLen = strlen(Str);
 
    if (Str[0] == '-')
{
iStart = 1;
        iFlag = -1;
}


    for (iLoop = iStart; iLoop < iStrLen; iLoop ++)
{
        if (Str[iLoop] == '.') 
{
            iFloat = iLoop;
            break;
}
        tempStr[iTempi++] = Str[iLoop];  /*将整数部分复制到tempStr[]中*/
}
    tempStr[iTempi] = '\0';


    if (iFloat != 0)
{
for (iLoop = iFloat+1; iLoop < iStrLen; iLoop ++) /*将小数部分计算出来*/
{
if (Str[iLoop] == '.')  /*如果有多余的小数点,则表示输入错误*/
{
printf("There is more that one dot '.' in number!error!!!\n");
exit(0);
}
            dFlag = dFlag * 0.1;
            dValueReturn += (dFlag * (Str[iLoop]-48));
}
}


    dFlag = 1.0;


    iStrLen = strlen(tempStr);           /*计算整数部分*/
    for (iLoop = iStrLen-1; iLoop >= 0; iLoop --)
{
dValueReturn = dValueReturn + (dFlag * (tempStr[iLoop] - 48));
        dFlag *= 10;
}


    dValueReturn = dValueReturn * iFlag;
    return dValueReturn;
}


/************************************************************************************
* 函数名: double ComputeString(char *Str)
* 输入参数:
           char *Str: 即将进行运算的字符串型数学表达式,如3.5+(2*3/5)
* 返回参数:
           dTotalNum[0]:计算结果将放入dTotalNum[0]中
* 功能:
           将输入的字符串中的数字分别调用DealNumber(char *Str)函数进行数值变换,再将其依
           次存入doulbe dTotalNum[i]中,将加减乘除运算符依次存入字符串符号数组中,
           然后如果遇到括号,则将括号内的字符串存入另一字符数组中,然后用此
           ComputeString(char *Str) 递归函数进行递归运算。 然后根据先乘除,后加减的顺序对已
           存入数组的数值根 据存入字符串符号数组的运算符进行运算。结果存入dTotalNum[0]中。
           返回最终结果。
*************************************************************************************/
double ComputeString(const char *Str)           /*可递归函数*/
{                                /*取得数值字符串,并调用DealNumber转换成double*/
char cStr[100] = {'\0'}, cTotalChar[30] = {'\0'};   /*cStr保存当前的表达式串,cTotalChar保存一个数的所有字符*/
    char cStack[80] = {'\0'};                  /*保存所有的符号的堆栈*/
    int iCharPos = 0;                   /*保存符号的位置指针*/
    double dTotalNum[80] = {0.0};     /*保存当前所有的数的一个堆栈*/
    int iDigitalPos = 0;              /*保存数字位置指针*/
    int iBracketFlag = 0;             /*若iBracketFlag=1则表示有一对括号*/
    int iCharInBracketNum = 0, iCharInNumberNum = 0;  /*iCharInBracketNum保存新括号内的字符数, iCharInNumberNum保存number里的字符位置*/
    int iNumOfMulAndDiv = 0;                         /*乘除符号数量*/
    int iNumOfAddAndDec = 0;                         /*加减符号数量*/


    while ((*Str) != '\0')           /*当p==1 和k==0时,表示已经把括号里的内容全部复制到g[100]中了*/
{
iBracketFlag = 0;
        iCharInBracketNum = 0;

switch (*Str)
{
case '+':            /*当前字符为加减乘除时则表示*/
case '-':
case '*':
case '/':
{
cStack[iCharPos++] = (*Str);
            if(((*Str) == '*') || ((*Str) == '/'))
{
iNumOfMulAndDiv ++;
}
else
{
iNumOfAddAndDec ++;
}
            if((*(Str-1)) != ')')
{
cTotalChar[iCharInNumberNum] = '\0';
iCharInNumberNum = 0;             /*完成一个数字的复制,其位置指针i=0*/
dTotalNum[iDigitalPos++] = DealNumber(cTotalChar);
}
            break;
}


        case '(':   /*有括号,则将当前括号作用范围内的全部字符保存,作为*/
{           /*一个新的字符表达式进行递归调用ComputeString函数计算。*/
iBracketFlag ++;            
            while(iBracketFlag > 0)
{
Str ++;
cStr[iCharInBracketNum] = (*Str);
iCharInBracketNum ++;
if((*Str) == ')')
{
iBracketFlag--;
}
                else if((*Str) == '(')
{
iBracketFlag ++;
}
}
            cStr[iCharInBracketNum-1] = '\0';
            iCharInBracketNum = 0;         /*完成一个括号内容的复制,其位置指针num=0*/
            dTotalNum[iDigitalPos++] = ComputeString(cStr);
            break;
}


        default:
{
cTotalChar[iCharInNumberNum++] = (*Str);
if((*(Str+1)) == '\0')

cTotalChar[iCharInNumberNum] = '\0';
                dTotalNum[iDigitalPos++] = DealNumber(cTotalChar);
}
            break;
}
}
  
        Str ++;
}


    cStack[iCharPos] = '\0';


    iCharInNumberNum = 0;


    while (iNumOfMulAndDiv > 0)
{
   switch (cStack[iCharInNumberNum])
{
case '*': 
{
   iNumOfMulAndDiv --;
            dTotalNum[iCharInNumberNum+1] = dTotalNum[iCharInNumberNum] * dTotalNum[iCharInNumberNum+1];
            DealString(cStack,dTotalNum, iCharInNumberNum);
            break;
}


        case '/': 
{
iNumOfMulAndDiv --;
            dTotalNum[iCharInNumberNum+1] = dTotalNum[iCharInNumberNum] / (float)dTotalNum[iCharInNumberNum+1];
            DealString(cStack, dTotalNum, iCharInNumberNum);
            break;
}


        default:
{
   iCharInNumberNum ++;
            break;
}
}
}


    iCharInNumberNum = 0;
    while (iNumOfAddAndDec > 0)
{
switch(cStack[iCharInNumberNum])
{
case '+': 
{
dTotalNum[iCharInNumberNum+1] = dTotalNum[iCharInNumberNum] + dTotalNum[iCharInNumberNum+1];
            iNumOfAddAndDec --;
            DealString(cStack,dTotalNum, iCharInNumberNum);
            break;
}


        case '-': 
{
dTotalNum[iCharInNumberNum+1] = dTotalNum[iCharInNumberNum] - dTotalNum[iCharInNumberNum+1];
            iNumOfAddAndDec --;
            DealString(cStack,dTotalNum,iCharInNumberNum);
            break;
}


        default:
{
printf("operator error!");
            break;
}
}

}

    return dTotalNum[0];
}


《main.c》主程序

#include <stdio.h>  
#include <string.h>  
#include <stdlib.h> 
#include "Compute.h"


/************************************************************************************
* 函数名: int main()
* 功能:   调用四则运算函数。
*************************************************************************************/
int main()
{
char cStr[100] = {'\0'};
    double dResult = 0.0;
    int iFlag = 1;
while (1)
{
printf("Enter expression(If you want to terminate the program, please enter '#' to end the program): \n");
        scanf("%s", cStr);

        iFlag = strncmp(cStr, "#", 1);
        if (iFlag == 0)
{
break;
}

        iFlag = CheckString(cStr);
        if (iFlag == 0)
{
continue;
}

dResult = ComputeString(cStr);

printf("%s = %f", cStr, dResult);
printf("\n");
}
    printf("Good bye!\n");

    return 0;
}


欢迎批评指正!

目录
相关文章
|
1月前
|
存储 自然语言处理 编译器
【C语言】编译与链接:深入理解程序构建过程
【C语言】编译与链接:深入理解程序构建过程
|
3月前
|
存储 算法 C语言
"揭秘C语言中的王者之树——红黑树:一场数据结构与算法的华丽舞蹈,让你的程序效率飙升,直击性能巅峰!"
【8月更文挑战第20天】红黑树是自平衡二叉查找树,通过旋转和重着色保持平衡,确保高效执行插入、删除和查找操作,时间复杂度为O(log n)。本文介绍红黑树的基本属性、存储结构及其C语言实现。红黑树遵循五项基本规则以保持平衡状态。在C语言中,节点包含数据、颜色、父节点和子节点指针。文章提供了一个示例代码框架,用于创建节点、插入节点并执行必要的修复操作以维护红黑树的特性。
102 1
|
3月前
|
NoSQL 编译器 程序员
【C语言】揭秘GCC:从平凡到卓越的编译艺术,一场代码与效率的激情碰撞,探索那些不为人知的秘密武器,让你的程序瞬间提速百倍!
【8月更文挑战第20天】GCC,GNU Compiler Collection,是GNU项目中的开源编译器集合,支持C、C++等多种语言。作为C语言程序员的重要工具,GCC具备跨平台性、高度可配置性及丰富的优化选项等特点。通过简单示例,如编译“Hello, GCC!”程序 (`gcc -o hello hello.c`),展示了GCC的基础用法及不同优化级别(`-O0`, `-O1`, `-O3`)对性能的影响。GCC还支持生成调试信息(`-g`),便于使用GDB等工具进行调试。尽管有如Microsoft Visual C++、Clang等竞品,GCC仍因其灵活性和强大的功能被广泛采用。
123 1
|
3月前
|
编译器 C语言 计算机视觉
C语言实现的图像处理程序
C语言实现的图像处理程序
154 0
|
1月前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序
|
2月前
|
程序员 C语言
【C语言基础考研向】06运算符与表达式
本文介绍了C语言中的运算符分类、算术运算符及表达式、关系运算符与表达式以及运算符优先级等内容。首先概述了13种运算符类型,接着详细说明了算术运算符的优先级与使用规则,以及关系运算符和表达式的真假值表示,并给出了C语言运算符优先级表。最后附有课后习题帮助巩固理解。
105 10
|
2月前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
95 10
|
2月前
|
C语言
C语言程序设计核心详解 第二章:数据与数据类型 4种常量详解 常见表达式详解
本文详细介绍了C语言中的数据与数据类型,包括常量、变量、表达式和函数等内容。常量分为整型、实型、字符型和字符串常量,其中整型常量有十进制、八进制和十六进制三种形式;实型常量包括小数和指数形式;字符型常量涵盖常规字符、转义字符及八进制、十六进制形式;字符串常量由双引号括起。变量遵循先定义后使用的规则,并需遵守命名规范。函数分为标准函数和自定义函数,如`sqrt()`和`abs()`。表达式涉及算术、赋值、自增自减和逗号运算符等,需注意运算符的优先级和结合性。文章还介绍了强制类型转换及隐式转换的概念。
|
3月前
|
C语言
C语言------运算符与表达式
这篇文章是C语言运算符与表达式的实训教程,通过多个示例程序展示了如何使用算术运算符、关系运算符、逻辑运算符以及条件语句来解决实际问题,并介绍了如何通过函数库简化复杂数学运算。
C语言------运算符与表达式
|
3月前
|
自然语言处理 编译器 C语言
C语言程序的编译
C语言程序的编译
65 2