4.3外部变量与逆波兰计算器

C语言程序可以看成由一系列的外部对象构成,这些外部对象可能是变量或函数。形容词external与internal是相对的。internal用于描述定义在函数内部的函数参数及变量。外部变量定义在函数之外可以在其他函数中使用。C语言不允许在函数中定义其他函数。外部变量永久存在,自动变量在退出函数消失。互不调用对方并且需要共享数据的两个函数,最好还是用外部变量。
书上说这个计算器程序的实现很简单,但是感觉是相对而言的,当时看这个的时候由于基础有限,看的还是比较难受的,但是当看到后面基础牢了点就好很多,现在来看这个确实是比较简单的一个程序,每个函数负责一个功能,而这些函数并不复杂,难的是想通其中的关键部分。
主要设计思路在书里这也不在多说。

逆波兰计算器
这个计算器例子我想了很长时间怎么解释,从哪部分开写,最后还是不想了,从头到后来吧。
定义函数时 push前面的void声明表示psh函数不返回任何值,括号里的double表示他要处理双精度浮点数类型的参数,pop的double声明表示他返回double类型的数值,但是没有任何附带参数。
首先看getop函数,用于获取下一个运算符或操作数。
这里又需要先说一下getch函数和ungetch函数
这两个函数想明白比较简单,想理解有那么一点复杂。

getch函数
返回一个值这个值有可能是在缓冲区也有可能是直接getchar获取,首先用一个外部变量bufp当做缓冲区的下标,因为两个函数修需要共享并且不互相调用,所以需要用到外部变量。
还有就是把buf当成缓冲区。
这个函数直接返回数值。条件判断式的值就是其返回值。
用一个条件表达式,判断buf缓冲区是否有字符存在。如果有则判断式的值为buf数组的第bufp个元素,如果buf数组没有字符存在则直接用getchar读取字符。然后将值返回。
return (bufp > 0) ? buf[--bufp] : getchar();

然后是ungetch函数。
这个函数将字符压入缓冲区。如果超过最大值则报警。
如果超过最大值则打印报警字符串。
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
不超过就直接将字符存入缓冲区buf数组。
buf[bufp++] = c;

再继续看getop函数。
跳过空白符,这里会将第0位元素保留为空白符(求指正)。
这里的保留为空白符是因为如果首位就是数字的话,还是需要保留的.因为首位是数字.s[0]就被赋值成数字了.
然后就会覆盖后面的空白符.
while ((s[0] = c = getch()) == ' ' | c == '\t')
;
然后将第1位元素置为‘\0’
s[1] = '\0'; 这里会把数组s变成一个只有一个空白符和结束符的数组。
之后是判断部分,首先判断是不是数,如果不是数并且不是小数点则将当前的字符返回给主函数main,让主函数去判断解决方法。
if (!isdigit(c) && c != '.')
return c;
接下来的将i赋值为0。
i = 0;
然后是收集整数部分,这里是将整数部分直接存入数组s中,这里的++i是前自增运算,先自增之后才参与赋值运算(这里最开始他的值是1,我做过测试,但是也不能保证肯定,希望有人指正。)
如果下标是1开始的话,那么之前的空格就会被留下了。(虽然留下也没什么atof函数我记得也会跳过空白符)
将整数部分的数收集到数组s中。
if(isdigit(c))
while (isdigit(s[++I] = c = getch()))
;
然后是碰到小数点,继续以同样的方式收集到数组s中。这里的i依然是先自增,目的是跳过的整数部分的最后一位。
if (c == '.')
while (isdigit(s[++i] = c =getch()))
;
最后将结束符'\0'加入数组s中。
s[i] = '\0';
然后继续判断,数值读取到最后还没到EOF文件结束符的话,那么需要将最后读入的这个字符放入缓冲区(原因书上写了,无法判断下一个字符到底是不是对程序有用的字符,只能先读取之后再看,所以如果不需要的话就需要将其放入缓冲区)
if (c != EOF)
ungetch(c);
然后都运行到这里了,就需要向主函数返回一个读取的是数的信号,
return NUMBER;

函数既然写这么多了,那就继续把剩下的两个比较简单和函数写完吧。
push函数。
作用就是将参数放入一个数组(栈)中。原理同上面的buf一样。如果不超过栈的最大值那么就将参数f放入到栈中。用变量sp记录栈顶的位置。
if (sp < MAXVAL)
val[sp++] = f;
如果超过最大值则显示错误报告。
else
printf("error: stack full, can't push %g\n", f);

pop函数就是将栈顶的元素取出变成返回主函数的值,就是说把pop函数当做栈顶的值。
if (sp > 0)
return val[--sp];
之后依然是错误报告,并且返回值为0.0。

之后进入主函数。
先定义变量type,用于确定字符是何种类型。op2用于直接指定运算顺序。数组s[MAXOP]需要运算的数。宏MAXOP是操作数或运算符的最大长度(100)。宏NUMBER也是一个用于判断类型。
int type;
double op2;
s[MAXOP];
直接用大循环判断当前字符的类型。之后就是通过switch语句进行分类操作,类型是什么就执行什么样的操作。,这里书上写的比较详细而且没什么难度,代码还很长久不直接写上来了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容