84
第1第

计算机实习

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: 计算机实习

第 1 讲

Page 2: 计算机实习

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

考核 )

Page 3: 计算机实习

文件的基本操作2

复习数组31

结构体数组33

归纳与提高4

Page 4: 计算机实习

数组数组1 .数组的基本概念

int a[100];

#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();}

例如:

Page 5: 计算机实习

利用随机数为数组元素赋值利用随机数为数组元素赋值产生 n1—n2 之间的随机整数 :

(int)((rand()/32768.0)*(n2-n1+1)+n1);

Page 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]); }}

Page 7: 计算机实习

利用随机数为数组元素赋值利用随机数为数组元素赋值main()

{

int a[N];

f1(a,40,150,20);

}

Page 8: 计算机实习

利用数据文件为数组元素赋值利用数据文件为数组元素赋值建立数据文件 : 通过 excel 建立数据文件 , 文件以文本文件

形式保存用程序读出文本文件中的数据 定义文件指针 FILE *fp; 打开文件 fopen("cj.txt","r") 读文件 fscanf(fp,"%d",&x[i]); 关闭文件 fclose(fp);

Page 9: 计算机实习

利用数据文件为数组元素赋值利用数据文件为数组元素赋值

#include <stdio.h>#define SIZE 143main(){ 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);

}

Page 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);}

Page 11: 计算机实习

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

Page 12: 计算机实习

按文件的逻辑结构: 记录文件:由具有一定结构的记录组

成(定长和不定长) 流式文件:由一个个字符(字节)数

据顺序组成

Page 13: 计算机实习

按存储介质: 普通文件:存储介质文件(磁盘、磁带等) 设备文件:非存储介质(键盘、显示器、打印

机等) 按数据的组织形式:

文本文件: ASCII 文件,每个字节存放一个字符的 ASCII 码

二进制文件:数据按其在内存中的存储形式原样存放

Page 14: 计算机实习

如 int 型数 10000

0010011100010000

内存存储形式0010011100010000

二进制形式

0011000100110000001100000011000000110000

ASCII 形式

文本文件特点 :存储量大、速度慢、便于对字符操作

二进制文件特点 :存储量小、速度快、便于存放中间结果

Page 15: 计算机实习

缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区

非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区

磁盘文件

输出文件缓冲区

输入文件缓冲区

程序数据区a

缓冲文件系统:

缓冲区

指令区

程序

用户数据区磁盘

非缓冲文件系统:

Page 16: 计算机实习

文件结构体 FILE 缓冲文件系统为每个正使用的文件在内存开辟文件

信息区 文件信息用系统定义的名为 FILE 的结构体描述 FILE 定义在 stdio.h 中

typedef struct{ int _fd; // 文件号 int _cleft; // 缓冲区中剩下的字符数 int _mode; // 文件操作方式 char *_next; // 文件当前读写位置 char *_buff; // 文件缓冲区位置}FILE;

Page 17: 计算机实习

指针变量说明: FILE *fp; 用法:

文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息 , 访问文件

文件关闭后,它的文件结构体被释放

文件名文件使用

方式

文件类型指针

C 程序 操作系统

磁盘

Page 18: 计算机实习

C 文件操作用库函数实现 , 包含在 stdio.h 文件使用方式 : 打开文件 --> 文件读 /写 --> 关闭文

件 系统自动打开和关闭三个标准文件:

标准输入 ------ 键盘 stdin 标准输出 ------ 显示器 stdout 标准出错输出 ----- 显示器 stderr

打开文件 fopen 函数原型: FILE *fopen(char *name,char *mode)功能:按指定方式打开文件

返值:正常打开,为指向文件结构体的指针;打开失败,为 NULL

要打开的文件名

使用文件方式

例 文件打开与测试 FILE *fp; fp=fopen(“aa.c”,“w”); if(fp==NULL) { printf(“File open error!\n”); exit(0); }

例 FILE *fp; fp= fopen (“c:\\fengyi\\bkc\\test.dat”,”r”);

例 FILE *fp; char *filename=“c:\\fengyi\\bkc\\test.dat” fp= fopen(filename,”r”);

“r+/rb+” ( 读写 )

“a/ab” ( 追加 )

“w/wb” ( 只写 )

“r/rb” ( 只读 )

“w+/wb+” ( 读写 )

“a+/ab+” ( 读写 )

为输入打开一个文本 / 二进制文件

为输出打开或建立一个文本 / 二进制文件

为读 / 写打开一个文本 / 二进制文件

为读 / 写建立一个文本 / 二进制文件

为读 / 写打开或建立一个文本 / 二进制文件

向文本 / 二进制文件尾追加数据

文件使用方式 含义

Page 19: 计算机实习

作用 : 使文件指针变量与文件“脱钩”,释放文件结构体和文件指针

函数原型: int fclose(FILE *fp)功能:关闭 fp 指向的文件返值:正常关闭为 0; 出错时 ,非 0文件打开时返回的文件类型指针

磁盘文件

输出文件缓冲区

输入文件缓冲区

程序数据区a

缓冲文件系统:

fclose

不关闭文件可能会丢失数据

Page 20: 计算机实习

字符 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)

