CC语言实现的数据结构课程设计的计算器堆栈

合集下载

实验报告堆栈操作

实验报告堆栈操作

一、实验目的1. 理解堆栈的基本概念和原理;2. 掌握堆栈的基本操作,包括入栈、出栈、取栈顶元素等;3. 熟悉堆栈在编程中的应用,提高编程能力。

二、实验原理堆栈是一种后进先出(Last In First Out, LIFO)的数据结构,它由一系列元素组成,遵循“先进后出”的原则。

在堆栈中,新元素总是被添加到栈顶,而移除元素时,总是从栈顶开始。

堆栈的基本操作包括:1. 初始化:创建一个空堆栈;2. 入栈:将一个元素添加到堆栈的顶部;3. 出栈:从堆栈中移除顶部元素;4. 取栈顶元素:获取堆栈顶部的元素,但不从堆栈中移除;5. 判断堆栈是否为空:检查堆栈中是否还有元素。

三、实验器材1. 计算机软件:C/C++编译器;2. 程序代码编辑器:例如Visual Studio、Code::Blocks等。

四、实验步骤1. 初始化堆栈:创建一个空堆栈,并设置栈的最大容量。

2. 入栈操作:(1)检查堆栈是否已满,如果已满,则无法入栈;(2)将元素添加到堆栈的顶部。

3. 出栈操作:(1)检查堆栈是否为空,如果为空,则无法出栈;(2)从堆栈中移除顶部元素。

4. 取栈顶元素操作:(1)检查堆栈是否为空,如果为空,则无法取栈顶元素;(2)获取堆栈顶部的元素。

5. 判断堆栈是否为空操作:(1)检查堆栈中的元素个数,如果为0,则堆栈为空。

6. 编写程序实现上述操作,并进行测试。

五、实验结果与分析1. 初始化堆栈:创建一个最大容量为10的空堆栈。

2. 入栈操作:(1)入栈元素1,堆栈状态:[1];(2)入栈元素2,堆栈状态:[1, 2];(3)入栈元素3,堆栈状态:[1, 2, 3]。

3. 出栈操作:(1)出栈元素3,堆栈状态:[1, 2];(2)出栈元素2,堆栈状态:[1]。

4. 取栈顶元素操作:(1)取栈顶元素1,栈顶元素为1。

5. 判断堆栈是否为空操作:(1)判断堆栈是否为空,结果为“否”。

六、实验结论通过本次实验,我们掌握了堆栈的基本概念、原理和操作。

c语言制作简单的计算器

c语言制作简单的计算器

c语言制作简单的计算器在计算机编程领域中,C语言是一种广泛使用的编程语言之一。

它具有简单易学的特点,并且能够进行复杂的计算和逻辑处理。

今天,我们就来学习一下如何使用C语言来制作一个简单的计算器。

首先,我们需要明确我们计算器的功能和界面设计。

本次制作的计算器将具有基本的四则运算功能,即加法、减法、乘法和除法。

我们将在控制台中实现计算器的操作,并通过简单的用户界面进行交互。

接下来,我们需要创建一个C语言程序的框架。

首先,我们需要包含头文件,以便在程序中使用各种函数和变量。

我们可以使用"#include" 来引入头文件,例如:```c#include <stdio.h>```然后,我们需要定义主函数 `main()`。

在这个函数中,我们将编写计算器的逻辑代码。

让我们开始编写函数吧!首先,我们需要声明一些变量来存储用户输入的数字和运算符。

我们可以使用 `int` 来定义整数变量,并用 `char` 定义字符变量。

例如:```cint num1, num2, result;char operator;```接下来,我们需要提示用户输入要进行的运算,并读取用户输入的数字和运算符。

我们可以使用 `printf` 和 `scanf` 函数来完成这个任务,例如:```cprintf("请输入第一个数字: ");scanf("%d", &num1);printf("请输入运算符(+, -, *, /): ");scanf(" %c", &operator);printf("请输入第二个数字: ");scanf("%d", &num2);```注意,我们在读取运算符之前添加了空格,这是为了消除输入缓冲区中可能残留的换行符等字符。

接下来,我们需要编写代码来进行实际的计算操作。

用堆栈实现四则运算c语言

用堆栈实现四则运算c语言

用堆栈实现四则运算c语言堆栈是一种常见的数据结构,它符合先进后出的原则。

在四则运算中,我们可以借助堆栈这种数据结构实现运算,方便高效,不易出错。

堆栈的实现包括两个基本操作:Push(入栈)和Pop(出栈)。

我们可以以此设计四则运算。

首先,我们需要将输入的四则运算表达式转换成后缀表达式。

后缀表达式也叫逆波兰表达式,相对于中缀表达式而言,运算符在后面,操作数在前面,这样方便计算机进行读取和计算。

例如:中缀表达式:5+3*2后缀表达式:5 3 2 * +将中缀表达式转换成后缀表达式,我们需要用到堆栈。

具体的实现方法是,从左向右遍历表达式,如果是数字,则直接输出;如果是符号,则将其与堆栈顶的符号进行比较,如果优先级高就入栈,否则不断将符号出栈并输出,直到当前符号优先级大于堆栈顶符号优先级,最后将当前符号入栈。

例如:表达式:5+3*2堆栈操作:1.将5输出,堆栈为空2.遇到+号,入栈3.将3输出,堆栈顶为+号4.遇到*号,入栈5.将2输出,堆栈顶为*号6.输出*号,堆栈顶为+号7.输出+号,堆栈为空得到后缀表达式:5 3 2 * +有了后缀表达式,我们可以用堆栈进行计算。

具体方法是,从左向右遍历后缀表达式,如果是数字则入栈,如果是符号则将栈顶两个数字出栈并进行计算,将结果入栈,最终得到最终的计算结果。

例如:后缀表达式:5 3 2 * +堆栈操作:1.将5入栈2.将3入栈3.遇到*号,出栈3和2,进行计算得到6,将6入栈4.将栈顶元素5出栈5.遇到+号,出栈6和5,进行计算得到11,将11入栈得到计算结果:11通过堆栈实现四则运算,可以有效简化我们的计算流程,避免复杂的优先级判断和计算错误。

同时,堆栈为我们提供了一种更加高效的数据结构,不仅在四则运算中可以发挥作用,在其他应用中也很常见。

当然,在实际应用中,我们需要考虑到多种情况的处理,例如负数、小数、括号等,以及错误处理等细节问题,才能保证算法的正确性和可靠性。

MCS51单片机程序设计时堆栈的计算方法解析

MCS51单片机程序设计时堆栈的计算方法解析

MCS51单片机程序设计时堆栈的计算方法解析[导读]用C语言进行MCS51系列单片机程序设计是单片机开发和应用的必然趋势。

Keil公司的C51编译器支持经典8051和8051派生产品的版本,通称为Cx51。

应该说,Cx51是C 语言在MCS51单片机上的扩展,既有C语言的共性,又有它自己的特点。

本文介绍的是Cx51程序设计时堆栈的计算方法。

用C语言进行MCS51系列单片机程序设计是单片机开发和应用的必然趋势。

Keil公司的C51编译器支持经典8051和8051派生产品的版本,通称为Cx51。

应该说,Cx51是C语言在MCS51单片机上的扩展,既有C语言的共性,又有它自己的特点。

本文介绍的是Cx51程序设计时堆栈的计算方法。

1.堆栈的溢出问题。

MCS51系列单片机将堆栈设置在片内RAM中,由于片内RAM资源有限,堆栈区的范围也是有限的。

堆栈区留得太大,会减少其他数据的存放空间,留得太少则很容易溢出。

