源码: github.
问题背景:
将有内在联系的变量组成一个组合数据
设想:数组:一个数组只能存放同一类型的数据
解决办法:C语言允许用户自己建立由不同数据类型组成的组合型的数据结构,称之为结构体
举例:
struct Student
{
int num;
char name[20];
char sex;
int age;
float score;
char address[30];
}; //注意:此处有一个分号
形式:
struct 结构体名
{
成员列表;(类型名 成员名;)
}
#include
int main()
{
struct student
{
long int num;
char name[20];
char sex;
char addr[20];
}a={10101,"Li Lin",'M',"123 Beijing Road"};
printf("NO.:%ld\nname:%s\nsex:%c\naddress:%s\n",a.num,a.name,a.sex,a.addr);
return 0;
}
#include
int main()
{
struct student // 声明结构体类型struct student
{
int num;
char name[20];
float score;
}student1,student2; // 定义两个结构体变量seudent1,student2
scanf("%d%s%f",&student1.num,student1.name, &student1.score); //输入学生1敌数据
scanf("%d%s%f",&student2.num,student2.name, &student2.score); //输入学生1敌数据
printf("The higher score is:\n");
if (student1.score>student2.score)
printf("%d %s %6.2f\n",student1.num,student1.name, student1.score);
else if (student1.score<student2.score)
printf("%d %s %6.2f\n",student2.num,student2.name, student2.score);
lse
{
printf("%d %s %6.2f\n",student1.num,student1.name, student1.score);
printf("%d %s %6.2f\n",student2.num,student2.name, student2.score);
}
return 0;
}
#include
#include
struct person // 声明结构体类型struct person
{
char name[20]; // 候选人姓名
int count; // 候选人得票数
}leader[3]={"Li",0,"Zhang",0,"Sun",0}; // 定义结构体数组并初始化
int 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++;
}
printf("\nResoult:\n");
for(i=0;i<3;i++)
printf("%5s:%d\n",leader[i].name,leader[i].count);
return 0;
}
#include
struct student // 声明结构体类型struct student
{
int num;
char name[20];
float score;
};
int main()
{
struct student stu[5]={{10101,"Zhang",78},{10103,"Wang",98.5},{10106,"Li",86},
{10108,"Ling",73.5},{10110,"Fun",100}}; // 定义结倒构体数组并初始化
struct student temp; //定义结构体变量temp,用作交换时的临时变量
const int n=5;
int i,j,k;
printf("The order is:\n");
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(stu[j].score>stu[k].score) // 进行成绩的比较
k=j;
temp=stu[k];
stu[k]=stu[i];
stu[i]=temp; // stu[k]和stu[i]元素互换
}
for(i=0;i<n;i++)
printf("%6d %8s %6.2f\n",stu[i].num,stu[i].name,stu[i].score);
printf("\n");
return 0;
}
指向结构体对象的指针变量即可以指向结构体变量,也可指向结构体数组中的元素
#include
#include
int main()
{
struct student
{
long num;
char name[20];
char sex;
float score;
};
struct student stu_1; // 定义struct student类型的变量stu_1
struct student * p; // 定义指向struct student 类型数据的指针变量p
p=&stu_1; // p指向stu_1
stu_1.num=10101; // 对结构体变量的成员赋值
strcpy(stu_1.name,"Li Lin");
stu_1.sex='M';
stu_1.score=89.5;
printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n", stu_1.num, stu_1.name, stu_1.sex, stu_1.score); // 输出结果
printf("\nNo.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n", (*p).num, (*p).name, (*p).sex, (*p).score);
printf("\nNo.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n", p->num, p->name, p->sex, p->score);
return 0;
}
#include
struct student
{
int num;
char name[20];
char sex;
int age;
};
struct student stu[3]=
{{10101,"Li Lin",'M',18},{10102,"Zhang Fun",'M',19},{10104,"Wang Min",'F',20}}; // 定义结构体数组并初始化
int main()
{
struct student *p; //定义指向struct student结构体的数组
printf(" No. Name sex age\n");
for (p=stu;p<stu+3;p++)
printf("%5d %-20s %2c %4d\n",p->num, p->name, p->sex, p->age);
return 0;
}
结构体变量的值传递给另一函数,有三个方法
#include
#define N 3 // 学生数为3
struct student // 建立结构体类型struct student
{
int num; // 学号
char name[20]; // 姓名
float score[3]; // 3门课成绩
float aver; // 平均成绩
};
int main()
{
void input(struct student stu[]); // 函数声明
struct student max(struct student stu[]); // 函数声明
void print(struct student stu); // 函数声明
struct student stu[N],*p=stu; // 定义结构体数组和指针
input(p); // 调用input函数
print(max(p)); // 调用print函数,以max函数的返回值作为实参
return 0;
}
void input(struct student stu[]) // 定义input 函数
{
int i;
printf("请输入各学生的信息:学号、姓名、三门课成绩:\n");
for(i=0;i<N;i++)
{
scanf("%d %s %f %f %f",&stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]); // 输入数据
stu[i].aver=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3.0; // 求各人平均成绩
}
}
struct student max(struct student stu[]) // 定义max 函数
{
int i,m=0; // 用m存放成绩最高的学生在数组中的序号
for(i=0;i<N;i++)
if (stu[i].aver>stu[m].aver) m=i; // 找出平均成绩最高的学生在数组中的序号
return stu[m]; // 返回包含该生信息的结构体元素
}
void print(struct student stud) // 定义print函数
{
printf("\n成绩最高的学生是:\n");
printf("学号:%d\n姓名:%s\n三门课成绩:%5.1f,%5.1f,%5.1f\n平均成绩:%6.2f\n",stud.num,stud.name,stud.score[0],stud.score[1],stud.score[2],stud.aver);
}
用结构体变量来建立链表是最合适的
#include
struct student // 声明结构体类型struct student
{
int num;
float score;
struct student *next;
};
int main()
{
struct student a,b,c,*head,*p; // 定义3个结构体变量作为链表的结点
a. num=10101; a.score=89.5; // 对结点a的num和score成员赋值
b. num=10103; b.score=90; // 对结点b的num和score成员赋值
c. num=10107; c.score=85; // 对结点c的num和score成员赋值
head=&a; // 将结点a的起始地址赋给头指针head
a.next=&b; // 将结点b的起始地址赋给a结点的next成员
b.next=&c; // 将结点c的起始地址赋给a结点的next成员
c.next=NULL; // c结点的next成员不存放其他结点地址
p=head; // 使p也指向a结点
do
{
printf("%ld %5.1f\n",p->num,p->score); // 输出p指向的结点的数据
p=p->next; // 使p指向下一结点
}while(p!=NULL); // 输出完c结点后p的值为NULL,循环终止
return 0;
}
本程序中所有节点都是在程序中定义的,不存在临时开辟的,用完后也不能释放,这种链表称为“静态链表”
#include
#include
#define LEN sizeof(struct student)
struct student
{
long num;
float score;
struct student *next;
};
int n;
struct student *creat(void)
{
struct student *head;
struct student *p1,*p2;
n=0;
p1=p2=(struct student *)malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score);
head=NULL;
while(p1->num!=0)
{
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct student*)malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score);
}
p2->next=NULL;
return(head);
}
int main()
{
struct student *pt;
pt=creat(); // 函数返回链表第一个结点的地址
printf("\nnum:%ld\nscore:%5.1f\n",pt->num,pt->score); // 输出第一个结点的成员值
return 0;
};
#include
#include
#define LEN sizeof(struct student)
struct student
{
long num;
float score;
struct student *next;
};
int n;
struct student *creat()
{
struct student *head;
struct student *p1,*p2;
n=0;
p1=p2=( struct student*) malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score);
head=NULL;
while(p1->num!=0)
{
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct student*)malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score);
}
p2->next=NULL;
return(head);
}
void print(struct student *head)
{
struct student *p;
printf("\nNow,These %d records are:\n",n);
p=head;
if(head!=NULL)
do{
printf("%ld %5.1f\n",p->num,p->score);
p=p->next;
}while(p!=NULL);
}
int main()
{
struct student *head ;
head=creat();
print(head);
return 0;
}
定义共用体类型变量的形式
union 共用体名
{
成员表列
}变量表列;
定义“共用体” 和 “结构体”的形式相似,但它们含义不同
其他书籍中将“共用体”翻译为“联合体”,但是不方便理解
引用共用体变量的方式
不建议引用共用体变量,建议直接引用成员变量。
共用体数据类型的特点
#include
struct
{
int num;
char name[10];
char sex;
char job;
union
{
int clas;
char position[10];
}category;
}person[2];
int main()
{
int i;
for(i=0;i<2;i++)
{
printf("please enter the data of person:\n");
scanf("%d %s %c %c", &person[i].num, &person[i].name, &person[i].sex, &person[i].job);
if(person[i].job == 's')
scanf("%d", &person[i].category.clas);
else if(person[i].job == 't')
scanf("%s", person[i].category.position);
else
printf("Input error!");
}
printf("\n");
printf("No. name sex job class/position\n");
for(i=0;i<2;i++)
{
if (person[i].job == 's')
printf("%-6d%-10s%-4c%-4c%-10d\n",person[i].num, person[i].name,
person[i].sex, person[i].job, person[i].category.clas);
else
printf("%-6d%-10s%-4c%-4c%-10s\n",person[i].num, person[i].name,
person[i].sex, person[i].job, person[i].category.position);
}
return 0;
}
#include
int main()
{
enum Color {red,yellow,blue,white,black}; //声明枚举类型enum Color
enum Color i,j,k,pri; //定义枚举变量i,j,k,pri
int n,loop;
n=0;
for (i=red;i<=black;i++) //外循环使i的值从red变到black
{
for (j=red;j<=black;j++) //中循环使j的值从red变到black
{ if (i!=j) //如果二球不同色
{
for (k=red;k<=black;k++) //內循环使k的值从red变到black
{
if ((k!=i) && (k!=j)) //如果3球不同色
{
n=n+1; //符合条件的次数加1
printf("%-4d",n); //输出当前是第几个符合条件的组合
for (loop=1;loop<=3;loop++) //先后对三个球分别处理
{
switch (loop) //loop的值从1变到3
{
case 1: pri=i;break; //loop的值为1时,把第1球的颜色赋给pri
case 2: pri=j;break; //loop的值为2时,把第2球的颜色赋给pri
case 3: pri=k;break; //loop的值为3时,把第3球的颜色赋给pri
default:break;
}
switch (pri) //根据球的颜色输出相应的文字
{
case red:printf("%-10s","red"); break; //pri的值等于枚举常量red时输出“red”
case yellow: printf("%-10s","yellow"); break; //pri的值等于枚举常量yellowd时输出“yellow”
case blue: printf("%-10s","blue"); break; //pri的值等于枚举常量blue时输出“blue”
case white: printf("%-10s","white"); break; //pri的值等于枚举常量white时输出“white”
case black: printf("%-10s","black"); break; //pri的值等于枚举常量black时输出“black”
default :break;
}
}
printf("\n");
}
}
}
}
}
printf("\ntotal:%5d\n",n);
return 0;
}
概述:
使用举例
FORTRAN 语言中Integer Real,以适用他们的编程习惯
(1)代表结构体类型
(2)代表数组类型
typedef int Num [10]; //声明 Num为整型数组类型名
Num a; //定义 a 为整形数组名 Num 是 int[10] 同义词
(3)代表指针
typedef char * String; //声明a为字符指针类型
String p , s[10]; //p 字符指针变量 s 为字符指针数组 String是 char * 同义词
(4)代表指向函数的指针类型
typedef int ( * Pointer ) (); //声明Pointer为指向函数的指针变量
Pointer p1,p2; //p1 p2 为Pointer类型的指针变量 Pointer 是 int (*) () 同义词
习惯将声明的类型名的首字母设为 大写 ,以便与系统提供的标准类型标志符相区别
typedef 与 #define 比较
typedef int Coount ; //在编译阶段处理
#define Count int //只是在预编译过程中作简单的字符串替换
当不同源文件用到同一类型数据时,(数组 指针 结构体 共用体 ),可以将 typedef 放在一个头文件中,然后在需要用的源文件中,用#include指令把它们包含在文件中
使用typedef有利于程序的通用与移植
不同硬件int有不同的字节长度定义,有2字节 和 4字节 的区别
当从4字节系统中 移植 到 2字节系统中,一般方式是将int 替换成 long ,int a,b,c --> long a,b,c,需要对程序多出进行修改
可以用 typedef int Integer;
typedef long Integer;