Page 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);}

Page 22: 计算机实习

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

Page 23: 计算机实习

函数原型: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 一般用于二进制文件的输入 / 输出

Page 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);

Page 25: 计算机实习

#include <stdio.h>#define SIZE 4struct 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();}

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);}

Page 26: 计算机实习

格式化 I/O:fprintf与 fscanf 函数原型:int fprintf(FILE *fp,const char *format[,argument,…])int fscanf(FILE *fp,const char *format[,address,…])

功能:按格式对文件进行 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

例 从键盘按格式输入数据存到磁盘文件中去

#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);}

Page 27: 计算机实习

函数原型: char *fgets(char *s,int n,FILE *fp) int fputs(char *s,FILE *fp)

功能:从 fp 指向的文件读 / 写一个字符串返值:

fgets 正常时返回读取字符串的首地址;出错或文件尾,返回 NULLfputs 正常时返回写入的最后一个字符;出错为 EOF

例 从键盘读入字符串存入文件,再从文件读回显示

fgets从 fp所指文件读 n-1个字符送入 s 指向的内存区 ,并在最后加一个‘ \0’( 若读入 n-1个字符前遇换行符或文件尾( EOF)即结束 )

fputs把 s 指向的字符串写入 fp指向的文件

#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);}

Page 28: 计算机实习

几个概念 文件位置指针 ----- 指向当前读写位置的指针 读写方式

顺序读写:位置指针按字节位置顺序移动,叫~ 随机读写:位置指针按需要移动到任意位置,叫~

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);}

Page 29: 计算机实习

函数原型: int fseek(FILE *fp,long offset,int whence)

功能:改变文件位置指针的位置 返值:成功,返回 0 ;失败,返回非 0 值

文件指针位移量(以起始点为基点 , 移动的字节数 )>0 向后移动<0 向前移动

起始点文件开始 SEEK_SET 0文件当前位置 SEEK_CUR 1文件末尾 SEEK_END 2

例 fseek(fp,100L,0); fseek(fp,50L,1); fseek(fp,-10L,2);

ftell 函数函数原型: long ftell(FILE *fp)功能:返回位置指针当前位置 ( 用相对文件开头的位移量表示 )返值:成功,返回当前位置指针位置;失败,返回 -1L ,

例 磁盘文件上有 3 个学生数据,要求读入第 1, 3 学生数据并显示

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];

Page 30: 计算机实习

ferror 函数 函数原型: int ferror(FILE *fp) 功能:测试文件是否出现错误 返值:未出错, 0 ;出错,非 0 说明

每次调用文件输入输出函数,均产生一个新的 ferror 函数值,所以应及时测试

fopen 打开文件时, ferror 函数初值自动置为 0

Page 31: 计算机实习