所谓堆栈溢出,是指在堆栈区已经满了的时候还要进行新的压栈操作,这时只好将压栈的内容存放到非堆栈区的特殊功能寄存器(SFR)中或者堆栈外的数据区中。

特殊功能寄存器的内容影响系统的状态,数据区的内容又很容易被程序修改,这样一来,之后进行出栈操作(如子程序返回)时内容已变样,程序也就乱套了。

因此,堆栈区必须留够,宁可大一些。

要在Cx51程序设计中防止堆栈的溢出,要解决两个问题:第一,精确计算系统分配给用户的堆栈大小,假设是M;第二,精确计算用户需要堆栈的大小,假设是N。

要求M≥N,下面分别分析这两个问题。

2.计算系统分配给用户的堆栈大小Cx51程序设计中,因为动态局部变量是长驻内存中的,实际上相当于局部静态变量,即使在函数调用结束时也不释放空间(这一点不同于标准C语言)。

Cx51编译器按照用户的设置,将所有的变量存放在片内和片外的RAM中。

片内变量分配好空间后,将剩下的空间全部作为堆栈空间,这个空间是最大可能的堆栈空间。

堆栈操作的实验报告

堆栈操作的实验报告

一、实验目的1. 理解堆栈的基本概念和特点。

2. 掌握堆栈的基本操作,包括初始化、进栈、出栈、查看栈顶元素等。

3. 熟悉堆栈在实际问题中的应用。

二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019三、实验内容1. 堆栈的定义与实现2. 堆栈的基本操作3. 堆栈的实际应用四、实验步骤1. 堆栈的定义与实现(1)设计堆栈类(Stack)```cpp#include <iostream>#include <vector>using namespace std;template <typename T>class Stack {private:vector<T> elements; // 使用动态数组存储元素int top; // 栈顶指针public:Stack() : top(-1) {} // 构造函数,初始化栈顶指针为-1 bool isEmpty() const { // 判断栈是否为空return top == -1;}bool isFull() const { // 判断栈是否已满return top == INT_MAX;}void push(const T& element) { // 进栈操作if (isFull()) {cout << "Stack is full." << endl;return;}elements[++top] = element;}bool pop(T& element) { // 出栈操作if (isEmpty()) {cout << "Stack is empty." << endl;return false;}element = elements[top--];return true;}T getTop() const { // 查看栈顶元素if (isEmpty()) {cout << "Stack is empty." << endl;return T();}return elements[top];}};```(2)测试堆栈类```cppint main() {Stack<int> stack;stack.push(1);stack.push(2);stack.push(3);cout << "Stack top element: " << stack.getTop() << endl; // 输出栈顶元素int element;while (stack.pop(element)) {cout << "Pop element: " << element << endl; // 输出出栈元素}return 0;}```2. 堆栈的基本操作(1)初始化:使用构造函数初始化堆栈类,设置栈顶指针为-1。

c语言stack(栈)和heap(堆)的使用详解

c语言stack(栈)和heap(堆)的使用详解

c语⾔stack(栈)和heap(堆)的使⽤详解⼀、预备知识—程序的内存分配⼀个由C/C++编译的程序占⽤的内存分为以下⼏个部分1、栈区(stack)—由编译器⾃动分配释放,存放函数的参数值,局部变量的值等。

其操作⽅式类似于数据结构中的栈。

2、堆区(heap)—⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。

注意它与数据结构中的堆是两回事,分配⽅式倒是类似于链表。

3、全局区(静态区)(static)—全局变量和静态变量的存储是放在⼀块的,初始化的全局变量和静态变量在⼀块区域,未初始化的全局变量和未初始化的静态变量在相邻的另⼀块区域。

程序结束后由系统释放。

4、⽂字常量区—常量字符串就是放在这⾥的。

程序结束后由系统释放。

5、程序代码区—存放函数体的⼆进制代码。

⼆、例⼦程序复制代码代码如下://main.cppint a=0; //全局初始化区char *p1; //全局未初始化区main(){intb;栈char s[]="abc"; //栈char *p2; //栈char *p3="123456"; //123456\0在常量区,p3在栈上。

static int c=0; //全局(静态)初始化区p1 = (char*)malloc(10);p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。

strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成⼀个地⽅。

}三、堆和栈的理论知识2.1申请⽅式stack:由系统⾃动分配。

例如,声明在函数中⼀个局部变量int b;系统⾃动在栈中为b开辟空间heap:需要程序员⾃⼰申请,并指明⼤⼩,在c中⽤malloc函数如p1=(char*)malloc(10);在C++中⽤new运算符如p2=(char*)malloc(10);但是注意p1、p2本⾝是在栈中的。

c++堆栈使用方法

c++堆栈使用方法

c++堆栈使用方法堆栈是计算机科学中的一个重要概念,也是C语言中常用的一种数据结构。

在堆栈中,数据按照后进先出(LIFO)的原则进行存储和操作,这在很多场合下都非常有用。

本文将介绍如何在C语言中使用堆栈,包括堆栈的基本概念、数据类型、创建、初始化、操作等。

一、堆栈的基本概念堆栈是一种特殊的线性表,它只允许在顶部进行数据添加和删除操作。

在堆栈顶部的数据被添加和删除的速度最快,因此堆栈也被称为“先进后出”(LIFO)的数据结构。

在C语言中,可以使用数组来实现堆栈。

二、C语言中的堆栈数据类型在C语言中,可以使用数组来定义一个堆栈。

通常,我们使用一个特殊的指针来表示堆栈的顶部,该指针指向当前堆栈的最后一个元素。

堆栈的大小可以通过数组的大小来确定,也可以根据需要进行动态调整。

三、创建和初始化堆栈在C语言中,可以使用malloc()函数来动态分配内存空间来创建一个堆栈对象。

在使用malloc()函数之前,需要先定义一个大小足够大的数组来存储堆栈数据。

以下是一个简单的示例代码,用于创建一个大小为10的堆栈对象并初始化:```c#include <stdio.h>#include <stdlib.h>#define MAX_STACK_SIZE 10int main() {int stack[MAX_STACK_SIZE];int top = -1; // 初始化时堆栈为空int *p = stack; // 指向堆栈顶部的指针// 初始化堆栈for (int i = 0; i < MAX_STACK_SIZE; i++) {stack[i] = i; // 将元素依次存入堆栈中}// 输出初始化后的堆栈内容printf("初始化后的堆栈内容:");for (int i = 0; i <= top; i++) {printf("%d ", stack[i]); // 从顶部开始输出元素}printf("\n");return 0;}```四、操作堆栈使用堆栈时,可以通过push()函数将元素添加到堆栈顶部,通过pop()函数从堆栈顶部删除元素,通过peek()函数查看堆栈顶部的元素但不删除它。

计算机软件基础实验 堆栈

计算机软件基础实验 堆栈

一、实验目的1.复习堆栈的基础知识2.练习入栈出栈操作二、实验设备装有运行C语言环境的计算机。

三、实验内容实验一1.对下述给定程序,完成:1)阅读并运行程序。

2)在有’/* */’的语句后加注释,说明语句功能2.编程完成在具有10个元素的堆栈的栈顶插入数据11。

要求:调试通过并将源程序提交。

