




已阅读5页,还剩144页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
我 们 采 用 的 教 材 名词的空间域 名词的时间域 第6章名词的空间域、时间域和物理存储 位置 名词的空间域和时间域不完全一致。有空间 域的类型或量值,一定有时间域。 有时间域的类型或量值,不一定有空间域。 6.1 C/C+程序的逻辑结构 从可执行的意义看,程序从小到大可分为如下逻 辑单位: 语句(statement)。 模块(block)。 嵌套模块。 6.1 C/C+程序的逻辑结构 从可执行的意义看,程序从小到大可分为如下逻 辑单位: 文件(file)。 工程(project)。 工作区(workspace)。 图6. 1 C/C+程序逻辑结构 6.2名词性的类型和量值在各逻辑结构上的 空间域 6.2.1模块域 例6. 1 量值模块作用域的验证 #include int fun(int x) int a=20; /函数模块fun内定义的a printf(“na= %d, x= %d“, a, x); /printf(“nb= %d“, b); / error C2065: b : undeclared identifier return a+x; void main() int a=10; /main模块内定义的a int b; /main模块内定义的b printf(“a= %d“,a); /输出的是main函数内定义的a的 值 b=fun(a); printf(“na= %d, b= %d“, a, b); /printf(“nx= %d“, x); /error C2065: x : undeclared identifier 例6. 2 类型模块作用域的验证 #include Person fun(); void main() Person LiSi; / main模块内声明定义在另一个函数内类 型Person的变量 LiSi=fun(); Person fun() struct Person /函数模块fun内定义的类型Person int id; char name10; ZS=1, “张三“; return ZS; 6.2.2嵌套模块的层域 例6. 3 嵌套模块中的同名类型或量值的空间域 #include void main() struct Person /main函数内(外层模块)定义的Person 类型 int id; char name10; ; struct Date /main函数内(外层模块)定义的Date类型 int year; int month; int day; ; Person ZS; /内嵌模块开始 struct Person / 内层模块定义的同名Person类型 int id; char name10; int Class; ; Person LiSi;/使用内层模块类型Person定义变量 Date Birthday; /Date类型只在外层定义,内层可见 printf(“n %dn“, sizeof(LiSi); /输出内嵌Person /内嵌模块结束 printf(“n %dn“, sizeof(ZS);/输出外层Person的大小 /printf(“n %d“, sizeof(LiSi); /error C2065: LiSi : undeclared identifier 6.2.3文件域 例6. 4 文件中定义的类型或量值的空间域 #include struct Person /定义在文件中的Person类型 int id; char name10; ; int i;/定义在文件中的int型变量i /*前面定义了类型和变量*/ /*后面引用了类型和变量*/ void main() Person ZS=1,“张三“; /外层模块中引用Person 类型 i=10;/ 内层模块内应用变量i printf(“i= %d“,i); printf(“n%d %sn“, ZS.id, ZS.name); 例6. 5 类型的先引用,后定义 #include int i; /*类型定义在后,而引用在先,会出现莫名其妙的 错误*/ void main() Person ZS=1,“张三“; /引用了定义在后面的 Person类型 i=10; printf(“i= %d“,i); printf(“n%d %sn“, ZS.id, ZS.name); struct Person /定义在文件后面的Person类型 int id; char name10; ; 下面的示例程序演示了用extern声明定义在后的变量的情况 。 例6. 6 变量的先声明,再应用,而后定义 #include #include struct Person /定义在先的Person类型 int id; char name10; ; void main() extern int i; /声明后面定义的变量 i =10; /定义在后面的变量的引用 extern Person ZS; /声明后面定义的变量 ZS.id=1; /定义在后面的变量的引用 strcpy(ZS.name, “张三“); /定义在后面的变量的 引用 printf(“ni= %d“, i); printf(“n%d %sn“, ZS.id, ZS.name); /* extern int j; /问题语句开始 j=200; printf(“nj=%d“, j); int j; / 问题语句结束 */ Person ZS; /定义在后的变量 int i;/定义在后的变量 6.2.4工程域 例6. 7工程内全局类型和量值空间域 首先,在VC中创建Win32 Console Application工程MyMFile(系统会自动添加文件 扩展名.dsw) 然后创建C+ Source File文件MyMFile0(系统 会自动添加文件扩展名.cpp),文件内容如下: int MyMax(int x, int y) return xy?x:y; 这是求最大值函数的定义部分。 再新建C/C+ Header File文件MyMFile(系统会 自动添加文件扩展名.h),文件内容如下: #include #include struct Person int id; char name10; ; int MyMax(int, int); int i=100; 再新建C+ Source File文件MyMFile1,文件内容如下: #include “MyMFile.h“ void main() Person ZS; ZS.id=i; strcpy(ZS.name,“张三“); printf(“ni= %d“, i); printf(“n%d %s“, ZS.id, ZS.name); int max; max=MyMax(2,20); printf(“nmax= %d“, max); putchar(n); 可能会有这样的情况: 某些全局类型、全局量值和函数只使用在某 几个特定文件中。 某些全局类型、全局量值和函数严格限定只 能使用在某一个特定文件中。 如在上面的例子中,如果MyMFile0.cpp文件的内容 是如下形式: static int MyMax(int x, int y) return xy?x:y; 这时,程序就会出错。 6.3名词性的类型和量值在各逻辑结构上的 时间域 通常:类型和量值的时间域和空间域是一致的。 特殊情况下:用关键字static对定义的变量和函 数做限定时,空间域和时间域不同。 6.3.1模块内static 模块内用static定义的量值(主要是变量)其空 间域仍然限定在该模块,但其时间域是整个工程 。 这种变量通常叫做“静态变量”。 例6. 8计算15的阶乘 #include int fac (int );/阶乘函数声明 void main() int i; for (i=1; i void main() extern int a;/对定义在本工程其它文件中全局变量 的声明 / extern int b; printf(“na= %d“, a); / printf(“nb= %d“, b); 6.3.3关于static的总结 6.4变量的物理存储位置 定义的变量通常情况下,无论是动态的还是静态 的,都是存储在ROM(随机只读存储器,内存) 中的。 在小型计算机或大型计算机中允许用关键字 register定义存储在CPU的寄存器中的变量 例6. 10寄存器变量的定义和使用 #include void main() register int i; for (i=0; i #define A 1 void main() /main函数模块开始 #define B 2 printf(“n A %d“, A); printf(“n B %d“, B); printf(“n C %d“, C); /error C2065: C : undeclared identifier /内嵌模块开始 #define C 4 printf(“n A %d“, A); printf(“n B %d“, B); printf(“n C %d“, C); #undef B printf(“n A %d“, A); printf(“n B %d“, B); /error C2065: B : undeclared identifier printf(“n C %d“, C); /内嵌模块结束 printf(“n A %d“, A); printf(“n B %d“, B); /error C2065: B : undeclared identifier printf(“n C %d“, C); /main函数模块结束 3.宏可以级联定义 例7. 2替换宏的级联定义和使用 #include #define LONG 5 #define AREA printf(“n AREA %d“, LONG*LONG);/宏定义包含已定义宏 void main() printf(“n LONG %d“, LONG); AREA 7.2复杂替换宏宏函数 前面讲解了简单替换的标识宏,宏还可以是更复 杂的参数形式,就象函数一样。宏函数定义的一 般形式为: #define 宏名(参数表) 字符串 例7. 3宏函数的定义和替换过程 #include #define PI 3.1415 #define CIRCLE(R) 2*PI*R /定义参数宏 CIRCLE,参数为R,宏体为2*PI*R void main() int a=5; float circle=CIRCLE(a); /调用参数宏 printf(“n %6.3fn“, circle); 上例中定义了带参数R的宏CIRCLE,宏体(宏的 实现部分)是2*PI*R。main函数内宏的替换过程 如下: 语句float circle=CIRCLE(a);中将宏名 CIRCLE替换为宏体,得到 float circle=2*23.14*R;。 宏的形式参数是R,宏的实际参数是a,将 形式参数替换成实际参数,得到 float circle=2*23.14*a; 例7. 4实际参数是表达式时宏函数的替换过程 #include #define PI 3.1415 #define CIRCLE(R) 2*PI*R void main() int a=5; float circle=CIRCLE(a+1); /宏函数的实际参数 是表达式 printf(“n %6.3fn“, circle); 下面的程序用一个宏起到两个函数的作用。 例7. 5宏的灵活使用 #include #define PI 3.1415 #define CIRCLE(R, ROUND, AREA) ROUND=2*PI*R; AREA=PI*R*R; void main() int a=5; float round, area; CIRCLE(a, round, area) printf(“n %6.3f %6.3fn“, round, area); 上面的程序中定义了宏CIRCLE,有三个形式参数 。宏体是两部分(复合的)。宏的替换过程如下 : 将main模块中的CIRCLE替换为 ROUND=2*3.1415*R; AREA=3.1415*R*R; 将宏的形式参数替换为实际参数。得到 round=2*3.1415*a; area=3.1415*a*a; 7.3批量的嵌入文件包含 图7. 1文件包含的作用 7.4条件编译 为了使C/C+开发的软件有功能强弱的多个版本 也可能为了使开发的软件可以方便地移植到不同 的运行环境中 更可能使前面学习的多个宏定义和文件包含具有 唯一性而不相互冲突 编译预处理中有条件编译指令。 7.4.1 #ifndef#else#endif 条件编译指令#ifndef#else#endif的一般形式: #ifndef 标识符 程序段1 #else 程序段2 #endif 作用:判断此前是否用#define定义过了“标识 符”,如果没有定义,编译程序段1,即最后的 可执行代码中只有程序段1;否则编译程序段2, 即最后的可执行代码中只有程序段2。 例7. 6 多文件工程中, #ifndef#else#endif条件编译指令的 使用 学生信息管理系统,实现信息输入、信息 输出、按学号排序、按姓名排序和按总成 绩排序。采用在一个工程中,多个源程序 和多个头文件的设计。 步骤如下: (1) 在VC中新建工程student。 (2) 新建头文件student.h。 文件内容如下: #ifndef STUDENT /注释掉第1行 / #if !defined (STUDENT) /该行代码和上一行是 等价的,有人喜欢这样使用 #define STUDENT /注释掉第2行 #include #include struct Student int id; char name20; int scores3; ; #define NUM 3 / /为了减少输入,假设有三名学生 void InPut(Student* , int); void OutPut(Student* , int); #endif/注释掉第3行 (3)新建源文件student.cpp内容如下 #include “student.h“ #include“SortId.h“ / #include “SortName.h“ / #include “SortScores.h“ void main() int FunId; Student stuNUM; InPut(stu, NUM); printf(“n请输入对应功能号,实现排序或退出: “); printf(“n 1:学号排序; 2:姓名排序;3:总成绩排 序;其它:退出“); scanf(“%d“, while (1) switch (FunId) case 1: SortId(stu, NUM); OutPut(stu, NUM); break; /*case 2:SortName(stu, NUM); OutPut(stu, NUM); break; case 3:SortScore(stu, NUM); OutPut(stu, NUM); break; */ default: break; printf(“nnn 1:学号排序; 2:姓名排序;3:总成 绩排序;其它:退出。n“); scanf(“%d“, if (FunId3) break; /break while (4)新建头文件SortId.h文件内容如下 #include “student.h“ void SortId(Student *stu, int num); (5)新建源文件SortId.cpp文件内容如下 #include “SortId.h“ void SortId(Student *stu, int num) int i, j, k; Student tem; for (i=0; istuj.id) k=j; tem=stuk; stuk=stui; stui=tem; (6)新建源文件studentLab.cpp,文件内容如下 #include “student.h“ void InPut(Student *stu, int n) int i, j; for (i=0; iid ); printf(“n请输入第%d个姓名: n“, i); getchar(); gets(); printf(“n请输入第%d个人三门成绩,回车结束: n“, i); for (j=0; jid, ); for (j=0; j #include /#define NDEBUG /该符号常量定义,一定要在 头文件包含#include 的前面 /解开该注释行,程序就不会终止 #include void main() int i; for (i=0; i #define HELLO(x) printf(“你好!“ #x “n“); void main() HELLO(张三) 图7. 5例7.8 运行结果 7.4.6数字链接# 预编译指令“#”可以象链接字符串一样链接数字。 例7. 9 数字链接预编译“#”的使用 #include 图7. 6 例7.9运行结果 #define CONNECT(x,y,z) x#y#z void main() int x=CONNECT(1,2,34); printf(“n%dn“, x); 在程序中定义的变量都是暂时存储在计算机的内 存中的,当程序执行完毕或计算机断电数据就不 存在了。 文件可以在磁盘上永久存储大量数据。 第8章 C/C+语言的纵向名词性扩充(3): 宏观扩充文件 8.1输入输出流和文件的指针 本质上,计算机语言程序不能真正操作文件。 只有操作系统可以操作文件。 C/C+程序对文件的操作是通过操作系统完成的 。 8.1.1输入输出流 在做文件读操作时,通常是将磁盘文件数据的一 部分(块),(这部分的大小由操作系统定)读 入内存。 8.1.2文件的指针 这个结构体类型定义在stdio.h文件中,且用 typedef定义为FILE类型。这样程序中就可以用 如下形式定义指向文件的指针变量 FILE * fp; 8.2文件的打开和关闭 8.2.1文件的物理形式 图8. 1数据的表示 8.2.2文件的打开 整个过程通过系统函数fopen()完成。 FILE *fp; fp=fopen(文件名字符串,文件打开方式字符串 ); 函数fopen()正确执行时返回地址,执行错误时 返回空指针NULL(NULL在stdio.h中被定义位0) 打开 方式 含 义 “r” “w” “a” “rb” “wb” “ab” “r+” “w+” “a+” “rb+” “wb+” “ab+” 以从文件中读的方式打开文本文件 以向文件中写的方式打开(新建)文本文件 以向文件尾追加数据的写方式打开文本文件 以从文件中读的方式打开二进制文件 以向文件中写的方式打开(新建)二进制文件 以向文件尾追加数据的写方式打开二进制文件 以既可从文件中读又可向文件中写的方式打开已经存在的文本文件 以既可从文件中读又可向文件中写的方式打开(新建)文本文件 以既可从文件中读又可向文件中追加数据的写方式打开已经存在的文本 文件 以既可从文件中读又可向文件中写的方式打开已经存在的二进制件 以既可从文件中读又可向文件中写的方式打开(新建)二进制文件 以既可从文件中读又可向文件中追加数据的写方式打开已经存在的二进 制文件 8.2.3文件的关闭 文件的关闭意味着缓冲区的清除和磁盘文件的更 新,当然文件指针不再指向记录文件信息的结构 体信息,该结构体所占内存释放。 fclose(文件指针变量); 如fclose(fp); 当fclose()正常关闭文件时,函数返回0;否则 返回EOF(1)。 8.3文件的顺序读写 文件的顺序读写是打开文件后,指向文件的开头 ,以后对文件的读写都是从文件的头顺序向后进 行的。 8.3.1向文件中顺序输出(写)字符 向文件中顺序写一个字符的函数是putc()或 fputc()。 两个函数的功能相同,都声明在stdio.h头文件 中。 两函数正确执行返回的是向文件中写的字符,执 行错误时返回字符常量EOF。 例8. 1创建文件,然后向文件中顺序写入字符 #include“stdio.h“ #include“stdlib.h“/*exit()的函数声明*/ void main() FILE *fp; /定义文件指针变量 char ch, filename10; printf(“n请输入要创建的文件名(*.dat): n“); scanf(“%s“, filename); if (fp=fopen(filename, “w“)=NULL) /*以写方式在当 前目录打开(新建)文件*/ printf(“cannot oen filen“); exit(0); /如果文件无法打开,关闭已经打开的其它文 件,结束程序。 getchar(); /“吃掉”上面结束scanf的回车,避免“ 回车”被后面getchar()接收。 printf(“n请输入文件内容,#结束:n“); ch=getchar(); while(ch!=#) /判断是否输入了“#” fputc(putc(ch, fp),stdout); /将写到磁盘文件 中 的字符, /写到标准输出文件(显示器) ch=getchar(); fclose(fp); /关闭文件 8.3.2从文件中顺序输入(读)字符 从文件中顺序读一个字符的函数是getc()或 fgetc()。 两个函数的功能相同,都声明在stdio.h头文件 中。 两函数正确执行返回的是从文件中读的字符,执 行错误时返回字符常量EOF。 例8. 2 读已经存在的文本文件,将文件内容输出到显示器 #include“stdio.h“ #include“stdlib.h“/*exit()的函数声明*/ void main() FILE *fp; /定义文件指针变量 char ch, filename10; printf(“n请输入要打开的文件名(*.dat): n“); scanf(“%s“, filename); if (fp=fopen(filename, “r“)=NULL) /*以读方式打开文 件*/ printf(“cannot oen filen“); exit(0); /如果文件无法打开,关闭已经打开的其它文 件,结束程序。 getchar(); /吃掉上面结束scanf的回车 printf(“n下面输出的是文件内容:n“); ch=getc(fp); /从文件中读一个字符 while(!feof(fp) /putc(ch,stdout);/ 将写到磁盘文件中的字符, 写到标准输出文件(显示器) putchar(ch); ch=fgetc(fp); /从文件中读字符 fclose(fp); /关闭文件 例8. 3 融合例8.1和例8.2,编写一个实现文件拷贝 的C程序。文件拷贝就是读一个已经存在的文件 ,然后写入另一个新创建文件,而不是写到标准 输出文件。 #include“stdio.h“ #include“stdlib.h“ void main() FILE *source, *object; /定义读文件和写文件指 针变量 char ch, sourcefile10, objectfile10; printf( “n请输入拷贝的源文件名:n“); scanf( “%s“, sourcefile); printf(“请输入拷贝的目标文件名:n“); scanf(“%s“, objectfile); if (source=fopen(sourcefile, “r“)=NULL) printf( “cannot open sourcefilen“); exit(0); if (object=fopen(objectfile, “w“)=NULL) printf( “cannot open objectfilen“); exit(0); while (!feof(source) putc(getc(source), object); /从源文件中读,写到目 标文件中 fclose(source); /关闭两个文件 fclose(object); 例8. 4 使用main()函数的参数,可以使文件复制程 序以命令形式运行,即在操作系统提示符下,输 入:命令名 源文件名 目标文件名,然后回车 。 创建工程MyCopy,新建源文件MyCopy.cpp,代 码如下: #include“stdio.h“ #include“stdlib.h“ void main(int argc, char *argv) FILE *source, *object; if (argc!=3) printf(“n命令参数个数错误!n“); exit(0); if (source=fopen (argv1, “r“)=NULL) printf(“ cannot open sourcefilen“); exit(0); if (object=fopen(argv2, “w“)=NULL) printf(“cannot open objectfilen“); exit(0); while (!feof(source) fputc(fgetc(source), object); fclose(source); fclose(object); 8.3.3文件的顺序多个数据读写 fread(buffer, size, count, fp); fwrite(buffer, size, count, fp); 例8. 5 学生信息的磁盘文件存储和读取。 #include #include /类型定义 typedef int Score2; typedef char Name10; struct Student int id; Name name; Score score; ; /函数声明 void InputStudent(Student * p); void OutputStudent(Student * p); void SaveStudent(Student * p, int n); void LoadStudent(Student * p, int n); /主函数开始 #define N 3 /为了输入简单,数组长度定义为3 void main() int j ,n ,id; Student studentsN; Student temN; while(1) printf(“n请输入功能编号,运行系统相应功 能n“); printf(“1输入信息;2文件存盘;3打开 文件输出;其它退出。n“); scanf(“%d“, switch (id) case 1: for (j=0; j3) break; /break while /输入函数 void InputStudent(Student * p) int i; printf(“n请输入整数编号,回车结束:“); scanf(“%d“, getchar(); printf(“n请输入姓名字符串,回车结束: “); gets(p-name); printf(“n请输入两门课的整数成绩,每门成绩以回车结 束:n“); for (i=0; iscorei); getchar(); /输出函数 void OutputStudent(Student *p) printf(“n%dt%st%dt%dn“, p-id, p-name, p-score0, p-score1); /写文件函数 void SaveStudent(Student * p, int n) FILE *fp; char filename20; int i; printf(“n请输入保存文件名:n“); gets(filename); if (fp=fopen(filename, “wb“)=NULL) /创建二进制文件 printf(“cannot open filen“); return; for (i=0; i #include void SaveStr(char * p); void LoadStr(char * p, int n); /主函数开始 void main() char str21; printf(“n请输入fputs的字符串( #include /类型定义 typedef int Score2; typedef char Name10; struct Student int id; Name name; Score score; ; /函数声明 void InputStudent(Student * p); void OutputStudent(Student * p); void SaveStudent(Student * p, int n); Student LoadStudent( int n); /主函数开始 #define N 3 void main() int j ,n ,id; Student studentsN; Student tem; /用来存放要输出的那个结构体信 息 while(1) printf(“n请输入功能编号,运行系统相应功 能n“); printf(“1输入信息;2文件存盘;3打开 文件输出;其它退出。n“); scanf(“%d“, switch (id) case 1: for (j=0; j3) break; /break while /输入函数 void InputStudent(Student * p) int i; printf(“n请输入整数编号,回车结束:“); scanf(“%d“, getchar(); printf(“n请输入姓名字符串,回车结束: “); get
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 汉字视觉联想反思课件
- 汉字甲课件教学课件
- 海南省省直辖县级行政单位琼海市2024-2025学年八年级下学期7月期末考试数学试卷(含答案)
- 2024-2025学年辽宁省鞍山市铁西区人教版四年级下册期末考试数学试卷(含答案)
- 汉字基本知识培训心得
- 房屋代持协议书4篇
- 通讯网络互联网行业前瞻报告
- 2025合同的订立与履行
- DB46-T 546-2021 非公路用旅游观光车安全管理与服务规范
- 2024年秋新北师大版数学一年级上册教学课件 第四单元 10以内数加与减 第11课时 做个加法表
- 2025小学道德与法治教师课标考试模拟试卷附参考答案 (三套)
- 中国卒中患者高血压管理专家共识(2024)解读
- 小艇行业跨境出海战略研究报告
- 三会一课培训内容
- GB/T 45309-2025企业采购物资分类编码指南
- 膜性肾病护理进展
- 销售过程管理培训课件
- 医院医保智能审核与规则解释
- 篮球裁判员手册
- 电焊工安全用电培训
- 安宁疗护服务规范
评论
0/150
提交评论