函数原型: void clearerr(FILE *fp) 功能:使文件错误标志置为 0 返值:无 说明:出错后,错误标志一直保留,直到对同一

文件调 clearerr(fp)或 rewind 或任何其它一个输入输出函数

例 ferror()与 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;}

Page 32: 计算机实习

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

Page 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);

}

Page 34: 计算机实习

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

Page 35: 计算机实习

与实际系统不同 图书的信息包括:书号、书名、出版日期、

出版地点、价格数据的独立性

Page 36: 计算机实习

33.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} ;

Page 37: 计算机实习

例:处理 50 个学生的信息,将学号、姓名、年龄按成绩排序 Name age sex address

wang 20 F 10#222Zhang 19 M 16#321Liu 18 M 16#324zhao 20 F 10#242

解决方法:解决方法:•数组:相同类型数据的集合,将学号、姓名、年龄、成绩分别定义为不同的数组,相同的下标表示同一个学生的不同信息•结构体:不同类型数据的集合,将不同类型的数据作为结构体的分量,定义一个结构体数组结构体:自定义数据自定义数据类型类型

Page 38: 计算机实习

结构体类型声明:structstruct 结构体类型名 { 数据类型 1 成员名 1; …… 成员表列 数据类型 n 成员名 n;};(1) 学生信息结构体声明: struct student { int num; char name[20]; char sex; float score; };

1 、注意类型名与变量名的区别:类型定义只规定在使用此结构体时应分配的内存 , 对类型名本身并不分配内存,更不能赋值、存取、运算,定义结构体变量时才分配内存2 “ ” “、各 成员 也可称为 结构体分

” “ ”量 或 域 , 用“ ;” 分隔。成员数据类型可以是各种基本类型或构造类型 (包括结构体类型 ),成员名可以与程序中的变量名相同。

一、自定义类型声明一、自定义类型声明

3. 声明时最后的右括号后要加分号

Page 39: 计算机实习

(2) 为了处理通讯录,可以定义如下结构:struct address{ char name[30]; /* 字符数组作为结构中的成员

*/ char street[40]; /* 街道名称 */ char city[20]; /* 城市 */ char state[2]; /* 省市代码 */ unsigned long zip; /* 邮政编码 , 无符号长整型 */ };(3) 个人数据,包含姓名、性别、年龄、身高、体重、住址 :

struct person{char name[8]; /* 姓名 */ char sex; /* 性别 */ int age; /* 年龄 */ float height , weight; /* 身高、体重*/char add[40]; /* 住址 */};

Page 40: 计算机实习

(4) 平面上的点 : struct point2{float x; /* 横坐标 */float y; /* 纵坐标 */};空间中的点:struct point3{float x; /*X 坐标 */float y; /*Y 坐标 */float z; /*Z 坐标 */};

(5) 日期, 包括年、 月、 日 :struct date{int year; /* 年 */int month; /* 月 */int day; /* 日 */};如考虑时间, 可作如下定义: struct time{int hh; /* 时 */int mm; /* 分 */int ss; /* 秒 */};

Page 41: 计算机实习

(6) 复数 :struct complex{ float re; /* 实部 */ float ie; /* 虚部 */};

(7) 三角形 :struct sjx{ float a , b , c; /* 三边 */};

Page 42: 计算机实习

二二 .. 变量定义变量定义用已声明的类型定义变量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;

声明的一般形式: struct 结构体名 { 成员表列 }变量名列表 ;

3、直接定义结构类型变量struct {成员列表 }变量名列表 ;struct { int num; char

name[20]; int age;

float score;}s1, s2;无类型名

Page 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

结构体成员 ( 类型 ,名 )

结构体变量

表头

表中的内容

Page 44: 计算机实习

例如,对以上定义的结构体类型,我们可以定义如下一些结构体变量:

struct student zhang; /*张同学情况 */ struct person p[100]; /*100 个人的数据 */ struct point2 p1 , p2; /* 平面上的两个点 */ struct point3 po1 , po2; /*空间上的两个点

*/