四、实验步骤和结果实验一代码1.#include <stdio.h>#define stacksize 100int push(int s[], int x, int *ptop)/*入栈*/{int top;top = *ptop; /* top 等于传入的栈的指针所在位置*/if (top == stacksize) /* 判断头指针是否等于栈的最大值*/{printf("overflow");return (0);} /* 判断栈满的时候输出“overflow”程序结束*/else {s[top] = x; /* 将传入的x值给现在栈顶所在位置*/*ptop = ++top; /* 栈顶上移*/return (1);} /* 栈未满时进行入栈操作*/}void main(){static int s[100];int top = 0, result;result = push(s, 11, &top); /* 让11入栈如果成功返回1 result=1 否则result=0 */if (result == 1) /* 入栈成功*/{printf("success ! \n");printf("top=%d", top);} /* 入栈成功输出sucess 并且把栈顶位置输出*/else printf("failure!");/*入栈失败输出failure*/}2.#include <stdio.h>#define stacksize 100int pop(int s[ ], int *ptop, int *py)/* 出栈函数*/{int top;top=*ptop;/* top 等于传入栈顶指针所在位置值*/if(top==0)/* 位置=0 栈空*/{ printf("stack empty");return( 0); }/*栈空时输出stack empty 返回值0 */else { --top;*py=s[top]; /* 将栈顶元素弹出*/*ptop=top;/*将下移的栈顶指针值赋值给*ptop */return(1);}}void main(){static int s[20]={10,20,30};int top=3,result,y;result=pop(s,&top,&y);/*出栈函数调用成功出栈后result=1 否则等于0 */if(result ==1){ printf ("success ! \n");printf ("top=%d,y=%d ", top,y);}/* 成功出栈后输出success 并且将栈顶指针位置值和栈顶元素值输出*/else printf("failure!");}插入代码#include <stdio.h>#define stacksize 100int pop(int s[ ], int *ptop, int *py)/* 出栈函数*/{int top;top=*ptop;/* top 等于传入栈顶指针所在位置值*/if(top==0)/* 位置=0 栈空*/{ printf("stack empty");return( 0); }/*栈空时输出stack empty 返回值0 */else { --top;*py=s[top]; /* 将栈顶元素弹出*/*ptop=top;/*将下移的栈顶指针值赋值给*ptop */return(1);}}int push(int s[], int x, int *ptop)/*入栈*/{int top;top = *ptop; /* top 等于传入的栈的指针所在位置*/if (top == stacksize) /* 判断头指针是否等于栈的最大值*/{printf("overflow");return (0);} /* 判断栈满的时候输出"overflow"程序结束*/else {s[top] = x; /* 将传入的x值给现在栈顶所在位置*/*ptop = ++top; /* 栈顶上移*/return (1);} /* 栈未满时进行入栈操作*/}void main(){static int s[20]={10,20,30,15,2,1,8,9,8,7};int top=9,a,y,b;a=push(s,11,&top);if ( a== 1) /* 入栈成功*/{printf("\n 入栈成功! \n");printf("top=%d", top);} /* 入栈成功输出sucess 并且把栈顶位置输出*/b=pop(s,&top,&y);/*出栈函数调用成功出栈后result=1 否则等于0 */if(b ==1){ printf ("\n 出栈成功! \n");printf ("top=%d,y=%d \n", top,y);}/* 成功出栈后输出success 并且将栈顶指针位置值和栈顶元素值输出*/else printf("failure!");}五、总结和问题1.问题:对于出栈入栈函数自己书写时采用的传值,导致传入值在函数中并没有获得更新。

数据结构-使用C语言 朱战立 第3章堆栈和队列

数据结构-使用C语言 朱战立 第3章堆栈和队列

top
D top C B A
D C B A
top
D C B A
top
顺序栈出栈函数的核心语句: S->top --; d = S->stack[S->top];
17
例5、 设依次进入一个栈的元素序列为c,a,b,d,则 可得到出栈的元素序列是:
A)a,b,c,d C)b,c,d,a
B)c,d,a,b D)a,c,d,b
初始化堆栈S 堆栈S非空否 入栈 出栈 取栈顶数据元素
11
二、堆栈的顺序表示和实现 1、顺序(堆)栈
顺序存储结构的堆栈。
顺序栈S an an-1 …… 栈顶top
2、顺序栈的存储结构
它是利用一组地址连续的存储 单元依次存放自栈底到栈顶的数据 元素,同时设指针top指示当前栈顶 位置。
ai …… a1 a0
具体方法:顺序扫描算术表达式(表现为一个字符串), 当遇到三种类型的左括号时让该括号进栈; 1. 当扫描到某一种类型的右括号时,比较当前栈顶括号是 否与之匹配,若匹配则退栈继续进行判断; 2. 若当前栈顶括号与当前扫描的括号不相同,则左右括号 配对次序不正确; 3. 若字符串当前为某种类型左括号而堆栈已空,则右括号 多于左括号; 4. 字符串循环扫描结束时,若堆栈非空(即堆栈中尚有某 种类型左括号),则说明左括号多于右括号;否则,左 右括号匹配正确。
14
顺序栈S
高地址
栈顶top
an an-1 …… ai …… a1 a0 入栈口诀:堆栈指针top “先 压后加” : S[top++]=an 栈底base 出栈口诀:堆栈指针top “先 减后弹” : e=S[--top]
低地址
栈不存在的条件: base=NULL; 栈为空的条件 : base=top或top<=0; 栈满的条件 : top-base=MaxSize;

C语言简单计算器原理——表达式求值(采用逆波兰表达式和栈结合)

C语言简单计算器原理——表达式求值(采用逆波兰表达式和栈结合)

C语⾔简单计算器原理——表达式求值(采⽤逆波兰表达式和栈
结合)
表达式的求解的关键是将其转换成逆波兰表达式(即后缀表达式,如1+2*3它的逆波兰表达式为123*+),在后缀表达式中已经考虑了运算符的优先级,
没有括号,只有操作数和运算符。

算术表达式转换成后缀表达式⽅法如下:
依次从键盘输⼊表达式的字符ch,对于每个ch:
(1)若ch为数字则直接将其放⼊后缀数组exp中并以#号标记数值串结束。

(2)若ch为"(",则直接将其压⼊字符栈op中。

(3)若ch为")",则将栈中"("以前的字符依次全部删除并将其放⼊后缀数组exp中,然后再将字符ch放⼊字符栈op中。

(4)若ch为"+"."-",则将栈中"("以前的运算符依次全部删除并将其放⼊后缀数组exp中,然后再将ch放⼊op栈中。

(5)若ch为"*"."/",则将栈顶连续的"*"."/"删除,并放⼊后缀数组exp中,然后将ch放⼊op栈中。

(6)若字符串str扫描完毕,则将栈中所有运算符删除并放⼊后缀数组exp,最后在后缀数组exp中便可得到后缀表达式。

在对后缀表达式求值时要⽤到⼀个数值栈st,在后缀数组exp中从头开始扫描,若是数字则将其放⼊数值栈中,
若遇到字符就进⾏两次退栈,并将运算结果再放⼊栈中,如此重复下去,最后当后缀数组扫描完后数值栈st的栈顶元素便是所要求的表达式的值。

C语言数据结构之栈的基本操作

C语言数据结构之栈的基本操作

C语言数据结构之栈的基本操作栈是一种特殊的数据结构,它按照后进先出(LIFO)的原则进行操作。

栈可以用数组或链表来实现,下面将介绍栈的基本操作。

1.初始化栈:栈的初始化就是为栈分配内存空间,并将栈顶指针设置为-1(如果是数组实现)或者NULL(如果是链表实现)。

2.判断栈空:栈空表示栈中没有任何元素。

如果栈顶指针等于-1或者NULL,则表示栈空。

3.判断栈满:栈满表示栈中已经存满了元素。

如果栈顶指针等于栈的最大容量减1,则表示栈满。

4. 进栈(push):进栈操作就是将元素放入栈中。

