c语言强化训练——简易计算器

高等数学全真模拟试题与详解:夯实基础·强化训练 来看一个经典例子:$$$$注意!这里 $ x=0 $ 是没定义的(分母为零),但我们关心的是“当 $ x $ 接近 0 时会发生什么”。你可以拿计算器试:$ x $0.1≈ 0.99830.01≈ 0.9999830.001看到了吗?越靠近 0,结果就越贴近 1。哪怕你永远不能代入 $ x=0 $,它的行为已经足够稳定了。这就引出了极限的核心哲学:我不在乎某一点上发生了什么,我在乎的是“周围邻居们”的集体趋势。 阅读详情

 

一、设计要求

实现一个简单的计算器,要求可以求解表达式,支持基本的运算并有扩展能力和基本的容错能力

 

二、设计思路

程序需要定义两个工作栈,分别保存表达式计算过程中的运算符与运算数,通过一个优先级表来判定运算顺序。通过判定输入的运算符来调用不同的函数,实现支持基本的运算符号。可以通过定义一个运算符表和一个函数指针表,通过查找方式调用函数,实现运算符的可扩展性。

 

三、详细设计

1、首先需要编写一个栈,这个栈需要支持浮点数和字符,编写这个栈stack.h文件

typedef struct {
        char * buffer;
        int typesize;
        int top;
        int max;
} Stack;

Stack * CreateStack(int max, int typesize);
void DestroyStack(Stack *);
void ClearStack(Stack *);
int Push(Stack *, void *);
int Pop(Stack *, void *);
int GetElement(Stack*, unsigned int n, void *);
int GetTop(Stack *, void *);
int IsEmpty(Stack *);
int IsFull(Stack *);

Stack * CreateStack(int max, int typesize)
{
        Stack * s = (Stack*)malloc(sizeof(Stack));
        if (!s) return 0;

        s->buffer = (char *)malloc(sizeof(char) * max * typesize);
        if (!s->buffer) return 0;

        s->top = -1;
        s->max = max;
        s->typesize = typesize;

        return s;
}

void DestroyStack(Stack* s)
{
        free(s->buffer);
        free(s);
}

void ClearStack(Stack * s)
{
        s->top = -1;
}

int Push(Stack * s, void * data)
{
        if (IsFull(s)) return 0;
	
        s->top++;
        memcpy(s->buffer + s->top*s->typesize, data, s->typesize);

        return 1;
}

int Pop(Stack * s, void * data)
{
        if (IsEmpty(s)) return 0;

        memcpy(data, s->buffer + s->top*s->typesize, s->typesize);
        s->top--;

        return 1;
}

int GetTop(Stack *s, void * data)
{
        if (IsEmpty(s)) return 0;
        
        memcpy(data, s->buffer + s->top*s->typesize, s->typesize);
        
        return 1;
}

int IsEmpty(Stack * s)
{
        return s->top == -1;
}

int IsFull(Stack * s)
{
        return s->top == s->max-1;
}

 

2、下面编写calcu.c文件,实现计算器功能,首先引入需要的头文件

#include "stdlib.h"
#include "stack.h"

3、对于用户输入的字符串要进行解析成运算符和数值,可以通过一个数组A来保存,再定义一个标记位数组B,标记数组A中哪一位是数据,哪一位是运算符。为了更明确数据与标记位的关系,这里把二者定义成一个结构体,通过结构体数据接受解析结果

#define fldouble 0
#define flchar 1

typedef struct {
        double data;
        char flag;
} cal;

4、定义支持的运算符,通过一个函数查找某个字符在运算符表中的位置,若不存在则返回-1

int SearchCode(char ch)
{
        char * code = "+-*/^()#";

        int n  = 0;

        while (code[n])
        {
                if (code[n] == ch) return n;
                n++;
        }
        return -1;
}

5、定义优先级表,控制运算过程中运算顺序,传入的参数为sch:栈中字符,nch下一个字符,返回优先级顺序