Page 45: 计算机实习

说明:(1)一旦定义了结构体变量后,则变量和其它变量一样,系统将分配其相应的存储空间 .

存储空间:各个成员所占的存储单元的总和s1

num name age score

(2)与标准类型变量不同:结构体变量的定义要有关键字 struct ,和结构体类型名。

Page 46: 计算机实习

3.为使用方便,可将对结构体类型的声明放入一文件中 ,在使用时用#include将其所在文件包入。还可定义一符号常量来代表一结构体类型。

#define STUDENT struct studentSTUDENT{ int num;

char name[20];int age;float score;

};STUDENT s1, s2;

Page 47: 计算机实习

三、结构体类型变量的引用 引用格式:结构体变量名 .成员名“ .”:成员运算符如: s1.num=10001;1.一般不将结构体作为一个整体进行操作,应对结构体变量中各成员分别实现各种操作和运算。由于结构体变量是一整体,要访问其中一个成员,必须先找到变量,通过成员运算符,从中找出某成员。

2.可嵌套定义。若成员本身又是结构体,则要用多个成员运算符一级级找到最低一级的成员,才能进行操作

Page 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;

Page 49: 计算机实习

3.对结构体变量可像普通变量一样进行各种运算,但应遵循各成员数据类型的运算规则。如 : s1.age=s2.age;

++s1.age;4.可将一结构体变量作为一个整体赋给另一同类型的结构体变量。不可将一组常量直接赋给结构体变量。如:

s1=s2;s1={20102,“Li Hao”,20,10};

Page 50: 计算机实习

5.结构体变量的 I/O同样要求对变量的各成员项来进行。可引用结构体变量成员的地址,也可引用结构体变量的地址。如:

scanf(“%d”,&s1.num);6. 成员名与变量名或其他变量同名,互不干扰:不同级,引用方式不同

Page 51: 计算机实习

四、四、结构体类型变量的结构体类型变量的初始化初始化在给结构体类型变量说明的同时,可以同时给其各成员赋初值,称为结构体类型变量的初始化。如:

struct student{ long int num;

char name[20];char sex;char addr[30];

}a={89031,“li lin”,’m’,“123 beijing road”};不完全初始化,则其余成员自动初始化为 0 或‘ \0’ 无初始化,则不会自动初始化为 0 或‘ \0’

Page 52: 计算机实习

说明: 1.初始化时对结构体变量赋初值,而不是对类型中各成员赋初值。如:

struct student{ long int num=89031;

char name[20]= “li lin”;char sex=’m’;char addr[30]= “123 beijing road”;

}student1;

Page 53: 计算机实习

struct data { int month; int day; int year; }; struct stud{ long int num; char name[20];

char sex;struct data birthday;;char addr[30];

}stud1={89031,“lilin”,’m’,3,28,1988,“beijing road”};

2 、若在一个结构体类型内又嵌套另一结构体类型,对该结构体变量进行初始化时,仍按顺序写出各个初始值。

Page 54: 计算机实习

例 求平面上两点之间的距离。 main(){ struct point { float x; float y; }p1, p2; float d; printf(" 请输入第一点的坐标 : "); scanf("%f, %f", &p1.x, &p1.y); printf(" 请输入第二点的坐标 : "); scanf("%f, %f", &p2.x, &p2.y); d=sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)); printf(" 两点之间的距离 =%8.3f", d); }

Page 55: 计算机实习

五、五、结构体结构体数组数组 数组的每个元素皆为结构体类型变量1.定义:先定义结构体类型 ,后说明数组 (三种形式 )struct student{ int num;

char name[20];float score;char addr[30];

} ;struct student stu[3]; 每个元素占 56 个字节 (设整型变量占内存 2 个字节 )

Page 56: 计算机实习

2.初始化:变量定义的同时进行初始化,可在相应的三个位置进行初始化