如果栈不满,则将栈顶指针加1,并将元素放入栈顶位置。

5. 出栈(pop):出栈操作就是从栈中取出一个元素。

如果栈不空,则将栈顶指针减1,并返回栈顶元素。

6. 获取栈顶元素(getTop):获取栈顶元素操作不改变栈的状态,只返回栈顶元素的值。

如果栈不空,则返回栈顶元素值;否则,返回空值。

7.清空栈:清空栈操作就是将栈中的所有元素全部出栈,即将栈顶指针设置为-1或者NULL。

8.销毁栈:销毁栈操作是释放栈的内存空间,将栈的指针设置为NULL。

栈的应用:栈在计算机领域有广泛的应用,其中一个常见的应用是函数调用栈。

当一个函数调用另一个函数时,当前函数的状态(包括局部变量、返回地址等)会被压入到栈中。

当被调用函数执行完成后,栈顶的元素会被弹出,然后继续执行调用该函数的代码。

另一个常见的应用是表达式求值。

在表达式求值过程中,需要用到运算符优先级。

我们可以利用栈来处理运算符的优先级。

将运算符入栈时,可以先与栈顶运算符比较优先级,如果栈顶运算符的优先级高于当前运算符,则将栈顶运算符出栈,并继续比较。

这样可以确保栈中的运算符按照优先级从高到低的顺序排列。

此外,栈还可以用于处理括号匹配问题。

当遇到左括号时,将其入栈;当遇到右括号时,判断栈顶元素是否为对应的左括号,如果是,则将栈顶元素弹出,否则表示括号不匹配。

如果最后栈为空,则表示所有括号都匹配。

计算器

计算器

湖南工程学院应用技术学院课程设计报告课程名称 C语言程序设计课题名称计算器专业电气工程及其自动化班级电气工程0783学号200713010315姓名刘毅指导教师王颖2008年3 月19 日湖南工程学院课程设计任务书课程名称C语言程序设计课题计算器专业班级电气工程0783学生姓名刘毅学号200713010315指导老师王颖审批任务书下达日期:2008 年3月8日任务完成日期:2008年3月20日前言《C语言程序设计》课程设计是对学生的一种全面综合训练,它包括问题分析,总体结构设计,用户界面设计,程序设计基本技能和技巧,多人合作,以至一整套软件工作规范的训练和科学作风的培养。

是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。

通常,课程设计的课题比平时的习题复杂得多,也更接近实际。

课程设计着眼于与应用的结合点,使学生学会如何把书上学到的知识用于解决实际问题,培养软件工作所需要的动手能力;另一方面,能使书上的知识变“活”,使学生更好地深化理解和灵活掌握教学内容。

为了达到上述目的,本课程设计安排了八个设计课题,训练重点在于基本的程序设计方法和分析问题的能力,而不强调面面俱到。

学生可任选其中一题进行设计,设计完毕写出课程设计报告,用A4纸打印成册;并将课程设计报告与源程序存盘。

学习委员将课程设计报告与磁盘收齐后交指导老师。

一、目的全面熟悉、掌握C语言基本知识,掌握C程序设计中的顺序、分支、循环三种结构及数组、函数和C语言基本图形编程等方法,把编程和实际结合起来,增强对不同的问题运用和灵活选择合适的数据结构以及算法描述的本领,熟悉编制和调试程序的技巧,掌握分析结果的若干有效方法,进一步提高上机动手能力,培养使用计算机解决实际问题的能力,养成提供文档资料的习惯和规范编程的思想,为以后在专业课程中应用计算机系统解决计算、分析、实验和设计等学习环节打下较扎实的基础。

二、基本情况课程类别:必修课课程学分:1学分课程学时:1周课程对象:电气工程0781、0782、0783、0784、0785、0786四、调试过程规范化要求1)需要分析分析系统功能需求以及用户操作流程。

c语言中的堆栈

c语言中的堆栈

c语言中的堆栈摘要:1.堆栈的概念与作用2.C语言中的堆栈实现3.堆栈的使用方法与注意事项4.堆栈溢出的原因及预防5.堆栈在编程中的应用实例正文:堆栈是计算机科学中一种重要的数据结构,主要用于实现函数调用、局部变量存储以及算法递归等功能。

在C语言中,堆栈有着广泛的应用,下面我们将详细介绍堆栈的相关知识。

1.堆栈的概念与作用堆栈是一种线性数据结构,遵循后进先出(LIFO)的原则。

堆栈分为栈顶和栈底,数据元素在栈中按照顺序排列,只有栈顶元素可以被访问和修改,其他元素则无法直接访问。

堆栈的主要作用有以下几点:- 函数调用:C语言中,函数调用是通过堆栈来实现的。

每当一个函数被调用,它的局部变量、返回地址等信息会被压入堆栈。

函数执行完毕后,堆栈会将这些信息弹出,恢复调用者的状态。

- 局部变量存储:在C语言中,局部变量的存储也是通过堆栈来实现的。

当进入一个函数时,局部变量会被压入堆栈;函数执行完毕后,局部变量会被自动弹出。

- 算法递归:递归算法通常使用堆栈来保存递归调用时的中间结果,从而避免重复计算。

2.C语言中的堆栈实现C语言中的堆栈是由操作系统提供的,通常使用一组固定大小的内存区域来实现。

堆栈的增长方向是向下的,堆栈指针指向栈顶元素。

在C语言中,堆栈的操作主要包括入栈(push)和出栈(pop)两种。

3.堆栈的使用方法与注意事项使用堆栈时,需要注意以下几点:- 避免堆栈溢出:堆栈空间是有限的,如果栈中的元素数量过多,会导致堆栈溢出。

因此,在使用堆栈时,需要合理控制栈的大小,避免长时间递归调用或大量使用局部变量。

- 遵循栈的生长方向:在C语言中,堆栈的生长方向是向下的,因此入栈操作会使栈顶指针减小,出栈操作会使栈顶指针增大。

- 注意栈的操作顺序:在函数调用中,先入栈的是函数的返回地址,然后是局部变量;函数执行完毕后,首先弹出的是局部变量,然后是返回地址。

4.堆栈溢出的原因及预防堆栈溢出是由于栈中的元素数量过多,导致栈空间不足而引发的。

c语言实现栈详细代码

c语言实现栈详细代码

c语言实现栈详细代码栈(Stack),又称堆栈,是一种后进先出(LIFO,Last In First Out)的数据结构,它只允许在一段端点进行插入和删除操作,这个端点被称为栈顶。

C语言实现栈的基本思路是建立一个结构体,结构体中包含一个数组和栈顶指针top。

数组用来存放栈中元素,top指针指向栈顶元素的下标。

实现栈的操作包括压栈(push)、出栈(pop)和获取栈顶元素(get_top)。

下面是详细代码:```#include <stdio.h>#include <stdlib.h>#define MAX_SIZE 100 //栈的最大长度typedef struct stack {int data[MAX_SIZE]; //栈中元素int top; //栈顶指针} Stack;//初始化栈void init(Stack *s) {s->top = -1; //栈顶指针初始化为-1,表示栈为空}//判断栈是否为空int is_empty(Stack *s) {return s->top == -1;}//判断栈是否已满int is_full(Stack *s) {return s->top == MAX_SIZE-1;}//压栈void push(Stack *s, int value) {if (is_full(s)) {printf("Stack is full, cannot push!\n");return;}s->data[++(s->top)] = value; //栈顶指针先加1,再将元素入栈}//出栈void pop(Stack *s) {if (is_empty(s)) {printf("Stack is empty, cannot pop!\n");}s->top--; //栈顶指针减1,表示栈顶元素已删除}//获取栈顶元素int get_top(Stack *s) {if (is_empty(s)) {printf("Stack is empty, cannot get top element!\n"); return -1;}return s->data[s->top]; //返回栈顶元素}int main() {Stack s;init(&s); //初始化栈for (i = 0; i < 5; i++) {push(&s, i); //压入5个元素}printf("Top element: %d\n", get_top(&s)); //获取栈顶元素while (!is_empty(&s)) {printf("%d ", get_top(&s)); //依次输出栈中元素pop(&s); //弹出栈顶元素}return 0;}```代码中定义了一个结构体,包含一个整型数组data和一个整型变量top,数组用来存放栈中元素,top表示栈顶指针。

