1 / 84

计算机实习

计算机实习. 第 1 讲. 教学任务. 作品 [ 申请成绩为优 ] 考核(结构体、文件、链表) 平时的实验 实习无补考 (2 次课堂教学 ,2 次实验 ,1 次考核 ). 3. 3. 复习数组. 1. 3. 文件的基本操作. 归纳与提高. 2. 4. 结构体数组. 目 录. 1 .数组的基本概念. 数组. #include &quot;stdio.h&quot; void f1(int a[],int n) { int i; for(i=0;i&lt;n;i++) { printf(&quot; 输入第 %d 个数据 <br>&quot;,i+1);

Download Presentation

计算机实习

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 计算机实习 第1讲

  2. 教学任务 • 作品[申请成绩为优] • 考核(结构体、文件、链表) • 平时的实验 • 实习无补考(2次课堂教学,2次实验,1次考核)

  3. 3 3 复习数组 1 3 文件的基本操作 归纳与提高 2 4 结构体数组 目 录

  4. 1.数组的基本概念 数组 #include "stdio.h" void f1(int a[],int n) { int i; for(i=0;i<n;i++) { printf("输入第%d个数据\n",i+1); scanf("%d",&a[i]);}} main() { int x,i,s[50]; printf("输入数组的元素个数\n"); scanf("%d",&x); f1(s,x); for(i=0;i<x;i++) printf("%3d",s[i]); printf("\n");getch(); } int a[100]; 例如:

  5. 利用随机数为数组元素赋值 产生 n1—n2之间的随机整数: (int)((rand()/32768.0)*(n2-n1+1)+n1);

  6. 利用随机数为数组元素赋值 #include <stdio.h> #include"stdlib.h" #include "time.h" #define N 100 void f1(int a[],int n1,int n2,int n) { int i; srand( (unsigned)time( NULL ) ); for (i=0; i<n;i++) {a[i] =(int)((rand()/32768.0)*(n2-n1+1)+n1); printf("%4d,",a[i]); }}

  7. 利用随机数为数组元素赋值 main() { int a[N]; f1(a,40,150,20); }

  8. 利用数据文件为数组元素赋值 建立数据文件: 通过excel建立数据文件,文件以文本文件形式保存 用程序读出文本文件中的数据 定义文件指针 FILE *fp; 打开文件fopen("cj.txt","r") 读文件fscanf(fp,"%d",&x[i]); 关闭文件fclose(fp);

  9. 利用数据文件为数组元素赋值 #include <stdio.h> #define SIZE 143 main() { int x[SIZE],i,max,min; FILE *fp; printf("Enter %d integers:\n",SIZE); if((fp=fopen("cj.txt","r"))==NULL) { printf("不能打开该文件,任意键退出"); getch(); exit(1); }

  10. 利用数据文件为数组元素赋值 for(i=0;i<SIZE;i++) fscanf(fp,"%d",&x[i]); fclose(fp); max=min=x[0]; for(i=1;i<SIZE;i++) { if(max<x[i]) max=x[i]; if(min>x[i]) min=x[i]; } printf("Maximum is %d\n",max); printf("Minimum is %d\n",min); }

  11. C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位

  12. 1文件分类 • 按文件的逻辑结构: • 记录文件:由具有一定结构的记录组成(定长和不定长) • 流式文件:由一个个字符(字节)数据顺序组成

  13. 按存储介质: • 普通文件:存储介质文件(磁盘、磁带等) • 设备文件:非存储介质(键盘、显示器、打印机等) • 按数据的组织形式: • 文本文件: ASCII文件,每个字节存放一个字符的ASCII码 • 二进制文件:数据按其在内存中的存储形式原样存放

  14. 如 int型数10000 ASCII形式 0011000100110000001100000011000000110000 0010011100010000 0010011100010000 内存存储形式 二进制形式 文件特点: 文本文件特点: 存储量大、速度慢、便于对字符操作 二进制文件特点: 存储量小、速度快、便于存放中间结果

  15. 缓冲文件系统: 程序 指令区 输入文件缓冲区 磁盘文件 用户数据区 磁盘 程序数据区 a 缓冲区 输出文件缓冲区 非缓冲文件系统: 文件处理方法 • 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区 • 非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区

  16. 2文件类型指针 • 文件结构体FILE • 缓冲文件系统为每个正使用的文件在内存开辟文件信息区 • 文件信息用系统定义的名为FILE的结构体描述 • FILE定义在stdio.h中 typedef struct { int _fd; //文件号 int _cleft; //缓冲区中剩下的字符数 int _mode; //文件操作方式 char *_next; //文件当前读写位置 char *_buff; //文件缓冲区位置 }FILE;

  17. 文件名 文件使用 方式 操作系统 C程序 文件类型指针 磁盘 文件类型指针 • 指针变量说明: FILE *fp; • 用法: • 文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件 • 文件关闭后,它的文件结构体被释放

  18. 含义 文件使用方式 “r/rb” (只读) 为输入打开一个文本/二进制文件 “w/wb” (只写) 为输出打开或建立一个文本/二进制文件 “a/ab” (追加) 向文本/二进制文件尾追加数据 “r+/rb+” (读写) 为读/写打开一个文本/二进制文件 “w+/wb+” (读写) 为读/写建立一个文本/二进制文件 “a+/ab+” (读写) 为读/写打开或建立一个文本/二进制文件 3文件的打开与关闭 例 文件打开与测试 FILE *fp; fp=fopen(“aa.c”,“w”); if(fp==NULL) { printf(“File open error!\n”); exit(0); } • C文件操作用库函数实现,包含在stdio.h • 文件使用方式:打开文件-->文件读/写-->关闭文件 • 系统自动打开和关闭三个标准文件: • 标准输入------键盘 stdin • 标准输出------显示器 stdout • 标准出错输出-----显示器 stderr • 打开文件fopen • 函数原型: FILE *fopen(char *name,char *mode) 例 FILE *fp; char *filename=“c:\\fengyi\\bkc\\test.dat” fp= fopen(filename,”r”); 例 FILE *fp; fp= fopen (“c:\\fengyi\\bkc\\test.dat”,”r”); 使用文件方式 • 功能:按指定方式打开文件 • 返值:正常打开,为指向文件结构体的指针;打开失败,为NULL 要打开的文件名

  19. 缓冲文件系统: 输入文件缓冲区 磁盘文件 程序数据区 a fclose 输出文件缓冲区 文件关闭fclose • 作用:使文件指针变量与文件“脱钩”,释放文件结构体和文件指针 • 函数原型:int fclose(FILE *fp) • 功能:关闭fp指向的文件 • 返值:正常关闭为0;出错时,非0 文件打开时返回的文件类型指针 不关闭文件可能会丢失数据

  20. 4文件的读写 • 字符I/O:fputc与fgetc • fputc • 函数原型:int fputc(int c, FILE *fp) • 功能:把一字节代码c写入fp指向的文件中 • 返值:正常,返回c;出错,为EOF • fgetc • 函数原型:int fgetc(FILE *fp) • 功能:从fp指向的文件中读取一字节代码 • 返值:正常,返回读到的代码值;读到文件尾或出错,为EOF 文件I/O与终端I/O #define putc(ch,fp) fputc(ch,fp) #define getc(fp) fgetc(fp) #define putchar( c ) fputc(c,stdout) #define getchar( ) fgetc(stdin)

  21. 从键盘输入字符,逐个存到磁盘文件中,直到 输入‘#“为止 #include <stdio.h> main() { FILE *fp; char ch,*filename=“out.txt”; if((fp=fopen(filename,"w"))==NULL) { printf("cannot open file\n"); exit(0); } printf("Please input string:"); ch=getchar(); while(ch!='#') { fputc(ch,fp); putchar(ch); ch=getchar(); } fclose(fp); } 例 修改程序使之在文件out.txt中保存一句完整的C语句

  22. 编写程序,从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,输出到磁盘文件“upper.txt”中保存。输入的字符串以“!”结束。同时将文件upper.txt中的内容显示在屏幕上。

  23. 数据块I/O: fread与fwrite size_t fread(void *buffer,size_t size, size_t count,FILE *fp) size_t fwrite(void *buffer,size_t size, size_t count,FILE *fp) • 函数原型: • 功能:读/写数据块 • 返值:成功,返回读/写的块数;出错或文件尾,返回0 • 说明: • typedef unsigned size_t; • buffer: 指向要输入/输出数据块的首地址的指针 • size: 每个要读/写的数据块的大小(字节数) • count: 要读/写的数据块的个数 • fp: 要读/写的文件指针 • fread与fwrite 一般用于二进制文件的输入/输出

  24. 例子 例 float f[2]; FILE *fp; fp=fopen(“aa.dat”,“rb”); fread(f,4,2,fp); for(i=0;i<2;i++) fread(&f[i],4,1,fp); 例 struct student { int num; char name[20]; char sex; int age; float score[3]; }stud[10]; for(i=0;i<10;i++) fread(&stud[i],sizeof(struct student),1,fp);

  25. 从键盘输入4个学生数据,把他们转存到磁盘文件中去 void save() { FILE *fp; int i; if((fp=fopen("d:\\fengyi\\exe\\stu_dat","wb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i<SIZE;i++) if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1) printf("file write error\n"); fclose(fp); } void display() { FILE *fp; int i; if((fp=fopen("d:\\fengyi\\exe\\stu_dat","rb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i<SIZE;i++) { fread(&stud[i],sizeof(struct student_type),1,fp); printf("%-10s %4d %4d %-15s\n",stud[i].name, stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); } #include <stdio.h> #define SIZE 4 struct student_type { char name[10]; int num; int age; char addr[15]; }stud[SIZE]; main() { int i; for(i=0;i<SIZE;i++) scanf("%s%d%d%s",stud[i].name,&stud[i].num, &stud[i].age,stud[i].addr); save(); display(); }

  26. #include <stdio.h> main() { char s[80],c[80]; int a,b; FILE *fp; if((fp=fopen("test","w"))==NULL) { puts("can't open file"); exit() ; } fscanf(stdin,"%s%d",s,&a);/*read from keaboard*/ fprintf(fp,"%s %d",s,a);/*write to file*/ fclose(fp); if((fp=fopen("test","r"))==NULL) { puts("can't open file"); exit(); } fscanf(fp,"%s%d",c,&b);/*read from file*/ fprintf(stdout,"%s %d",c,b);/*print to screen*/ fclose(fp); } int fprintf(FILE *fp,const char *format[,argument,…]) int fscanf(FILE *fp,const char *format[,address,…]) • 格式化I/O:fprintf与fscanf • 函数原型: • 功能:按格式对文件进行I/O操作 • 返值:成功,返回I/O的个数;出错或文件尾,返回EOF 例 fprintf(fp,“%d,%6.2f”,i,t); //将i和t按%d,%6.2f格式输出到fp文件 fscanf(fp,“%d,%f”,&i,&t); //若文件中有3,4.5 ,则将3送入i, 4.5送入t 例 从键盘按格式输入数据存到磁盘文件中去

  27. 字符串I/O: fgets与fputs #include<stdio.h> main() { FILE *fp; char string[81]; if((fp=fopen("file.txt","w"))==NULL) { printf("cann't open file");exit(0); } while(strlen(gets(string))>0) { fputs(string,fp); fputs("\n",fp); } fclose(fp); if((fp=fopen("file.txt","r"))==NULL) { printf("cann't open file");exit(0); } while(fgets(string,81,fp)!=NULL) fputs(string,stdout); fclose(fp); } • 函数原型: char *fgets(char *s,int n,FILE *fp) int fputs(char *s,FILE *fp) • 功能:从fp指向的文件读/写一个字符串 • 返值: • fgets正常时返回读取字符串的首地址;出错或文件尾,返回NULL • fputs正常时返回写入的最后一个字符;出错为EOF fputs把s指向的字符串写入fp指向的文件 fgets从fp所指文件读n-1个字符送入s指向的内存区, 并在最后加一个‘\0’ (若读入n-1个字符前遇换行符或文件尾(EOF)即结束) 例 从键盘读入字符串存入文件,再从文件读回显示

  28. 5文件的定位 • 几个概念 • 文件位置指针-----指向当前读写位置的指针 • 读写方式 • 顺序读写:位置指针按字节位置顺序移动,叫~ • 随机读写:位置指针按需要移动到任意位置,叫~ • rewind函数 • 函数原型: void rewind(FILE *fp) • 功能:重置文件位置指针到文件开头 • 返值:无 #include <stdio.h> main() { FILE *fp1,*fp2; fp1=fopen("d:\\fengyi\\bkc\\ch12_4.c","r"); fp2=fopen("d:\\fengyi\\bkc\\ch12_41.c","w"); while(!feof(fp1)) putchar(fgetc(fp1)); rewind(fp1); while(!feof(fp1)) fputc(fgetc(fp1),fp2); fclose(fp1); fclose(fp2); } 例 对一个磁盘文件进行显示和复制两次操作

  29. main() { int i; FILE *fp; if((fp=fopen("studat","rb"))==NULL) { printf("can't open file\n");exit(0); } for(i=0;i<3;i+=2) { fseek(fp,i*sizeof(struct student_type),0); fread(&stud[i],sizeof(struct student_type),1,fp); printf("%s %d %d %s\n", stud[i].name,stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); } #include <stdio.h> struct student_type { int num; char name[10]; int age; char addr[15]; }stud[3]; fseek函数 • 函数原型: int fseek(FILE *fp,long offset,int whence) • 功能:改变文件位置指针的位置 • 返值:成功,返回0;失败,返回非0值 起始点 文件开始SEEK_SET 0 文件当前位置SEEK_CUR 1 文件末尾SEEK_END 2 文件指针 位移量(以起始点为基点,移动的字节数) >0向后移动 <0向前移动 • ftell函数 • 函数原型: long ftell(FILE *fp) • 功能:返回位置指针当前位置(用相对文件开头的位移量表示) • 返值:成功,返回当前位置指针位置;失败,返回-1L, 例 fseek(fp,100L,0); fseek(fp,50L,1); fseek(fp,-10L,2); 例 磁盘文件上有3个学生数据,要求读入第1,3学生数据并显示

  30. 6 出错的检测 • ferror函数 • 函数原型: int ferror(FILE *fp) • 功能:测试文件是否出现错误 • 返值:未出错,0;出错,非0 • 说明 • 每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试 • fopen打开文件时,ferror函数初值自动置为0

  31. clearerr函数 #include <stdio.h> int main(void) { FILE *stream; stream = fopen("DUMMY.FIL", "w"); getc(stream); if (ferror(stream)) { printf("Error reading from DUMMY.FIL\n"); clearerr(stream); } if(!ferror(stream)) printf("Error indicator cleared!"); fclose(stream); return 0; } • 函数原型: void clearerr(FILE *fp) • 功能:使文件错误标志置为0 • 返值:无 • 说明:出错后,错误标志一直保留,直到对同一文件调clearerr(fp)或rewind或任何其它一个输入输出函数 例 ferror()与clearerr()举例

  32. proc1() {if((fp=fopen("book.txt","r"))==NULL) { printf("不能打开该文件,任意键退出"); getch(); exit(1); } }

  33. int proc2(BOOK a[]) { int i=0; while (!feof(fp)) { fscanf(fp,"%s %s %s %d %d %d %f",a[i].bno,a[i].bname,a[i].cbadd,&a[i].bcdate.day,&a[i].bcdate.month,&a[i].bcdate.year,&a[i].bprice); i++; } return i;fclose(fp); }

  34. 将名单存在文本文件中,利用程序访问该文本文件后,输出学生名单。将名单存在文本文件中,利用程序访问该文本文件后,输出学生名单。

  35. 问题 与实际系统不同 图书的信息包括:书号、书名、出版日期、出版地点、价格 数据的独立性

  36. 3 3.6 在程序中存入变量 int x=3;float y=3.6; {10,20,30,40} int a[10]={10,20,30,40} {" zhang" , 27 , " li " , 18 , " wang " , 73} ; struct man { char name[20] ; int age ; }; struct man person [N] ={ " zhang" , 27 , " li " , 18 , " wang " , 73} ;

  37. Name age sex address wang 20 F 10#222 Zhang 19 M 16#321 Liu 18 M 16#324 zhao 20 F 10#242 问题 例:处理50个学生的信息,将学号、姓名、年龄按成绩排序 • 解决方法: • 数组:相同类型数据的集合,将学号、姓名、年龄、成绩分别定义为不同的数组,相同的下标表示同一个学生的不同信息 • 结构体:不同类型数据的集合,将不同类型的数据作为结构体的分量,定义一个结构体数组 • 结构体:自定义数据类型

  38. 结构体 一、自定义类型声明 1、注意类型名与变量名的区别: 类型定义只规定在使用此结构体时应分配的内存, 对类型名本身并不分配内存,更不能赋值、存取、运算,定义结构体变量时才分配内存 结构体类型声明: struct结构体类型名 { 数据类型1 成员名1; …… 成员表列 数据类型n 成员名n;}; (1)学生信息结构体声明: struct student { int num; char name[20]; char sex; float score; }; 2、各“成员”也可称为“结构体分量”或“域”,用“;”分隔。成员数据类型可以是各种基本类型或构造类型(包括结构体类型),成员名可以与程序中的变量名相同。 3.声明时最后的右括号后要加分号

  39. 结构体 (2)为了处理通讯录,可以定义如下结构: struct address { char name[30]; /* 字符数组作为结构中的成员 */ char street[40]; /* 街道名称 */ char city[20]; /* 城市 */ char state[2]; /* 省市代码 */ unsigned long zip; /* 邮政编码,无符号长整型*/ }; struct person {char name[8]; /*姓名*/ char sex; /*性别*/ int age; /*年龄*/ float height , weight; /*身高、体重*/ char add[40]; /*住址*/ }; (3) 个人数据,包含姓名、性别、年龄、身高、体重、住址:

  40. (5) 日期, 包括年、 月、 日: struct date {int year; /*年*/ int month; /*月*/ int day; /*日*/ }; 如考虑时间, 可作如下定义: struct time {int hh; /*时*/ int mm; /*分*/ int ss; /*秒*/ }; (4) 平面上的点: struct point2 {float x; /*横坐标*/ float y; /*纵坐标*/ }; 空间中的点: struct point3 {float x; /*X坐标*/ float y; /*Y坐标*/ float z; /*Z坐标*/ };

  41. (6) 复数: struct complex { float re; /*实部*/ float ie; /*虚部*/ }; (7) 三角形: struct sjx { float a, b, c; /*三边*/ };

  42. 结构体 声明的一般形式: struct 结构体名 { 成员表列 }变量名列表; 二.变量定义 用已声明的类型定义变量 1、先声明后定义 struct student s1, s2; student:类型名称 s1, s2:变量名 2、声明类型同时定义 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }s1, s2; 3、直接定义结构类型变量 struct {成员列表 }变量名列表; struct { int num; char name[20]; int age; float score; }s1, s2; 无类型名

  43. Name age sex address wang 20 F 10#222 Zhang 19 M 16#321 Liu 18 M 16#324 zhao 20 F 10#242 结构体 表头 结构体成员(类型,名) 结构体变量 表中的内容

  44. 例如,对以上定义的结构体类型,我们可以定义如下一些结构体变量:例如,对以上定义的结构体类型,我们可以定义如下一些结构体变量: struct student zhang; /*张同学情况*/ struct person p[100]; /*100个人的数据*/ struct point2 p1, p2; /*平面上的两个点*/ struct point3 po1, po2; /*空间上的两个点*/

  45. s1 num name age score 结构体 说明: (1)一旦定义了结构体变量后,则变量和其它变量一样,系统将分配其相应的存储空间. 存储空间:各个成员所占的存储单元的总和 (2)与标准类型变量不同:结构体变量的定义要有关键字struct,和结构体类型名。

  46. 结构体 3.为使用方便,可将对结构体类型的声明放入一文件中,在使用时用#include将其所在文件包入。还可定义一符号常量来代表一结构体类型。 #define STUDENT struct student STUDENT { int num; char name[20]; int age; float score; }; STUDENT s1, s2;

  47. 结构体 三、结构体类型变量的引用 • 引用格式:结构体变量名.成员名 “.”:成员运算符 如:s1.num=10001; 1.一般不将结构体作为一个整体进行操作,应对结构体变量中各成员分别实现各种操作和运算。由于结构体变量是一整体,要访问其中一个成员,必须先找到变量,通过成员运算符,从中找出某成员。 2.可嵌套定义。若成员本身又是结构体,则要用多个成员运算符一级级找到最低一级的成员,才能进行操作

  48. 结构体 例如: (1) struct student类型变量zhang, 其所有分量如下: zhang.no,zhang.name,zhang.sex,zhang.age, (2) struct point2类型变量p1, 其所有分量如下: p1.x, p1.y (3)嵌套的结构体类型和变量: struct data { int month; int day; int year; }; struct stud { int num; char name[20]; struct data birthday; }stud1; stud1.birthday.day=12;

  49. 结构体 3.对结构体变量可像普通变量一样进行各种运算,但应遵循各成员数据类型的运算规则。如: s1.age=s2.age; ++s1.age; 4.可将一结构体变量作为一个整体赋给另一同类型的结构体变量。不可将一组常量直接赋给结构体变量。如: s1=s2; s1={20102,“Li Hao”,20,10};

  50. 结构体 5.结构体变量的I/O同样要求对变量的各成员项来进行。 可引用结构体变量成员的地址,也可引用结构体变量的地址。如: scanf(“%d”,&s1.num); 6.成员名与变量名或其他变量同名,互不干扰:不同级,引用方式不同

More Related