struct student { int num; char name[20]; char sex; char addr[30]; }a[3]= {{89031,“lilin”,’m’,“123 beijing road”}, {89032,“zhangmin”,’f’,“123 beijing

road”}, {89033,“he li”,’m’,“123 beijing road”}};分别对数组的各成员进行初始化

Page 57: 计算机实习

3 、引用对结构体数组元素成员的引用形式为:结构体数组名 [下标 ].. 结构成员例 选票统计 对侯选人得票进行统计。有三个候选人,每次输入一个后选人的名字 , 要求最后输出各人得票结果。

#include <string.h>struct person{ char name[20]; int count;} leader[3]={“li”,0,”zhang”,0,”fun”,0};

定义一个全局结构体类型数组

Page 58: 计算机实习

main(){ int i,j; char leader_name[20]; for (i=1;i<=10;i++) { scanf(“%s”,leader_name); for (j=0;j<3;j++)if(strcmp(leader_name,leader[j].name)==0

) leader[j].count++; } for (i=0;i<3;i++) { printf(“%5s:”,leader[i]. name); printf(“%d\n”,,leader[i].count); } }

Page 59: 计算机实习

六六 .. 用结构体变量和指针函数参数用结构体变量和指针函数参数(1) 用结构体变量的成员作函数 (同数组元素作参数 )

——值传递方式(2) ——用结构体变量作参数 值传递 方式。例:有 4个学生,每个学生包括学号、姓名、成绩。要求在main()在函数中赋以值,在另一函数 print中将它们打印输出。

#define FORMAT “%d\n%s\n%f\n%f\n%f\n”struct student{ int num; char name[20]; float score[3]; };

Page 60: 计算机实习

main(){ void print(struct student); struct student stu; stu.num=12345; strcpy(stu.nam,”li lin”); stu.score[0]=67.5; stu.score[1]=89; stu.score[2]=78.6; print(stu); }void print(struct student stu){ printf(FORMAT,stu.num,stu.name, stu.score[0], stu.acore[1],stu.score[2]);}

Page 61: 计算机实习

(3)返回值为结构体类型的函数struct 结构体类型名 函数名 () { ……; return(结构体变量名 );}

Page 62: 计算机实习

#include "string.h"#include "stdio.h"#define BOOK struct bookBOOK{

char bno[10];char bname[50];struct date{

int day;int month;int year;

}bcdate;char cbadd[40];float bprice;

};

Page 63: 计算机实习