数据结构(C语言版)课程设计报告表达式求值说明书

数据结构(C语言版)课程设计报告表达式求值说明书

数据结构(C语言版)课程设计报告表达式求值说明书XX大学数据结构课程设计说明书题目:表达式求值院系:计算机科学与工程学院专业班级:计算机班学号:学生姓名:指导教师:2021年X月X日XX大学课程设计(论文)任务书计算机科学与工程学院学号学生姓名专业(班级)设计题目表达式求值设计技术参数系统平台:Windows7/WindowsXP开发工具:VC++6.0设计要求(1)能够计算的运算符包括:加、减、乘、除、圆括号。

(2)能够计算的数要求在实数范围内。

(3)能执行多重括号嵌套运算。

(4)对于异常表达式给出错误提示。

工作量课程设计报告要求不少于3000字。

源程序要求不少于300行工作计划2021.11.21-12.01根据课程设计大纲的要求,查找相关资料,完成需求分析;2021.12.02-12.16进行系统的概要设计;2021.12.17-12.31进行系统的详细设计和源代码的书写;2021.01.01-01.17对系统进行调试分析,写出课程设计报告。

参考资料[1]何钦铭主编.C语言程序设计.北京:高等教育出版社,2021.[2]谭浩强编著.C程序设计(第四版).北京:清华大学出版社,2021.[3]严蔚敏,吴伟民编著.数据结构(C语言版)北京:清华大学出版社,2021.[4]严蔚敏,吴伟民编著.数据结构题集北京:清华大学出版社,2021.指导教师签字教研室主任签字2021年X月X日学生姓名:学号:专业班级:课程设计题目:表达式求值指导教师评语:成绩:指导教师:年月日XX大学课程设计(论文)成绩评定表目录1需求分析12概要设计12.1设计思路12.2存储结构设计12.3功能模块设计13详细设计14运行与测试15总结1参考文献2(要求:给出一级目录和二级目录,宋体,四号字,1.5倍行距,页码使用罗马数字,居中)(报告正文部分):(要求:正文部分一律用小四号字,宋体,行距20磅。

一级标题靠左,加粗。

二级大标题靠左,不加粗。

C语言计算器实现(中缀表示法后缀表示法)

C语言计算器实现(中缀表示法后缀表示法)

C语⾔计算器实现(中缀表⽰法后缀表⽰法)————————————————————————————————————————————实现原理:每个操作数都被依次压⼊栈中,当⼀个运算符到达时,从栈中弹出相应数⽬的操作数(对于⼆元运算符来说是两个操作数),把该运算符作⽤于弹出的操作数,并把运算结果再压⼊栈中- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -计算器(后缀表达式)相关知识:后缀表达式(逆波兰表⽰法):在逆波兰中,所有运算符都跟在操作数后⾯,如下:(1 - 2) *(4 + 5) 采⽤逆波兰表⽰法表⽰为:1 2 - 4 5 + *,不需要圆括号,只要知道每个运算符需要⼏个操作数就不会引起歧义实现功能:输⼊后缀表达式,以换⾏结束,计算四则运算结果。

对于 1 2 - 4 5 + * 来说,⾸先把1和2压⼊到栈中,再⽤两者之差-1取代它们;然后将4和5压⼊到栈中,再⽤两者之和9取代它们。

最后从栈中取出栈顶的-1和9,并把它们的积-9压⼊到栈顶。

到达输⼊⾏的末尾时,把栈顶的值弹出来并打印。

伪代码:while 读⼊值不为换⾏时if 是数字压⼊栈中else if 是运算符弹出两个运算数,计算并压栈else 输⼊错误并退出end if读⼊值弹出最终结果并打印实现代码:1/* 实现功能:输⼊后缀表达式,以换⾏结束,计算四则运算结果 */2/* 这种后缀表⽰法只需要⼀个栈就可以了,遇到符号则弹运算数,但是中缀就不⼀样 */3 #include <stdio.h>4 #include <stdlib.h>5#define OK 16#define ERROR 07#define OVERFLOW -28#define STACK_INIT_SIZE 1009#define STACKINCREAMENT 1010 typedef int Status;11 typedef char SElemType;12 typedef struct13 {14 SElemType *top;15 SElemType *base;16int stacksize;17 } SqStack;18 Status InitStack(SqStack *s)19 {20 s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));21if (!s->base) exit(OVERFLOW);22 s->top = s->base;23 s->stacksize = STACK_INIT_SIZE;24return OK;25 }26 Status Push(SqStack *s, SElemType e)27 {28if (s->top - s->base == s->stacksize)29 {30 s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType)); 31if (!s->base) exit(OVERFLOW);32 s->top = s->base + s->stacksize;33 s->stacksize += STACKINCREAMENT;34 }35 s->top++;36 *(s->top) = e;37return OK;38 }39 Status Pop(SqStack *s, SElemType *e)40 {41if (s->top == s->base) exit(OVERFLOW);42 *e = *(s->top);43 s->top--;44return OK;45 }46 Status Empty(SqStack s)47 {48if (s.top - s.base == 0)49return OK;50else51return ERROR;52 }53int main()54 {55 SqStack OPND; //OPTR是运算符 OPND是运算数56char c, num1, num2;57 InitStack(&OPND);58while((c = getchar()) != '\n')59 {60switch(c)61 {62case'0':63case'1':64case'2':65case'3':66case'4':67case'5':68case'6':69case'7':70case'8':71case'9':72 Push(&OPND, c - '0');73break;74case'+':75 Pop(&OPND, &num2);76 Pop(&OPND, &num1);77 Push(&OPND, num1 + num2);78break;79case'-':80 Pop(&OPND, &num2);81 Pop(&OPND, &num1);82 Push(&OPND, num1 - num2);83break;84case'*':85 Pop(&OPND, &num2);86 Pop(&OPND, &num1);87 Push(&OPND, num1 * num2);88break;89case'/':90 Pop(&OPND, &num2);91 Pop(&OPND, &num1);92 Push(&OPND, num1 / num2);93break;94default:95break;96 }97 }98while(!Empty(OPND))99 {100 Pop(&OPND, &c);101 printf("%d ", c);102 }103return OK;104 }- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -计算器(中缀表⽰法)运算符优先级:+-*/()# +>><<<>>->><<<>>*>>>><>>/>>>><>>(<<<<<=0)>>>>0>>#<<<<<0=执⾏过程:在计算 #4+3*(5-10)/5# 时栈中的执⾏过程如下步骤输⼊字符执⾏操作OPTR OPND 1#Push(#)#24Push(4)#43+'#'<'+',Push(+)# +443Push(3)# + 4 35*'+'<'*',Push(*)# + * 4 36('*'<'(',Push(()# + * ( 4 375Push(5)# + * ( 4 3 58-'('<'-',Push(-)# + * ( - 4 3 5910Push(10)# + * ( - 4 3 5 1010)'-'>')',计算并压⼊结果# + * ( 4 3 -511'('=')',脱括号# + * 4 3 -5 12/'*'>'/'计算并压⼊结果# + 4 -1513'+'<'/',Push(/)# + / 4 -15145Push(5)# + / 4 -15 5 15#'/'>'#',计算并压⼊结果# + 4 -316'+'>'#',计算并压⼊结果#117'#'='#',脱括号1伪代码:初始化运算符栈;压⼊#;初始化运算数栈;获取输⼊;while 获取输⼊不为#或栈顶不为#if 输⼊的是数字压⼊运算数栈获取输⼊if 新输⼊的也是数字⼗位数百位数运算end ifelseswitch 运算符栈顶与当前输⼊优先级⽐较压⼊运算符栈获得输⼊弹出运算符栈顶(或#获得输⼊弹出运算符栈顶弹出两个运算数计算并将结果压⼊运算数栈//此时不获取新输⼊,该循环输⼊的运算符作为c重新进⼊循环end ifend while输出运算数栈中剩的运算数实现代码:1/* 只能运算-128~127之间的结果 */2 #include <stdio.h>3 #include <stdlib.h>4 #include <math.h>5#define OK 16#define ERROR 07#define SPILL -2 //math.h中已有OVERFLOW,则改⽤SPILL8#define STACK_INIT_SIZE 1009#define STACKINCREAMENT 1010 typedef char SElemType;11 typedef int Status;12 typedef struct13 {14 SElemType *top;15 SElemType *base;16int stacksize;17 } SqStack;18 Status InitStack(SqStack *s)19 {20 s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));21if (!s->base)22 exit(SPILL);23 s->top = s->base;24 s->stacksize = STACK_INIT_SIZE;25return OK;26 }27 Status EmptyStack(SqStack s)28 {29if (s.top - s.base == 0)30return OK;31else32return ERROR;33 }34 Status Push(SqStack *s, SElemType e)35 {36if (s->top - s->base == s->stacksize)37 {38 s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType)); 39if (!s->base)40 exit(SPILL);41 s->top = s->base + s->stacksize;42 s->stacksize += STACKINCREAMENT;43 }44 s->top ++;45 *(s->top) = e;46return OK;47 }48 Status Pop(SqStack *s, SElemType *e)49 {50if (s->top == s->base)51 exit(SPILL);52 *e = *(s->top);53 s->top--;54return OK;55 }56 SElemType GetTop(SqStack s)57 {58return *(s.top);59// *e = *(s.top);60// return OK;61 }62/* 判断如果是数字则返回OK,运算符返回ERROR,⾮法输⼊则退出 */63 Status InputJudge(SElemType c)64 {65switch(c)66 {67case'0':68case'1':69case'2':70case'3':71case'4':72case'5':73case'6':74case'7':75case'8':76case'9':77return OK;78break;79case'+':80case'-':81case'*':82case'/':83case'(':84case')':85case'#':86return ERROR;87break;88default:89 exit(SPILL);90break;91 }92 }93/* 当前输⼊的运算符和前⼀个运算符⽐较优先级 */94 SElemType PriorityJudge(SElemType optr1, SElemType optr2)95 {96int i, j;97char priorityTable[7][7] =98 {99 {'>', '>', '<', '<', '<', '>', '>'},100 {'>', '>', '<', '<', '<', '>', '>'},101 {'>', '>', '>', '>', '<', '>', '>'},102 {'>', '>', '>', '>', '<', '>', '>'},103 {'<', '<', '<', '<', '<', '=', '0'},104 {'>', '>', '>', '>', '0', '>', '>'},105 {'<', '<', '<', '<', '<', '0', '='}106 };107switch(optr1)108 {109case'+':110 i = 0;111break;112case'-':113 i = 1;114break;115case'*':116 i = 2;117break;118case'/':119 i = 3;120break;121case'(':122 i = 4;123break;124case')':125 i = 5;126break;127case'#':128 i = 6;129break;130 }131switch(optr2)132 {133case'+':134 j = 0;135break;136case'-':137 j = 1;138break;139case'*':140 j = 2;141break;142case'/':143 j = 3;144break;145case'(':146 j = 4;147break;148case')':149 j = 5;150break;151case'#':152 j = 6;153break;154 }155return priorityTable[i][j];156 }157/* 四则运算 */158 SElemType Calc(SElemType optr, SElemType num1, SElemType num2)159 {160switch(optr)161 {162case'+':163return (num1 + num2);164break;165case'-':166return (num1 - num2);167break;168case'*':169return (num1 * num2);170break;171case'/':172return (num1 / num2);173break;174 }175 }176int main()177 {178char c, optr, num1, num2, temp;179 SqStack OPND, OPTR;180 InitStack(&OPTR);181 Push(&OPTR, '#');182 InitStack(&OPND);183 c = getchar();184while(c != '#' || GetTop(OPTR) != '#')185// while(!EmptyStack(OPTR))186//严蔚敏⽼师书上的算法是判断输⼊⾮#或栈顶⾮#时循环,个⼈认为判断运算符栈不为空也可以,当初始化时压⼊的#闭合,结束运算187 {188if (InputJudge(c))189 {190 Push(&OPND, c - '0');191 c = getchar();192/* 当连续输⼊数字时,计算⼗位数和百位数 */193while(InputJudge(c))194 {195int i = 1;196 Pop(&OPND, &temp);197 Push(&OPND, temp * pow(10, i) + (c - '0'));198 i++;199 c = getchar();200 }201 }202else203switch(PriorityJudge(GetTop(OPTR), c))204 {205case'<':206 Push(&OPTR, c);207 c = getchar();208break;209case'=':210 Pop(&OPTR, &c);211 c = getchar();212break;213case'>':214 Pop(&OPTR, &optr);215 Pop(&OPND, &num2);216 Pop(&OPND, &num1);217 Push(&OPND, Calc(optr, num1, num2)); 218break;219 }220 }221while(!EmptyStack(OPND))222 {223 Pop(&OPND, &c);224 printf("%d\n", c);225 }226return OK;227 }。

简述堆栈及其用途

简述堆栈及其用途

简述堆栈及其用途堆栈(Stack)是一种常见的数据结构,用于存储数据的容器。

它的特点是“后进先出”(Last In First Out,简称LIFO),即最后一个进入堆栈的元素将第一个被移除。

堆栈的用途广泛,常见于计算机科学和软件开发领域。

下面将从不同角度介绍堆栈及其用途。

堆栈在计算机的内存管理中起着重要作用。

在程序执行过程中,局部变量、函数调用和返回地址等信息通常存储在堆栈中。

当一个函数被调用时,它的局部变量被压入堆栈,当函数执行完毕时,这些变量被弹出。

这样可以保证函数之间的数据独立性,避免相互干扰。

堆栈在表达式求值中也有着重要的应用。

例如,中缀表达式转换成后缀表达式时就需要使用堆栈。

堆栈可以帮助我们按照正确的顺序处理运算符和操作数,并最终得到正确的计算结果。

堆栈还广泛应用于递归算法和深度优先搜索(DFS)等算法中。

递归算法通常需要使用堆栈来保存每一层递归调用的信息,以便在递归结束后能够正确返回。

DFS也是基于堆栈实现的,通过不断将未访问的节点入栈,并在访问完一个节点后将其出栈,可以实现对图或树的深度遍历。

堆栈还被广泛应用于编译器和解释器的实现中。

编译器在将源代码转换成目标代码的过程中,通常使用堆栈来保存运算符和操作数的顺序,以便生成正确的目标代码。

解释器在解释执行代码时,也需要使用堆栈来保存执行上下文和临时变量的信息。

堆栈还可以用于实现缓冲区(Buffer)和撤销操作(Undo)等功能。

在文本编辑器中,当我们输入字符时,这些字符被依次压入堆栈,当我们按下撤销按钮时,字符会从堆栈中被弹出,实现了撤销的功能。

在操作系统中,堆栈还可以用于保存进程的现场信息,以便在需要时能够恢复到之前的状态。

堆栈作为一种简单而有效的数据结构,在计算机科学和软件开发中有着广泛的应用。

它在内存管理、表达式求值、递归算法、深度优先搜索、编译器和解释器实现等方面发挥着重要的作用。

了解和掌握堆栈的使用方法,对于提高程序的效率和正确性具有重要意义。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C、C++语言实现的数据结构课程设计的计算器(堆栈)/*// 我真诚地保证:// 我自己独立地完成了整个程序从分析、设计到编码的所有工作。

// 如果在上述过程中,我遇到了什么困难而求教于人,那么,我将在程序实习报告中// 详细地列举我所遇到的问题,以及别人给我的提示。

// 我的程序里中凡是引用到其他程序或文档之处,// 例如教材、课堂笔记、网上的源代码以及其他参考书上的代码段,// 我都已经在程序的注释里很清楚地注明了引用的出处。

// 我从未没抄袭过别人的程序,也没有盗用别人的程序,// 不管是修改式的抄袭还是原封不动的抄袭。

// 我编写这个程序,从来没有想过要去破坏或妨碍其他计算机系统的正常运转。

// &lt;李雷阳&gt;*//********************************************************************用堆栈做的计算器程序*创建者:李雷阳*创建时间:2011.03.12 *最后修改时间:2011.03.15 */********************************************************************/********************************************************************本程序功能:实现用堆栈处理计算表达式具体内容:I: 如果算式里面有计算式不应该出现的字符,则将其智能略去如:将(1.4a54+2f.6)*3.09s+4ff看成(1.454+2.6)*3.09+4II: 检查括号是否匹配,如果匹配,再检查是否出现在合法位置如:(8*(7-4)不匹配,以及65*(72+98)(70-45)匹配但是不合法III: 检查计算数与计算符号的数量是否合格如:+23-4* 、23-4*、+23-4 等等IV: 检查输入小数的时候小数点是否输入过多以及智能改正如:将3....2*10+8 看成3.2*10+8V: 检查连续输入大于两个符号时候是否能智能修改,“不能”则-&gt; 对于3+-2 给出判断结果:输入有误VI: 接V:如果判断能够改正,则-------------------------------&gt;将4++++++++++++5看成4+5并计算VII:检测“0”是否出现在分母上【下边是检测数据,检测结果与期望结果吻合】【注:输入数据结尾没有“#”,以为在我的程序里面要它没用】()*2+3# 期望结果:输入有误(3+3)*3+1*(1+3)-3/2+3*3# 期望结果:29.51+2*(4-5)+45# 期望结果:44.000000(1.454+2.6)*3.09+4# 期望结果:16.5269(1.4a54+2f.6)*3.09s+4ff# 期望结果:16.5269(56-23)/8-4# 期望结果:0.12534+p(u89-12.3)k/3# 期望结果:59.566789.5*749+25)# 期望结果:输入有误89.5*749+25# 期望结果:67060.500000(8*(7-4)# 期望结果:输入有误65*(72+98)(70-45) # 期望结果:输入有误6*# 期望结果:输入有误)5+3(# 期望结果:输入有误(3+)(4)# 期望结果:输入有误3....2*10+8# 期望结果:40+23-4*# 期望结果:输入有误23-4*# 期望结果:输入有误+23-4# 期望结果:输入有误3+-2# 期望结果:输入有误4+++++++++++++++5# 期望结果:9********************************************************************//********************************************************************* 程序中所用到的头文件*********************************************************************/#include&lt;iostream&gt;#include&lt;cstring&gt;using namespace std;/********************************************************************* 宏定义*********************************************************************/#define MAX_LENGHT 50//预先假设计算字符串最多有500个字符#define MAX 10//一般情况下输入要计算的数不会超过10位/********************************************************************* 自定义函数*********************************************************************/bool isOperand(char ch);//检查是否为操作数int priority( char op);//设置操作等级并返回操作符op的等级template &lt;class Stack_type&gt;//用计算符号op计算数字number_1 和number_2Stack_type caculate( char op, const Stack_type number_1, const Stack_type number_2 );char *mark(char string[]);//将符号和数字放在同一个堆栈里面时,两个数字可能会连在一起,导致无法区分//哪个是第一个数哪个是第二个数,这里我用了小方法,就是在每个数字后边加个//字母a来将两个连着的数字区分开char *parsing(char A_string[]);//将将传入的中缀计算字符串A_string转化成后缀计算字符串并返回一个指针float result(char A_string[]);//计算用函数“char *parsing(char A_string[]);”转化过的后缀计算字符串的值bool check(char A_string[]);/*自定义堆栈*/template&lt;class Type&gt;class Stack;template&lt;class Type&gt;class StackNode{friend class Stack&lt;Type&gt;;private:Type data;StackNode&lt;Type&gt; *link;StackNode(Type D=0,StackNode&lt;Type&gt; *L=NULL):link(L),data(D){}};template&lt;class Type&gt;class Stack{public:Stack():_top(NULL),NumItem(0){}void push(Type item);void pop(); //Type pop();Type top();void MakeEmpty();bool empty();private:int NumItem;StackNode&lt;Type&gt; *_top;};template&lt;class Type&gt;void Stack&lt;Type&gt;::push(Type item){_top=new StackNode&lt;Type&gt;(item,_top);NumItem++;}template&lt;class Type&gt;void Stack&lt;Type&gt;::pop(){StackNode&lt;Type&gt; *p;p=_top;_top=_top-&gt;link;delete p;NumItem--;}template&lt;class Type&gt;Type Stack&lt;Type&gt;::top(){return _top-&gt;data;}template&lt;class Type&gt;bool Stack&lt;Type&gt;::empty(){return _top==NULL;}template&lt;class Type&gt;void Stack&lt;Type&gt;::MakeEmpty(){delete _top;}/********************************************************************* 主函数*********************************************************************/int main()//主函数{char inputString0[MAX_LENGHT];//定义输入的字符串int i=1;char inputString[MAX_LENGHT];//为了不改变输入的字符串,用来充当计算过程中的inputString0while(1){if(i){puts(&quot;请输入计算式,以“#”号结束(如:65*(72+98)*(70-45)#)&quot;);i=0;} cout &lt;&lt;&quot;&gt;&gt;&quot;;gets( inputString0 );//从键盘接收输入的计算字符串inputString0strcpy( inputString , inputString0 );//为了不改变输入的字符串inputString0,用inputString来充当计算过程中的//inputString0.以后计算用到计算字符串的时候都将inputString传递,而原始字符串//inputString0不变if(check(inputString)==false){cout &lt;&lt;&quot;输入有误!&quot;&lt;&lt;endl;//exit(0);}else{strcpy( inputString , mark(inputString) );//进行标记inputString并且返回赋值给inputStringstrcpy( inputString , parsing(inputString) );//将【经过处理】的中缀计算字符串返回并且赋值给inputStringcout &lt;&lt;&quot;&gt;&gt;=&quot;&lt;&lt;result(inputString)&lt;&lt;endl&lt;&lt;endl; //计算最终的结果}}return 0;}/*********************************************************************函数名称:isOperand **函数表述: 检查ch是否为操作数**输入值:char ch **返回值:检查ch是否为操作数,是则返回1,否则返回0 * ********************************************************************/bool isOperand(char ch){bool ret;//ret :标记是否为操作数switch(ch){case &#39;+&#39;:case &#39;-&#39;:case &#39;*&#39;:case &#39;/&#39;:case &#39;(&#39;:case &#39;)&#39;:ret = false;//ret=0 :ch不是操作数break;default :ret = true;//ret=1 :ch是操作数break;}return ret;}/******************************************************************** *函数名称:priority **函数表述: 为操作符op (+、-、*、/)设置操作等级并返回操作符op的等级* *输入值:char op **返回值:返回操作符op的等级*********************************************************************/int priority(char op){int p;//p表示操作符号的等级switch(op){case &#39;+&#39;:case &#39;-&#39;:p = 1;break;case &#39;*&#39;:case &#39;/&#39;:p = 2;break;default:p = 0;break;}return p;}/******************************************************************** *函数名称:mark **函数表述: 在每个数字后边添加a **输入值:char string[] **返回值:返回添加字符a后的字符串*********************************************************************/char *mark(char string[]){int i;int j;int lenght = strlen(string);//lenght :输入的计算字符串string[]的长度char A_string[MAX_LENGHT];//添加字母a 之后的新字符串,MAX_LENGHT初步宏定义为500,基本上已经足够了for(i = 0,j = 0; i &lt; lenght;)//从计算字符串string[]的第0为开始搜索到全部搜索过为止{if( isOperand(string[i]) || string[i]==&#39;(&#39; )//如果string[i]是数字或者“(”,则直接复制给新字符串A_string[i]A_string[j++] = string[i++];else if(string[i]==&#39;)&#39;)//如果string[i]是“)”,则前边一定是数字的最后边,{A_string[j++] = &#39;a&#39;;//此时给那个数字最后添加一个作为标记的符号“a”A_string[j++] = string[i++];//这个是将右括号复制给A_stringA_string[j++] = string[i++];//这里赋值是因为任何计算中,右括号后边第一个一定是计算符号,不用判断是否为数//字了,(因为这个函数的用途:见函数表述)所以这里直接复制给A_string}else{A_string[j++] = &#39;a&#39;;//这个就不解释了,上边解释过了A_string[j++] = string[i++];}}if( isOperand(A_string[j]) )A_string[j++] = &#39;a&#39;;//这里的原因是:当字符串的后边有一个数字,比如:A+B的时候,B后边没有操作符//号了,就不能正常给数字B后边添加字母a了A_string[j] = &#39;\0&#39;;//最后一定要给新的字符串一个结尾符return A_string;}/******************************************************************** *函数名称:parsing **函数表述: 将中缀字符串转化为后缀计算字符串* *输入值:char A_string[] **返回值:返回转化完的后缀计算字符串*********************************************************************/char *parsing(char A_string[]){int i;int j;char ch_0;char ch_1;int lenght = strlen(A_string);//输入的计算字符串的长度char B_string[MAX_LENGHT];Stack &lt;char&gt;setStack ;for( i = 0, j = 0; i &lt; lenght; i ++){ch_0 = A_string[i];if( isOperand(ch_0) )//如果是操作数,则直接赋值给B_stringB_string[j++] = ch_0;else{if( ch_0 == &#39;(&#39; )//左括号的时候--------{setStack.push(ch_0);//左括号直接压栈}else if( ch_0 == &#39;)&#39; )//右括号的时候--------{while( !setStack.empty() ){ch_0 = setStack.top(); setStack.pop();//弹出栈的最上边元素if( ch_0 == &#39;(&#39; )break;elseB_string[j++] = ch_0;//只要没有遇到左括号,就一直弹出栈内元素}}else//既不是左括号右不是右括号的时候---------{if( !setStack.empty() )//如果栈不是空的话{do{ch_1 = setStack.top(); setStack.pop();//弹出栈的最上边元素if( priority( ch_0 ) &lt;= priority( ch_1 ) )//当想入栈的元素级别小于栈内顶元素运算级别时{B_string[j++] = ch_1;//弹出栈顶元素if(setStack.empty())//当栈内没有元素了的时候,就不用比较了,直接入栈跳出去就OK了{setStack.push(ch_0);break;}}else{setStack.push(ch_1);//如果想入栈的元素的优先级别大于栈顶元素级别,//则将取出的元素和它都压入栈内setStack.push(ch_0);break;}}while( !setStack.empty() );}else//如果是空的话,就不用比较栈内元素和要入栈的元素级别了,直接入栈{setStack.push(ch_0);}}}}while( !setStack.empty() )//当栈内还有元素的时候,一起将所有元素弹出{B_string[j++] = setStack.top(); setStack.pop();}B_string[j] = &#39;\0&#39;;//给B_string加结尾符return B_string;}/*********************************************************************函数名称:caculate **函数表述: 用计算符 op 计算number_1 和number_2 **输入值:op、number_1 、number_2 **返回值:用计算符o p 计算number_1 和number_2的结果*********************************************************************/template &lt;class Stack_type&gt;Stack_type caculate( char op, const Stack_type number_1, const Stack_type number_2 ) {Stack_type temp;switch(op){case &#39;+&#39;:temp = number_1 + number_2;break;case &#39;-&#39;:temp = number_2 - number_1;//这里很容易出错,一定是栈下边减去栈上边的break;case &#39;*&#39;:temp = number_1 * number_2;break;case &#39;/&#39;:temp = number_2 / number_1;//这里很容易出错,一定是栈下边除以栈上边的break;}return temp;}/**********************************************************用这种写法也可以,但是这样的话会有一个waring,所以没有这样写**********************************************************//*template &lt;class Stack_type&gt;Stack_type caculate( char op, const Stack_type number_1, const Stack_type number_2 ) {switch(op){case &#39;+&#39;:return number_1 + number_2;case &#39;-&#39;:return number_2 - number_1;//这里很容易出错,一定是栈下边减去栈上边的case &#39;*&#39;:return number_1 * number_2;case &#39;/&#39;:return number_2 / number_1;//这里很容易出错,一定是栈下边除以栈上边的}}*//*********************************************************************函数名称:result **函数表述: 计算后缀计算字符串**输入值:char A_string[] **返回值:后缀计算字符串的结果*********************************************************************/float result( char A_string[]){int i, j, k;Stack &lt;float&gt; setStack;//数字栈/*接下来先把A_string[]里面的所有数字用浮点型堆栈setStack储存起来*/ char numString[MAX];//用atof将它转为float型再保存在堆栈里,一般情况下输入的数字不会大于10^10 float numNumber;//用atof将numString转化后传给numNumber,将float型numNumber压入栈中方便计算float temp[2];//接收需要计算的时候从栈里面弹出来的那两个float型元素float sum;//sum存储temp[0] 和temp[1] 的计算结果for(i = 0, j = 0, k = 0; i &lt; strlen(A_string); i ++){if( isOperand(A_string[i]) &amp;&amp; A_string[i]!=&#39;a&#39; )//当正在读取的是数字并且没有读完这个数字的所有位数的时候,{numString[j++] = A_string[i];//将正在读取的数字元素复制给numString}else{numString[j] = &#39;\0&#39;;//否则,当这个数字的所有位都读进numString[]的时候,给numString[]结尾标志,numNumber = atof(numString);//并且将它转换为float型,用float型的numNumber接收if(A_string[i]==&#39;a&#39;)//如果是因为遇到数字结尾标记字母“a”而进入else的话,将它直接压入堆栈,因为//此时这个数字后边的一定也是数字,而不是操作符。

相关文档
最新文档