用c语言编写的可以计算+-*/的计算器

写了一个计算器程序,想分享给大家;同时写到最后感觉有点凌乱,希望各位帮忙给优化下,共同提高。这个计算器可以计算输入的字符串,字符串中可以含括号,可以是小数,也可以包含负数。此程序被拆分在5个文件中,我按文件一一罗列吧:

编写环境:VC++6.0。

第一个main函数所在文件:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
    char *s1;
    int i;
    double c;
    double calc(char *s);
    int brk(char *st);
    while(1)
    {
        s1=(char *)malloc(50);   //为s1分配地址和空间。
        scanf("%s",s1);          //输入并得到s1字符串。
        i=brk(s1);               //执行所有"()"中的计算式。
        c=calc(s1);              //计算最后的不带"()"的s1。
        printf("%g\n",c);        //输出最后结果。
        printf("--------Press Up/Down Arorw or Begain Next Input:\n");    
        //提示执行下一次运算。
        free(s1);    //释放s1内存空间。
    }
}

第二个函数文件:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
double calc(char *s)   //把s拆解成double型数组和保存操作符的字符型数组,
{                      //并利用两个数组计算结果。
    int i=0,j=0,k=0,num=1,end=0,sub=0;    //num、end、sub为开关标识。
    double *sn;
    char *sc,*sp;
    void mathc(double *a,char *s);
    sn=(double *)malloc(51);              //用于存放s中所有的数字串。
    sc=(char *)malloc(50);                //用于存放s中所有的操作符。
    sp=(char *)malloc(10);                //遍历s中的各个数字串,并保存其中。
    //while(!isdigit(*s))
    //    s++;
    //c=*s;
    //if(c==‘-‘)
    //{
    //    *sp=c;
    //    i=1;
    //    s++;
    //}
    for(;*s!=‘\0‘;s++)                    //遍历s所有字符。
    {
        if(!isdigit(*s) && *s!=‘+‘ && *s!=‘-‘ && *s!=‘*‘ && *s!=‘/‘ &&
(接上一行) *s!=‘.‘)    //如果字符不是数字且不是操作符及小数点则输出错误。
        {
            printf("Error 6: illegal input!\n");
            return 0;
        }
        if(isdigit(*s)||*s==‘.‘)        //如果字符是个数字或者小数点。
        {
            //if(c==‘-‘)
            *(sp + i++)=*s;
            //i++;
            num=0;                      //把这3个开关置为0。
            end=0;
            sub=0;
            continue;
        }
        if(sub==1)          //sub用于标识s中负数,比如"-5",
                            //但是如果有两个"--"则是错误,
                            // 除了类似"4--5"【等价于4-(-5)】的情况。
            {               //"--"前没有数字的情况是不允许的。
                printf("Error 7: too many operator!\n");
                return 0;
            }
        if(num==1)          //num==1说明是字符串刚开始(即第一个字符)
        {                   //或者上一次执行的是“+-*/”。
            if(*s!=‘-‘)     //开始不是"-"或"+*/"后面不是"-"。
            {               //(注意在这个时候肯定也不是数字,
                            //因为数字已经被判断过了。)
                printf("Error 8: too many operator!\n");
                return 0;
            }
            else
            {
                *(sp + i++)=*s;     //开始是个"-"或者前一个字符是"+*/"。
                sub=1;              //把sub置为1,即下一个字符不能再是"-",
                                    //注意这是在num==1的情况下。
                end=0;              //执行的是数字字符部分,此程序把
                                    //这种情况下的负号做为了数字的一部分。
                continue;           //执行下一次循环。
            }
        }
        if(*s==‘+‘||*s==‘-‘||*s==‘*‘||*s==‘/‘)  //如果执行的字符是操作符。
        {
            *(sp+i)=‘\0‘;                     //是sp结束,即结束数字字符部分。
            i=0;                              //使下一次sp从0开始计数。
            end=1;                            //标识数字字符部分执行结束。
            *(sn + j++)=atof(sp);             //把sp转换为double型数组。
            if(*(s+1)==‘\0‘)                  //如果下一个元素为s的的结束,
                                              //则不往下执行,即不保存这个操作符。
                break;
            *(sc + k++)=*s;                   //既然s的下一个元素不是结束,
                                              //那么把这个字符串保存到sc中。
            num=1;                            //因为刚保存的是个操作符,
                                              //下一个不能再是操作符,除了"-"。
            continue;
        }
    }
    if(*s==‘\0‘&&end==0)            //s的最后一个字符是数字字符,执行这一部分语句。
    {
        *(sp+i)=‘\0‘;               //使sp结束。
        //i=0;
        if(*(sp+i-1)==‘-‘)          //如果上一个字符只是一个"-"号,则输出错误。
        {
            printf("Error 9: illegal input!\n");
            return 0;
        }
        *(sn + j++)=atof(sp);        //把sp转换成double数组保存到sn中。
    }
    *(sn+j)=‘\0‘;                    //是sn和sc结束。
    *(sc+k)=‘\0‘;
    mathc(sn,sc);                    //把sn和sc传给mathc函数计算s的结果。
    return *sn;                      //mathc的计算结果是保存在sn中的,
}                                    //把sn返回即可。