char GetPerferen(char sch, char nch)
{
        char perferen[8][8] = {
                ">><<<<>>",
                ">><<<<>>",
                ">>>><<>>",
                ">>>><<>>",
                ">>>>><>>",
                "<<<<<<=E",
                ">>>>>E>>",
                "<<<<<<E="
        };

        int s = SearchCode(sch);
        int n = SearchCode(nch);

        if (s==-1 || n==-1) return 'E';

        return perferen[s][n];
} rs;
}
double calcu(double a, char ch, double b)
{
        double (*function[5])(double,double) = {add,sub,mul,ddiv,mi};

        return function[SearchCode(ch)](a,b);
}

6、定义支持的运算函数,和一个查找函数指针列表的函数,函数指针列表中的运算函数与运算符表一一对应

double add(double a, double b) { return a+b; }
double sub(double a, double b) { return a-b; }
double mul(double a, double b) { return a*b; }
double ddiv(double a, double b) { return a/b; }
double mi(double a, double b)
{
        int n = 1;
        double rs = a;
        for (n=1; nreturn

7、编写函数检查用户输入的字符串是否合法,若含有结束符#,或不是有效运算符,不是数字且不是小数点,则视为非法字符,返回0。若字符串合法,在字符串末尾加入运算结束符#

int CheckStr(char * buffer)
{
        int n = -1;

        while (buffer[++n])
        {
                if ((SearchCode(buffer[n]) != -1 ||
                         buffer[n] == '.' ||
                          (buffer[n] >= '0' && buffer[n] <= '9'))
                           && buffer[n] != '#')

                        continue;
                else
                        return 0;
        }

        buffer[n] = '#';
        buffer[n+1] = 0;

        return 1;
}

8、解析过程是遍历字符串的过程,首先判断当前字符是否为运算符,若不是运算符调用一个函数GetNextValue获取这个数值。若是运算符但为加号或减号,需要判断是正负号还是加减号,再分别处理

首先编写GetNextValue函数,这个函数需要字符串指针,和指向解析过程中计数器的指针,接收结果的指针。若数值中有多个小数点或者小数点出现在第一位或最后一位,则非法,返回0,成功则返回1

int GetNextValue(char * buffer, int * n, double * rs)
{
        char str[30];
        int ii=0,ij = 0;

        while (SearchCode(buffer[*n]) == -1)
        {
                str[ii++] = buffer[*n];
                (*n)++;
        }
        str[ii] = 0;

        ii=0;
        while (str[ii])
        {
                if (str[ii++] == '.') ij++;
        }
        if (ij>1 || str[ii-1] == '.' || str[0] == '.') return 0;

        *rs = atof(str);

        return 1;
}

9、解析函数需要传入用户输入的字符串指针和接受解析结果的指针,成功返回0,失败返回1

int resolu(char * buffer, cal * calstr)
{
        int bn = 0, cn = 0;
        cal c;

        while (buffer[bn])
        {
                if (SearchCode(buffer[bn]) == -1)
                {
                        if (!GetNextValue(buffer,&bn, &c.data)) return 0;
                        c.flag = fldouble;

                        calstr[cn++] = c;
                }
                else
                {
                        if ((buffer[bn] == '-' && buffer[bn-1] == '(') || (bn==0 && buffer[0] == '-'))
                        {
                        		bn++;
                                if (!GetNextValue(buffer,&bn, &c.data)) return 0;
                                c.data = 0 - c.data;
                                c.flag = fldouble;
                                calstr[cn++] = c;
                        }
                        if ((buffer[bn] == '+' && buffer[bn-1] == '(') || (bn==0 && buffer[0] == '+'))
                        {
                        		bn++;
                                if (!GetNextValue(buffer, &bn, &c.data)) return 0;
                                c.flag = fldouble;
                                calstr[cn++] = c;
                        }
                        else
                        {
                                c.data = (double)buffer[bn++];
                                c.flag = flchar;
                                calstr[cn++] = c;
                        }
                        
                }
        }
}

10、运算函数

运算过程需要两个工作栈,当符号栈顶和解析串的下一个字符均为#时,表示运算结束。结束后数值栈应该只有一个元素,这个元素就是结果。这个函数需要传入指向解析结果的指针,和一个接收运算结果的指针,返回计算是否成功

int result(cal * calstr, double * rs)
{
        Stack * pst = CreateStack(100,sizeof(char));
        Stack * pnd = CreateStack(100,sizeof(double));

        double num1,num2;
        int n = 0;
        char ch = '#';

        Push(pst, &ch);

        while(ch != '#' || !(calstr[n].flag == flchar && (char)calstr[n].data == '#'))
        {
                if (calstr[n].flag == fldouble)
                {
                        Push(pnd, &(calstr[n].data));
                        n++;
                }
                else
                {
                        switch( GetPerferen(ch, (char)calstr[n].data))
                        {
                        case '<':
                                ch = (char)calstr[n].data;
                                Push(pst, &ch);
                                n++;
                                break;
                        case '=':
                                if (!Pop(pst, &ch)) return 0;;
                                n++;
                                break;
                        case '>':
                                if (!(Pop(pnd,&num2) && Pop(pst,&ch) && Pop(pnd,&num1))) return 0;;
                                num1 = calcu(num1,ch,num2);
                                Push(pnd, &num1);
                                break;
                        case 'E':
                                return 0;
                        }
                }
                if (!GetTop(pst, &ch)) return 0;
        }

        if (GetSize(pnd) == 1 && GetTop(pnd,rs))
        {
                DestroyStack(pst);
                DestroyStack(pnd);
                return 1;
        }
        else
        {
                return 0;
        }
}

11、编写与用户交互的函数

void treatment()
{
        char buffer[100];
        cal calstr[50];
        double rs;

        printf("calcu>");
        gets(buffer);

        while (!(buffer[0]=='e' && buffer[1]=='x' && buffer[2]=='i' && buffer[3]=='t'))
        {
                if (CheckStr(buffer) && resolu(buffer,calstr) && result(calstr,&rs))
                {
                        printf("/n%f/n",rs);
                }
                else
                {
                        printf("/nError!/n");
                }

                printf("/ncalcu>");
                gets(buffer);
        }
        printf("/nbye/n");
}

 

12、主函数

main()
{
        printf("Copyright/n/n");

        treatment();
}

四、测试

程序在TC2.0环境下测试通过

 

        (I)正常检测:
                (1)运算情况是否正确检测:
                          1.12+3*(3*4^3+3.12542*(1+2))/(4.2-1)+2.1 = 192.01024375
 
               (2)负数运算检测:
                         -2.1+((-2)^2)= 1.9

               (3)正数运算检测:
                         +2.1+((+2)^2)
              
               (4)单数字输入运算检测:
                         1  = 1.00000
            

        (II)容错检测:
                 (1)小数点输入错误检测:
                           1.22.+3..234..
                            .1+2

                (2)括号是否匹配检测:
                          ((2+3)/(5/4.1)))
 
                (3)运算符输入错误检测:
                          2.1--2
                          2.1++2
                          2.1**2
                          2.1//2
                          2.1^^2

                (4)字符串输入错误检测:
                          1+3.1+5=
                          1#3.3
                           #                          
                           (())
                           回车
                           空格

未来教育考试系统:计算机二级与专业技能综合练习 简介:本系统旨在帮助考生准备国家计算机二级考试,涵盖了包括Java编程和医药知识在内的多个领域。系统包含模拟考试平台,提供模拟练习和测试,提高用户对计算机理论知识、编程语言、数据库管理和操作系统原理的理解。同时,为医疗行业从业者提供护理和药学相关IT应用的练习题。通过使用该系统,考生能够自我测试,发现弱点,强化训练,最终提升通过考试的可能性。系统设计旨在帮助用户充分准备并提高应对考试的能力。 阅读详情

相关推荐

C语言强化训练1

C语言强化训练

c语言强化训练

1、编写一个程序,用户输入某个大写字母,产生一个金字塔图案。例如用户输入字母E,则产生如下图案:3、编写一个程序,该程序要求输入一个float型数并打印概述的立方值。3、编写一个程序,该程序读取输入直到遇到#字符,然后报告读取的空格数目、读取的换行符数目以及读取的所有其他字符数目。4、编写一个程序,此程序要求输入天数,然后将该值转换为星期数和天数。4、编写一个程序,接受一个整数输入,然后显示所有小于或等于该数的素数。5、输入一个华氏温度,要求输出摄氏温度。

qq_57629682的博客 581

c语言强化训练题及答案

c语言相关训练题及答案,面试必备。小伙伴们学习求职必备佳品哦!

【C语言】数组的强化训练(详细讲解+源码展示)

这是数组的强化训练知识,也是续前面数组知识点之后特地而出的强化训练部分,本部分将很好的带你复习数组知识,并学习更多与数组有关的知识。通过这篇文章,你可以很好的掌握一些数组逆序,数组最值以及冒泡排序等相关方法。.........

感谢您的关注! 907

C语言强化训练(2)

截止现在,我们C语言的大部分基础内容就已经讲完了,但是,光掌握基础只是还是不够的,所以小编会将自己写过的一些题整理起来,不定期更新刷题博客,希望能扩展大家的思路。话不多说,现在就开始我们的第一篇刷题博客吧!!

pusue_the_sun的博客 872

必练的100道C语言程序设计练习题(上)

在计算机编程的世界中,C语言一直是一门备受推崇的语言。它的简洁性、高效性以及广泛应用使得学习C语言成为每一位程序员的必由之路。然而,掌握这门语言并不是一蹴而就的事情,它需要不断的练习和实践。为了帮助各位编程爱好者更好地理解和掌握C语言的精髓,我整理了一份“必练的100道C语言程序设计练习题(上)”。这不仅是一次对基础知识的回顾,更是一个深入学习的契机。通过挑战这些题目,你将更好地锻炼编程思维,提高问题解决能力,为未来的编程之旅打下坚实的基础。

分享关于数据的知识。 3579

pnd1 c语言,c语言强化训练——简易计算器

一、设计要求实现一个简单的计算器,要求可以求解表达式,支持基本的运算并有扩展能力和基本的容错能力二、设计思路程序需要定义两个工作栈,分别保存表达式计算过程中的运算符与运算数,通过一个优先级表来判定运算顺序。通过判定输入的运算符来调用不同的函数,实现支持基本的运算符号。可以通过定义一个运算符表和一个函数指针表,通过查找方式调用函数,实现运算符的可扩展性。三、详细设计1、首先需要编写一个栈,这个栈需要...

weixin_27180827的博客 243

c语言强化训练笔记2010/5/16

 函数指针的应用首先实现一个基本的计算器,暂时可以支持加减乘除功能int add(int,int);int sub(int,int);int mul(int,int);int div(int,int);main(){ char a[30]; char b[30]; char c; gets(a); printf("%c/

一个程序员的成长历程 853

c语言高级项目训练,《C语言程序设计》综合训练项目任务书.doc

《C语言程序设计》综合训练项目任务书综合训练项目一:简单计算器目的和要求:提高学生数据类型、输入输出、选择结构及循环结构程序设计方法的应用能力完成简单的计算器根据菜单的提示,选择要进行的运算,通过输入数据,完成加、减、乘、除等各种运算,要求计算器可重复使用。成果形式:源程序代码综合训练项目二:学生成绩统计系统目的和要求:为了强化数组、函数和指针等相关知识的掌握,综合利用数组、函数及指针等相关知识解...

weixin_35977770的博客 436

数据分析——day01

教学导航 JavaSE内容: 基础语法:变量、数据类型、分支结构、循环结构、数组 基础语法的强化训练 OOP:面向对象的分析——结合项目 常用API:字符串、集合、IO流 常用的API训练 网络编程——Socket 多线程——聊天室 1、Java概述 面向对象的语言。区别于c. 1.1Java语言的学习—了解 特性:简单性、面向对象、健壮性、安全性、可移植性… Java跨平台能力: 编写桌面程...

weixin_44690848的博客 212

C++学习进程安排

[非原创,看到有参考价值,所以果断转来:原文链接]   第一阶段(Linux C开发) 目标:能使用并管理linux系统,熟悉linux开发环境。熟练掌握C语言语法。掌握Linux下C开发方法。 主题  内容 Linux最佳入门 ...

weixin_33755847的博客 88

数据挖掘01

教学导航 JavaSE内容: 基础语法:变量,数据类型,分支结构,循环结构,数组 基本语法的强化训练 OOP:面向对象的分析----结合项目 常用API:字符串,集合,Io流 常用API训练 网络编程----Soder 多线程---聊天室 1、 java概述: 面向对象的语言,区别于C 1.1 java语言的学习: 特性:简...

weixin_44690311的博客 179

JavaSE基础学习

CSDN Github 简书 技术博客 要求 :打卡(技术分析,自己笔记,项目经验,学习收获)。—分享 day01 课前10分钟,自我介绍。(2位同学 ,点评) 教学导航 JavaSE内容: 基础语法:变量、数据类型、分支结构、循环结构、数组 基础语法的强化训练 OOP:面向对象的分析—结合项目 常用API:字符串、集合、IO流 常用的API的训练 网络编程—Socket 多线程—聊天室 1、 j...

weixin_44690275的博客 179

数据挖掘day01

javaSE ​ 基础语法:变量,数据类型 分支结构 循环结构 数组 基础语法强化训练 oop 面向对象的分析--结合项目 常用api 字符串集合 io流 常用api 训练 网络编程socket 多线程 聊天室 1、java概述 ​ 面向对象的语言 区别于C 1.1java语言的学习 了解 ​ 特性:简单、面向对象、健壮、安全性 ​ java跨品台能力: ​ 编写桌面程序、web应用...

weixin_44425833的博客 208

2022年贵州大学计算机考研(初试+复试+实验室经验贴)

初试篇 ​​​ 初试估分英语85,政治75往上,结果差强人意吧。 首先讲一下自己考研经历,属于双非、在职、跨考840,直接三层debuff。 关于是否歧视双非:和同学聊了聊,一致是认为贵大计院是很公平的,不存在歧视情况,但是双非肯定是有优势的。所以别给自己那么多焦虑吧,好好备考。 关于跨考:是信工跨考计算机专业,本科期间进过实验室,做过挺多项目,所以对专业课并没有抵触心理,专业课学起来也比较轻松。只要你本科进过实验室、真正有过计算机竞赛经历、认真做过计算机项目,跨考应该是不难的。至于没有学过C语言

qq_34146295的博客 1万+

小白学javaSE基础

javaSE内容 基础语法:变量、数据类型、分支结构、循环结构、数组 基础语法的强化训练 oop:面向对象的分析—结合项目 常用API:字符串、集合、io流 常用的API训练 网络编程—socket 多线程–聊天室 1.Java概述 面向对象的语言。区别于C。 1.1 Java语言的学习—了解 特性简单性、面向对象、健壮性、安全性、可移植跨平台能力 编写桌面程序、Web应用程序、分布式...

qq_41171883的博客 212
上一篇: 百度VS谷歌:优秀与伟大之别
下一篇: J2SE配置文件读取工具
lingdushanke
博客等级 码龄18年 48粉丝 35原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值