void welcome(){ printf("\n\t\t\

t*****************************\n"); printf("\t\t\t* *\n"); printf("\t\t\t* 欢迎图书管理系统 *\

n"); printf("\t\t\t* *\n"); printf("\t\t\

t*****************************\n");}

Page 64: 计算机实习

void mainmenu(){ printf("\n\n\n"); printf("\t\t\t*******************************\n");

printf("\t\t\t* 1.---- 输入 *\n"); printf("\t\t\t* 2.----排序 *\n"); printf("\t\t\t* 3.---- 退出系统 *\n"); printf("\t\t\t*******************************\n"); }

Page 65: 计算机实习

void f1(BOOK a[],int n){

int i,b1,b2,b3;float x;printf(" 输入功能 \n");for(i=0;i<n;i++){ printf(" 输入 %d 本书的信息 \n",i+1); printf("书号:书名 出版地: \n");scanf("%s",a[i].bno);puts(a[i].bno);getch();

scanf("%s",a[i].bname);puts(a[i].bname);getch();scanf("%s",a[i].cbadd);puts(a[i].cbadd);getch(); printf("\n 出版日期: "); scanf("%d%d%d",&b1,&b2,&b3);a[i].bcdate.day=b1;a[i].bcdate.month=b2; a[i].bcdate.year=b3; printf("\n书价: "); scanf("%f",&x); a[i].bprice=x; }

}

Page 66: 计算机实习

void f2(BOOK a[],int n){ int i,j;BOOK temp; printf("排序功能 \n"); for(i=0;i<n-1;i++) for(j=1;j<n-i;j++) if(strcmp(a[j-1].bno,a[j].bno)>0) {strcpy(temp.bno,a[j-1].bno);strcpy(temp.bname,a[j-

1].bname);strcpy(temp.cbadd,a[j-1].cbadd); strcpy(a[j-1].bno,a[j].bno);strcpy(a[j-1].bname,a[j].bname);strcpy(a[j-1].cbadd,a[j].cbadd);

strcpy(a[j].bno,temp.bno);strcpy(a[j].bname,temp.bname);strcpy(a[j].cbadd,temp.cbadd);

temp.bcdate.month=a[j-1].bcdate.month; temp.bcdate.day=a[j-1].bcdate.day;

temp.bcdate.year=a[j-1].bcdate.year; a[j-1].bcdate.month=a[j].bcdate.month; a[j-1].bcdate.day=a[j].bcdate.day;

a[j-1].bcdate.year=a[j].bcdate.year; a[j].bcdate.month=temp.bcdate.month; a[j].bcdate.day=temp.bcdate.day;

a[j].bcdate.year=temp.bcdate.year; temp.bprice=a[j-1].bprice; a[j-1].bprice=a[j].bprice;

a[j].bprice=temp.bprice; }}

Page 67: 计算机实习

void f3(BOOK a[],int n){ int i; printf("书号 书名 出版地 出版日期 价格 \n");

for(i=0;i<n;i++){printf("%s %s %s ",a[i].bno,a[i].bname,a[i].cbadd); printf("%d-%d-%d %f\n",a[i].bcdate.day,a[i].bcdate.month,a[i].bcdate.year,a[i].bprice);}

getch();

}

Page 68: 计算机实习

void f3(BOOK a[],int n){ int i; printf("书号 书名 出版地 出版日期 价格 \n");

for(i=0;i<n;i++){printf("%s %s %s ",a[i].bno,a[i].bname,a[i].cbadd); printf("%d-%d-%d %f\n",a[i].bcdate.day,a[i].bcdate.month,a[i].bcdate.year,a[i].bprice);}

getch();

}

Page 69: 计算机实习

void sele(BOOK a[],int n){

int k,m;char x[30];while(1){system("cls");welcome();getch();system("cls");

mainmenu();scanf("%d",&k);while((k>4||k<1))

{system("cls");mainmenu();scanf("%d",&k);}switch(k)

{case 1: printf(" 输入图书数 \n"); scanf("%d",&m); f1(a,m);f3(a,m); break;case 2:

f2(a,m);printf("排序后的图书列表 \n");f3(a,m);break;case 3:printf("谢谢使用,再见 \n");exit(0);

}}}

Page 70: 计算机实习

main(){

BOOK s[20];sele(s,20);

}

Page 71: 计算机实习

(1)union data { int i; char ch; float f; }a,b,c;(2) union data { int i; char ch; float f; }; union a,b,c;(3)union { int i; char ch; float f; }a,b,c;

Page 72: 计算机实习

2. 存储 :内存长度等于最长的成员长度二、引用“ ”先定义,后使用 变量名 .成员名“ .”:成员运算符 a.i , a.ch注意:1) 不能整体引用:因共用体各成员占共同的内存区域,某一时刻其所占的内存单元内只能保留某成员项的数据,所以对共用体变量的引用只能引用共用体变量中的某个成员。

Page 73: 计算机实习

2)某一时刻只有一个共用体成员有效,且是最后一次存放的成员有效。例: union data { int i; char c; float f; }a;main(){ a.i=3; a.c=’A’; a.f=32; printf(“a.i=%d,a.c=%c,a.f=%f\

n”,a.i,a.c,a.f);}输出结果: a.i=0,a.c= ,a.f=32.0000

Page 74: 计算机实习

3.共用体变量的地址值等于各成员地址值例: union data { int i; char c; float f; }; main() { union data a; printf(“&a=%d,&a.i=%d,&a.c=%d,&a.f=%d”,

&a,&a.i,&a.c,&a.f); }值相同,但类型不同

Page 75: 计算机实习