第三个函数文件:

#include<stdio.h>
void mathc(double *a, char *s)                            //执行计算。
{
    int i;
    double sum;
    void offsetd(double *s,int n1, int n2);
    void offsetc(char *s,int n1,int n2);
    for(i=0;*(s+i)!=‘\0‘;i++)                            //先计算“/”。
        if(*(s+i)==‘/‘)
        {
            if(*(a+i+1)==0)                                //不能除以0。
            {
                printf("Error 5: illegal input 0!\n");
                break;
            }
            sum = *(a+i) / *(a+i+1);
            *(a+i)=sum;
            offsetd(a,i+1,1);
            offsetc(s,i,1);
            i=-1;
        }
    for(i=0;*(s+i)!=‘\0‘;i++)                            //计算"*"。
        if(*(s+i)==‘*‘)
        {
            sum = *(a+i) * *(a+i+1);
            *(a+i)=sum;
            offsetd(a,i+1,1);
            offsetc(s,i,1);
            i=-1;
        }
    for(i=0;*(s+i)!=‘\0‘;i++)                            //计算"-"。
        if(*(s+i)==‘-‘)
        {
            sum = *(a+i) - *(a+i+1);
            *(a+i)=sum;
            offsetd(a,i+1,1);
            offsetc(s,i,1);
            i=-1;
        }
    for(i=0;*(s+i)!=‘\0‘;i++)                            //计算"+"。
        if(*(s+i)==‘+‘)
        {
            sum = *(a+i) + *(a+i+1);
            *(a+i)=sum;
            offsetd(a,i+1,1);
            offsetc(s,i,1);
            i=-1;
        }
}

第四个函数文件:

#include<stdio.h>
#include<string.h>
void offsetd(double *s,int n1, int n2) //使double数组的n1+n2处的元素往前移动n2。
{
    for(;*(s+n1)!=‘\0‘;n1++)
        *(s+n1) = *(s+n1+n2);
}
void offsetc(char *s,int n1, int n2)   //与offsetd功能相同,只是s数组元素是字符型。
{
    for(;*(s+n1)!=‘\0‘;n1++)
        *(s+n1) = *(s+n1+n2);
}
void repl(char *c1,char *c2,int i,int j) //使用c2替换c1中第i-j之间的元素。
{
    unsigned int n=0;
    int a;
    n=strlen(c2);
    for(a=n;*(c1+j)!=‘\0‘;)             //先把c1中第j元素以后的数字复制到c2后面。
        *(c2 + a++) = *(c1 + j++);
    *(c2+a)=‘\0‘;
    for(;*c2 != ‘\0‘;)                 //用c2替换c1中第i元素往后的所有元素。
        *(c1 + i++) = *(c2++);
    *(c1+i)=‘\0‘;
}

第五个函数文件:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int brk(char *st)    //计算括号内的算式的值。
{
    int m,n,d,b;     //m左括号位置,n遍历整个st数组,d右括号位置,b用于上s2数组。
    char *s2;
    double i;
    void repl(char *c1,char *c2,int i,int j);  //调用repl函数使用s2计算结果
                                               //替换st中相应位置的字符。
    //void mathc(double *a,char *s);
    double calc(char *s);                      //计算字符串s的值。
    s2=(char *)malloc(50);            //为s2分配内存空间,并返回空间地址。
    for(n=0;*(st+n)!=‘\0‘;n++)        //遍历st数组。
        if(*(st+n)==‘)‘)              //首先查找")"。重要!在多重括号
                                      //中查找")"才能有效的找到每组括号。
        {    d=n;                     //把"("的位置保存在d中。
            if(*(st+d+1)!=‘\0‘&&isdigit(*(st+d+1))) //st的下一位是个数字则
                                                    //输出错误并返回。
            {
                printf("Error 1: ();\n");
                return 0;
            }
            while(n>0&&*(st + --n)!=‘(‘)      //从")"的位置n往回查找"("。
                ;
            if(*(st+n)!=‘(‘)           //while语句执行完成,此时n==0;
                                       //但是*(st+n)不是"(",则意味着没有匹配的
                                       //"(",输出错误。
            {
                printf("Error 2: ();\n");
                return 0;
            }
            m=n;                        //找到"("的话,把n的值保存到m中。
            if(m>0 && isdigit(*(st+m-1)))  //m位置的上一位不能是数字。
            {
                printf("Error 3: ();\n");
                return 0;
            }
            if((d-m)==1)                   //如果"()"为空,输出错误。
            {
                printf("Error 4: ();\n");
                return 0;
            }
            for(b=0;*(st + ++n)!=‘)‘;b++)  //把括号中的内容复制到s2中。
                *(s2+b) = *(st + n);
            *(s2+b)=‘\0‘;
            i=calc(s2);                    //计算s2的值,并返回double i。
            sprintf(s2,"%g",i);            //把i转换成字符串保存至s2中。
            //printf("s2 %s\n",s2);
            repl(st,s2,m,n+1);             //使用s2替换st中的括号。
            printf("step %s\n",st);        //输出替换后的st。
            n=-1;                          //执行下一次循环。
            continue;
        }
}

