the c programming language second edition 第四章函数与程序结构笔记
4.3外部变量
- C语言程序可以看成由一系列的外部对象构成,这些外部对象可能是变量或函数
- 外部变量和函数具有以下性质:通过同一个名字对外部变量的所有引用实际上都是引用同一个对象。(标准把这一性质称为外部链接)
- 因为外部变量可以在全局范围内访问,这就为函数之间的数据交换提供了一种可以代替函数参数与返回值的方式。
- 外部变量的用途还表现在它们与内部变量相比具有更大的作用域和更长的生存期,外部变量是永久存在的它们的值在一次函数调用到下一次函数调用之间保持不变。因此在需要函数共享某些数据时最方便的方式是把这些共享数据定义为外部变量而不是作为函数参数传递。
用逆波兰表示法表示
在逆波兰表示法中所有运算符都跟在操作数后面,比如
(1-2)(4+5) == 12-45+
while(下一个运算符或操作数不是文件结束指示符)
if(是数)
将该数压入栈中
else if(是运算符)
弹出所需数目的操作数
执行运算
将结果压入到栈中
else if(是换行符)
弹出并打印栈顶的值
else
出错
- 栈的压入与弹出操作比较简单,但是,如果把错误检测与恢复操作都加进来,该程序就很长,最好把它们设计成独立的函数,而不要把它们作为程序中重复的代码使用。另外还需要一个单独的函数来取下一个输入运算符或操作数
- main函数不需要了解控制栈的变量信息,它只进行压入与弹出操作。因此可以把栈及相关信息放在外部变量中,并只提供push与pop函数访问,而不能被main函数访问
#include···//包含一些头文件
#define···//一些define定义
main(){}
void push (double f){}
double pop(void){}
int getop(char s[]){}
- 逆波兰计算器强化版
#include <stdio.h>
#include<math.h>
#include <string.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXOP 100//操作数或运算符的最大长度
#define NUMBER '0'//标识找到了一个数
void push(double);//把f压入到值栈中
double pop(void);//弹出并返回栈顶的值
int getop(char []);//截取下一个运算符或数值操作数
int getch(void);//读取下一个待处理的字符
int ungetch(int);//用于把字符放回到输入中
//程序中经常会出现这样的情况:程序不能确定它已经读入的输入是否足够,除非超前多读入一些输入
void clear(void);
int main()
{
int type;
double op1,op2;
char s[MAXOP];
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof(s));
break;
case '+':
push(pop()+pop());
break;
case '*':
push(pop()*pop());
break;
case '-'://不满足交换律运算符左右操作数必须加以区分
op2=pop();
push(pop()-op2);
break;
case '/':
op2=pop();
if(op2!=0.0)
push(pop()/op2);
else
printf("error:zero dibisor\n");
break;
case '%':
op2=pop();
if(op2!=0.0)
push(fmod(pop(),op2))
else printf("error: zero divisor\n");
case '\n':
printf("\t%.8g\n",pop());
break;
case '?'://在不弹出元素的情况下打印栈顶元素
op2=pop();
printf("\t%.8g\n",op2);
push(op2);
break;
case 'c'://清空栈
clear();
break;
case 's'://交换栈顶两个元素
op1=pop();
op2=pop()
push(op1);
push(op2);
break;
case 'd'://复制栈顶元素
op2=pop();
push(op2);
push(op2);
break;
default:
printf("error:unknown command %s\n",s);
break;
}
}
return 0;
}
//-------------------------------------------------
#define BUFSIZE 100
#define maxval 100//val的最大深度
int sp=0;//下一个空闲栈位置
double val[maxval];//值栈
void push(double f)//把f压入到值栈中
{
if(sp<maxval)val[sp++]=f;
else printf("error:stack full %g failed\n",f);
}
double pop(void)//弹出并返回栈顶的值
{
if(sp>0) return val[--sp];
else
{ printf("error:stack empty\n");
return 0.0;
}
void clear(void)//清空栈
{
sp=0;
}
}
//-------------------------------------------------
//-------------------------------------------------
char buf[BUFSIZE];//用于ungetch函数的缓冲区
int bufp=0;//buf中下一个空闲位置
int getch(void)
{
return (bufp>0)?buf[--bufp]:getchar();
}
int ungetch(int c)
{
if(bufp>=BUFSIZE) printf("ungetch: too many characters\n");
else buf[bufp++]=c;
}
//-------------------------------------------------
int getop(char s[])//截取下一个运算符或数值操作数
{
int i,c;
while((s[0]=c=getch())==' '||c=='\t');
s[1]='\0';
if(!isdigit(c)&&c!='.'&&c!='-')return c;//不是数
i=0;
if(c=='-')//考虑负数的情况
{
if(isdigit(c=getch())||c=='.')
s[++i];
}
if(isdigit(c))//收集整数部分
while(isdigit(s[++i]=c=getch()));
if(c=='.')//收集小数部分
while(isdigit(s[++i]=c=getch()));
s[i]='\0';
if(c!=EOF)ungetch(c);
return NUMBER;
}
//-------------------------------------------------