4.共用体变量不可在定义时初始化。5.共用体变量名不可赋值,或作函数参数,但可使用共用体数组。

Page 76: 计算机实习

例 设有若干教师的数据,包含有教师编号、姓名、职称,若职称为讲师,则描述他们的所讲课程,若职称为教授,则描述他们所写论文数目。

/* 输入输出教师信息 */union cf {char clname[30]; /* 所讲课程 */int num; /* 论文数目 */}; struct teachers{int no; /* 编号 */ char name[12]; /* 姓名 */ char zc; /* 职称 */ union cf x; /* 可变字段, 为所讲课程或论文数目 */} teach[3];

Page 77: 计算机实习

main( ){ int i; for(i=0; i<3; i++) { scanf("%d, %s,%c ", &teach[i].no,teach[i].name, &teach[i].zc); if (teach[i].zc= ='L')/*L 表示讲师 */ scanf("%s" , &teach[i].x .clname); else if (teach[i].zc= ='P' )/*P 表示教授 */ scanf ("%d" , &teach[i].x .num); else printf ("input data error\n"); }for(i=0; i<3; i++) {printf ("%d %s %c ", teach[i].no, teach[i].name,teach[i].zc);

Page 78: 计算机实习

if (teach[i].zc= ='L')printf ("%s\n" , teach[i].x.. clname); else if 'teach[i].name= ='P')printf ("%d\n", teach[i].x. num); else printf("data error\n"); }}

Page 79: 计算机实习

1. 下列关于结构体的说法错误的是 。

结构体是由用户自定义的一种结构类型;A

结构体中可设定若干个不同数据类型的成员B

结构体中成员的数据类型可以是另一个已定义的结构C

在定义结构时,可以为成员设置默认值D

课堂练习课堂练习课堂练习课堂练习

Page 80: 计算机实习

2. 下列程序中 , 结构体变量 a 所占内存字节数是 。union u{char st[4] ;int i;long l;};struct A{int c;union u;}a;A.4 B.5 C.6 D.8

课堂练习课堂练习

Page 81: 计算机实习

3. 3. 已知 已知 struct fsstruct fs { int fz; int fm; } x[ ]={{2,7}, {4,9}};{ int fz; int fm; } x[ ]={{2,7}, {4,9}};计算表达式:计算表达式:

x[0].fz*x[1].fm+x[1].fz*x[0].fmx[0].fz*x[1].fm+x[1].fz*x[0].fm 和和 x[0].fm*x[1].fmx[0].fm*x[1].fm 的值。的值。4. 4. 设设 struct student struct student {int num;char name[20];}st;{int num;char name[20];}st; 写出写出 printfprintf 语句:输出学生语句:输出学生 stst 的各个成员分量。要求按的各个成员分量。要求按 numnum、、

namename 的顺序输出,各成员之间使用空格分隔开。的顺序输出,各成员之间使用空格分隔开。如果利用结构体输出学生名单“如果利用结构体输出学生名单“ 0912000101 0912000101 张三”,如何设张三”,如何设

计该程序?计该程序?

课堂练习课堂练习

Page 82: 计算机实习

编写一个程序实现如下功能:定义一个点的结构数据类型,实现下列功能:①为点输入坐标值。②求两个点中点坐标。③求两点间距离。

Page 83: 计算机实习

课后练习课后练习1

2

分数包含分子分母两项,定义一个有关分数分数包含分子分母两项,定义一个有关分数的结构体类型,写一个函数计算两分数之和,的结构体类型,写一个函数计算两分数之和,结果仍为分数类型,注意约分。编写主函数结果仍为分数类型,注意约分。编写主函数验证之。验证之。

编写一个程序实现如下功能:定义一个点的结构数据编写一个程序实现如下功能:定义一个点的结构数据类型,实现下列功能:类型,实现下列功能:①① 为点输入坐标值。为点输入坐标值。②② 求两个点中点坐标。求两个点中点坐标。③③ 求两点间距离。求两点间距离。

Page 84: 计算机实习

谢谢