可执行程序下载地址:http://pan.baidu.com/s/1jGiUaYM

写的不好,大神勿喷,欢迎指正。

欢迎转载,但是版权所有。

时间: 2024-10-19 00:14:31

用c语言编写的可以计算+-*/的计算器的相关文章

基于Perfect用Swift语言编写Slack聊天机器人

基于Perfect用Swift语言编写Slack聊天机器人 本项目是专门为Slack聊天机器人定制的模板服务器. 完整的源代码下载在Github https://github.com/PerfectServers/SlackBot 在本项目模板中,一个聊天机器人可以加入授权频道,读取频道内所有用户发送的"曲奇"并记录在案,而且可以直接答复用户的有关曲奇饼干的问题. 预备知识 在您决定编译.测试或者部署您自己的基于Perfect软件框架体系的聊天机器人之前,以下基础知识??不可或缺??:

C语言编写的bmp读写程序

C语言编写的bmp读写程序 建议先把bmp的数据存储格式了解下 [cpp] view plaincopy <span style="font-size:16px;">#include "Windows.h" #include "stdio.h" #include "string.h" #include "malloc.h" unsigned char *pBmpBuf;//读入图像数据的指针 i

悟空:用Go语言编写的全文搜索引擎

最近Go语言1.5版正式发布,国内关于Go语言的学习和应用也逐渐火热,InfoQ也将关注并推动国内Go语言社区的发展.悟空开源项目是用Go语言编写的全文搜索引擎,InfoQ记者采访了它的作者陈辉,了解了这个项目背后的一些信息. 悟空搜索引擎的特点是高度可定制,具有如下特性: 高效索引和搜索(1M条微博500M数据28秒索引完,1.65毫秒搜索响应时间,19K搜索QPS) 支持中文分词(使用作者自己研发的Go语言中文分词工具sego分词包并发分词,速度27MB/秒) 支持计算关键词在文本中的紧邻距

shell简介 linux由什么语言编写

1.shell简介 Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言.作为命令语言,它交互式地解释和执行用户输入的命令:作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支.它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序.建立文件并以并行的方式协调各个程序的运行.因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其

《C语言编写 学生成绩管理系统》

/* (程序头部凝视開始)* 程序的版权和版本号声明部分* Copyright (c) 2011, 烟台大学计算机学院学生 * All rights reserved.* 文件名: 学生成绩管理系统 * 作 者: 刘江波 * 完毕日期: 2012 年 6 月 23 日* 版 本 号: v.623 * 对任务及求解方法的描写叙述部分 * 程序头部的凝视结束 */ #include "stdio.h" #include"string" /*定义学生结构体*/ struc

【原创】用第三方语言编写PostgreSQL 存储函数

在PostgreSQL里,所有的存储函数需求都可以用PLPGSQL来实现.同时也支持用第三方语言来编写,这个就得看自己哪个方面熟练了.不过要注意的一点是 PLPGSQL的效率怎么着都比其他第三方语言来的高效.比如,简单的插入表的存储函数: CREATE OR REPLACE FUNCTION ytt.insert_plpgsql(f_num integer) RETURNS void LANGUAGE plpgsql AS $ytt$ declare i int := 0; v_rank int

ubuntu 下使用CGI c语言 编写helloworld

从根本上说,CGI 就是HTML表单与服务端脚本之间的接口. 自己可以百度了一些cgi知识:给出链接报错.那就自己Google哈 也因为工作需要,所以来学习了下. 一.安装及配置apache服务器 安装apache2服务器 #sudo apt-get install apache2 配置apache2服务器 配置文件位于 /etc/apache2/sites-enabled/000-default 用vi打开配置文件: #sudo vi /etc/apache2/sites-enabled/00

运用Python语言编写获取Linux基本系统信息(三):Python与数据库编程,把获取的信息存入数据库

运用Python语言编写获取Linux基本系统信息(三):Python与数据库编程 有关前两篇的链接: 运用Python语言编写获取Linux基本系统信息(一):获得Linux版本.内核.当前时间 运用Python语言编写获取Linux基本系统信息(二):文件系统使用情况获取 一.实验环境: Python2.7.10.pycharm.VM虚拟机.CentOS6.3.mysql 二.MySQLdb模块: MySQLdb模式是Python中专门连接MySQL数据库的模块,另外Python开发环境的搭

通过WebSocket实现实时通讯C#语言编写服务端

无意中发现js有webSocket对象于是百度了一下客户端代码与服务端代码没有现成的 有的就有一些简单了连接例子有的还不好使 于是就自己整理了一下 c#编写的服务端代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Text.RegularExpression