目录
1、掌握栈与队列的定义;
2、掌握掌握栈与队列的基本操作。
1.验证某算术表达式的正确性,若正确,则计算该算术表达式的值。
(1)、从键盘上输入表达式的值。
(2)、分析该表达式是否合法:
(a)是数字,则 判断该数字的合法性。若合法,则压入数据存放堆栈。
(b)是规定的运算符,则根据规则进行处理。在处理过程中,将计算该表达式的值。
(c)若是其它字符,则返回错误信息。
(3)、若上述处理过程中没有发现错误,则认为该表达式合法,并打印处理结果。
表达式的计算过程:
1、变量直接输出;
2、遇到“(”,无条件入栈;
3、输入运算优先数是2,3,4,5,时,如栈空则入栈,否则,将其与栈顶元素进行比较,如果优先级大,就进栈,否则就退栈输出;
4、如遇“)”,同时栈顶元为“(”,则退栈,抹去括号。
首先将用户输入一整串的运算式存入字符exp数组,然后通过栈进行一系列处理得到运算结果。
(1)输入运算式,定义并初始化数字栈和字符栈分别用于存储输入数据中的数字和运算符。
(2)若为数字,则压入数字栈,此处与众不同的是通过归并的思想,可实现多位数的运算。
(3)若为运算符,则首先进行与栈顶元素优先级的判断。若优先级低于栈顶元素,则运算符栈栈顶元素弹出,同时弹出数字栈两个栈顶元素进行运算。得到的运算结果压入数字栈;若优先级高于栈顶元素,则直接入栈;若优先级相等,则栈顶元素出栈。
(4)若为空格,则直接跳过。
(5)若为其他情况,则判为非法字符输入,程序停止运行。
(6)经过一系列的运算、出栈、入栈的操作后,最终获取数字栈中的数据可得运算结果。
此次实验代码,经过反复思考,通过三次更改,得到了最后的版本。
5.此程序总体功能:可实现多位整数的运算,但由于时间有限,尚未想出浮点数的求值算法。
6.现版本输入方式的选取:整体输入。此方式可通过直接建立一个字符数组利用gets方法或scanf函数获取输入的数据。逐个输入则需要使用getchar()进行逐个读取。整体输入相对逐个输入更加直观。
7.优先级判断函数的思路:在前两个版本中,我采用的是比较直白的if语句,列出可能的情况进行结果输出。现版本受网上资料的启发,采用以二维数组存储优先列表,将可能的7*7种情况列出,利用switch语句,输出对应的结果,更加直观。
8.提高程序健壮性的体现:
(1)整个程序运算中,无可避免的出现了除法运算,因此在求值函数operate中,当theta为“/”,利用if语句判断,若除数为0,则提示用户输入错误并结束程序。
(2)运算式输入的字符串出现非法字符、空格的处理:在evaluateExpression函数中,同样采用if语句进行判断,若为空格,则使用continue跳过,若不为字符、数字和空格,则输入为非法字符,程序将提示输入错误。
(3)在对栈操作方面的体现:初始化栈时对内存是否申请成功进行判断、入栈时对是否栈满进行判断、出栈和获取栈顶元素时对是否栈空进行判断。
9.程序运行界面友好的体现:输入输出方面进行一系列的提示,以输入为更重要,受程序算法限制,输入的运算式必须以“#”结尾,否则无法准确的识别。




(1)通过此次实验对栈这一数据结构有了更深一步的认识,也更加熟悉了栈的一系列表示和实现操作。
(2)通过表达式求值方法的探索,深入理解了“后缀表达式”的含义,并掌握了将中缀表达式转化为后缀表达式的方法,这同样也是表达式求值的重要算法。
(3)在功能扩展方面,将个位数的运算提升到多位数的运算,很好的学习并利用了归并的思想,其与递归思想有很多类似之处。
(4)对C语言和C++两种编程语言差别的认识又多了一个细微的收获:
最初采用的是这种函数参数,即函数参数带&符号,与教材上的伪代码一致。但在实际运行时Xcode编译器却一直对此处报错(结果如下)。查阅资料后发现,&为引用符,它是C++的内容,当需要对原变量进行修改时,可以给参数添加&。但部分C语言编译器是无法适用的。


问题的解决:思考后发现,这种函数参数加&的功能与C语言指针的功能十分相似,因此将函数参数定义为指针类型即可很好的解决此问题;另一方面,也可以直接将文件后缀名从.c
改为.cpp,即改成C++文件,同样可以解决此问题。
表达式求值这一算法核心在于对运算式的运算过程,利用栈来实现是很方便的。因此便涉及运算符优先级的判断和如何对进行有序的运算的思考。此外,对功能是否可以扩展的思考同样极为重要,其可大大提高程序的实
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
//利用宏常量定义最大存储空间
#define Maxsize 100
//定义数字栈
typedef struct Stack
{
int *top;
int *base;
int stacksize;
}sqstack;
//构造空栈
void initStack(sqstack *s)
{
//申请内存空间
s->base=(int *)malloc(Maxsize*sizeof(int));
if(!s->base)
{
printf("栈初始化失败!\n");
return;
}
//初始化,此时栈空
s->top=s->base;
s->stacksize=Maxsize;
return;
}
//入栈操作
int push(sqstack *s,int e)
{
if(s->top-s->base==s->stacksize)
{
printf("栈满!\n");
return 0;
}
*s->top++=e;
return 1;
}
//出栈操作
int pop(sqstack *s,int *elem)
{
if(s->base==s->top)
{
printf("栈空!\n");
return 0;
}
*elem=*--s->top;
return 1;
}
//获取栈顶元素
int getTop(sqstack *s)
{
if(s->base==s->top)
{
printf("栈空!无法获取元素!\n");
return 0;
}
return *(s->top-1);
}
//判断运算符优先级
char Precede(char theta1,char theta2)
{
int i = 0,j = 0;
//对7*7种可能性进行分列,得到最后的运算符对比结果
char pre[7][7]={// + - * / ( ) =
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}};
switch(theta1){
case '+': i=0; break;
case '-': i=1; break;
case '*': i=2; break;
case '/': i=3; break;
case '(': i=4; break;
case ')': i=5; break;
case '=': i=6; break;
}
switch(theta2){
case '+': j=0; break;
case '-': j=1; break;
case '*': j=2; break;
case '/': j=3; break;
case '(': j=4; break;
case ')': j=5; break;
case '=': j=6; break;
}
return(pre[i][j]);
}
//对操作数进行运算
int Operate(int a,char theta,int b)
{
switch(theta){
case'+':return a+b;
case'-':return a-b;
case'*':return a*b;
case'/':
//考虑分母为0的情况,若除数为零返回错误提示
if(b!=0)
return a/b;
else
{
printf("分母为0,无意义!\n");
exit(0);
}
}
return 0;
}
//判断是否为运算符,若是运算符返回1,若不是返回0
int isChar(char c)
{
switch(c){
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '=':
return 1;
default:
return 0;
}
}
//核心算法,进行运算式运算
int evaluateExpression(char exp[])
{
//定义运算数栈、运算符栈
sqstack OPND,OPTR;
/* a,b,theta用于Operate函数
X用于存放多余的出栈字符
X1,X2用于归并 */
int a,b;
int x,X1,X2,theta;
//读取字符的变量
char ch;
//指向存放表达式数组的下标指针(其实不是真正的指针,而是数组下标)
int i=0;
//建立并初始化运算数栈OPND
initStack(&OPND);
//建立并初始化运算符栈OPTR
initStack(&OPTR);
//先将“=”号压入OPTR栈(表达式也必须以“=”结束)
push(&OPTR,'=');
//ch读取字符数组第一个元素,并将指针i后移一位
ch=exp[i++];
//表达式没有扫描完毕或OPTR的栈顶不为“=”
while(ch!='='||getTop(&OPTR)!='=')
{
if(isChar(ch)) //判断ch是否为操作符
{
//比较ch的与OPTR栈顶元素的优先级
switch(Precede(getTop(&OPTR),ch))
{
case'<':
push(&OPTR,ch);
//读取下一位字符并将指针向后偏移一位
ch=exp[i++];
break;
case'>':
/*若栈顶操作符优先级更大,则弹出运算符栈顶运算符及数字栈栈顶两个运算数
*/
pop(&OPTR,&theta);
pop(&OPND,&b);
pop(&OPND,&a);
//运算结果压入数字栈
push(&OPND,Operate(a,theta,b));
break;
case'=':
//若优先级相当,则将运算符栈栈顶元素弹出
pop(&OPTR,&x);
//读取下一位字符并将指针向后偏移一位
ch=exp[i++];
break;
}
}
//判断是否为数字字符
else if(isdigit(ch))
{
//将字符形式转化为数字
X1=ch-'0';
push(&OPND,X1);
X2=X1;
//读取下一位字符并将指针向后偏移一位
ch=exp[i++];
//归并思想,实现多位数运算
while(isdigit(ch)) //判断下一位是否还是数字
{
X1=ch-'0';
X2=10*X2+X1; //归并至X2
pop(&OPND,&x);
push(&OPND,X2);
ch=exp[i++]; //读取下一位字符并将指针向后偏移一位
}
}
else if(ch==' ') //判断是否为空格
{
while(ch==' ') //跳过若干个空格
{
ch=exp[i++]; //忽略空格,直接取下一位
}
}
else //若不是上述三种情况之一,则为非法字符
{
printf("Input has illegal characters!\n");
printf("Please enter again.\n");
exit(0); //返回错误提示
}
}
return(getTop(&OPND)); //最后返回操作数栈顶为运算结果
}
int main()
{
char exp[100]; //定义一个字符数组用于存储表达式
int result;
printf("请输入运算式(运算式尾部务必加上‘=’):\n");
gets(exp);
result=evaluateExpression(exp);
printf("运算式及运算结果如下:\n");
printf("%s%d\n",exp,result);
return 0;
}
分享结束,感谢观看!!!
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit