什么是结构体?
结构体的本质就是把一些基本类型数据组合在一起形成的一个新的复合数据类型。
利用结构体可以造出一种新的数据类型,这种新的数据类型是由基本数据类型组合在一起的,利用结构体,我们就可以模拟现实生活中任何一个比较复杂的事物。
结构体的定义和结构体变量的初始化
/**
* 三种定义结构体的方式(等价)
* 定义的同时可以同时赋初值
* 如果定义完后则只能单个地赋初值
*/
//第一种方式,纯粹定义结构体类型(推荐)
struct Student {
int num;
char sex;
float score;
}; //分好不能省
//第二种方式,在定义结构体类型的同时,定义结构体类型变量
struct Student {
int num;
char sex;
float score;
} stu1,stu2;
//第三种方式,无结构体名方式
struct {
int num;
char sex;
float score;
} stu1,stu2;
/**
* 结构体变量的初始化和赋值
*/
struct Student stu1 = {2010, 'M', 66.6}; //定义的同时进行定义赋值
struct Student stu2; //先定义,之后再赋值
stu2.num = 2010;
stu2.sex = 'F';
stu2.score = 55.5;
printf("%d %c %f\n", stu1.num, stu1.sex, stu1.score);
两种读写结构体变量成员的方法
/**
* 两种读写结构体变量的成员的方法:
* 1、指针变量—>成员名
* 2、结构体变量名 .成员名 例如 st1. num
* 通常我们只使用第一种方式
*/
# include <stdio.h>
# include <string.h>
int main() {
struct Student {
char name[10]; //c语言中数据类型中没有字符串类型,字符串用字符数组来实现
int num;
char sex;
float score;
};
struct Student stu = {"kignlyjn", 2010, 'M', 99};
struct Student * pstu = &stu; //定义结构体类型的指针,注意‘&st’不要写成‘st’
strcpy(pstu->name, "张三");
pstu->num = 2011;
(*pstu).sex = 'F'; //等价于pstu->sex = 'F';
(*pstu).score = 88.9f; //因此88.9是double类型,而88.9f是float类型
printf("%s %d %c %f\n", pstu->name, pstu->num,pstu->sex, pstu->score);//%s表示输出字符串
strcpy(stu.name, "李四"); //第二种方式
stu.num= 2011;
stu.sex= 'F';
stu.score= 88.8f;
printf("%s %d %c %f\n", stu.name, stu.num, stu.sex,stu.score);
}
/*
[注]:常用字符串函数总结
1、使用到字符串处理函数时,应当在程序文件的开头加 string.h 头文件;
2、puts(字符数组);表示将一个字符串输出--例如:charstr[] = {"China\nBeijing"}; puts(str); 会将str这个字符串输出到屏幕;
3、gets(字符数组);其作用是从终端输入一个字符串到一个已经定义好的字符数组--例如:gets(str);从键盘键入"China!\n";
4、strcpy(字符数组1,字符串或字符数组2);其作用是将字符串或字符数组2的内容复制到字符数组1中;
--例如:该程序的strcpy(st.name,"李四");语句;
5、strncpy(str1, str2, 2);表示将str2中最前面两个字符复制到str1中,取代str1中原有的最前面两个字符;
6、strcat(字符串1, 字符串2);表示将字符串2接到字符串1的后面,结果放在字符数组1中,函数调用后得到字符数组1的地址;
7、strcmp(字符串1,字符串2);其作用是按照ASCII编码的前后顺序比较讲个字符串;
如果全部字符相等,则认两个字符串相等;
若出现不同的字符,则以第一对不相同的字符比较结果为准;
若字符串1==字符串2,则函数返回值为0;若字符串1>字符串2,则返回值为一个正数;若字符串1<字符串2,则返回值是一个附负数;
8、strlen(字符数组);表示测量字符串的实际长度(不包括末尾的‘\0’在内!);
*/
结构体的相互赋值
/**
* 结构体变量不能相加,不能相减,也不恩能够相互乘除;
* 但结构体变量可以相互赋值;
*/
struct Student {
char name[9];
char sex;
float score;
};
struct Student st1,st2
st1 + st2;//error!
st1 - st2;//error!
st1 * st2;//error!
st1 / st2;//error!
st1 = st2;//OK!
st2 = st1;//OK!
结构体变量和结构体变量指针作为函数参数传递
/**
* 通过函数完成对结构体变量的输入和输出
*/
# include <stdio.h>
# include <string.h>
struct Student {
char name[10];
int num;
double score;
};
int main() {
struct Student stu;
void input_stu(struct Student *);
void print_stu(struct Student *);
input_stu(&stu);
print_stu(&stu);
return 0;
}
void input_stu(struct Student * pst) {
strcpy(pst->name,"张三"); //[注]:不能写成(*pst).name = "张三";必须要用字符串处理函数strcpy完成赋值任务!
pst->num= 2010;
pst->score= 99.9f;
return;
}
void print_stu(struct Student * pst) { //传递的变量最好为stu的指针,这样可以大大的节省内存的开销
printf("%s %d %lf\n", pst->name,pst->num,pst->score);
return;
}
常指针和指向常量的指针
/**
* 指向常量的指针,指针可以变,指针指向的内容不可以变
*/
# include <stdio.h>
int main () {
int a[2] = {1, 2};
const int * p = a; //与"int const * p = a" 等价
p++;
printf("%d\n", p[0]); //2
p[0] = 3; //error!
printf("%d\n", p[0]);
return 0;
}
/**
* 常指针,指针不可以变,指针指向的内容可以变
*/
# include <stdio.h>
int main () {
int a[2] = {1, 2};
int * const p = a;
p[0] = 3; //OK
printf("%d\n", p[0]);
p++; //error!
printf("%d\n", p[0]);
return 0;
}
学生信息管理模拟程序-v1.0
/**
* 2013年12月26日20:21:41
* 学生信息管理系统_第一版
*/
# include <stdio.h>
# include <string.h>
# include <mm_malloc.h>
struct Student {
char name[10];
int num;
float score;
};
int main() {
struct Student * pst; //指向存放学生信息数组的第一个元素的地址
int len; //学生的个数
void input_stu(struct Student *, int);
void print_stu(struct Student *, int);
void sort_stu_by_score(struct Student *, int);
printf("please input the length of stu: ");
scanf(" %d", &len);
//为学生信息的存储开辟内存空间
pst = (struct Student *) malloc(sizeof(struct Student)*len);
//输入学生信息
input_stu(pst, len);
//学生分数排序
sort_stu_by_score(pst, len);
//输出学生信息
print_stu(pst, len);
return 0;
}
void input_stu(struct Student * pst, int len) {
for (int i=0; i<len; i++) {
printf("please input the infomation of student %d: \n", i+1);
printf("name: ");
scanf(" %s", pst[i].name); //注意此处的 pst[i].name 本身就是指针
printf("num: ");
scanf(" %d", &pst[i].num);
printf("score: ");
scanf(" %f", &pst[i].score);
}
}
void print_stu(struct Student * pst, int len) {
printf("student infomation is as follows: \n");
for (int i=0; i<len; i++) {
printf("%-15s %-10d %-5.1f\n", pst[i].name, pst[i].num, pst[i].score);
}
}
void sort_stu_by_score(struct Student * pst, int len) {
struct Student t;
for (int i=0; i<len-1; i++) {
for (int j=0; j<len-i-1; j++) {
if (pst[j].score < pst[j+1].score) { //分数从大到小排序,注意交换的是学生而不是学生分数
t = pst[j];
pst[j] = pst[j+1];
pst[j+1] = t;
}
}
}
}
共用体
概念:在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体。
/**
* 共用体测试
*/
# include <stdio.h>
union data {
int i; //不能初始化
int j;
};
int main() {
union data s1;
s1.i = 2;
s1.j = 3;
printf(" %d\n", s1.i); //3
return 0;
}
枚举
概念:枚举说白了就是把一个事物所有可能的取值一一列举列出出来
优缺点:
- 优点:使代码更安全
- 缺点:写代码麻烦
简单示例:
# include <stdio.h>
enum Weekday {
MonDay,TuesDay, WednsDay,ThursDay, FriDay,SaturDay, SunDay // 0 1 2 3 4 5 6
};
enum Weekday1 {
MonDay1,TuesDay1=4, WednsDay1,ThursDay1, FriDay1,SaturDay1, SunDay1 // 0 4 5 6 7 8 9
};
int main() {
enum Weekday day = SunDay;
printf("%d\n", day); //6
enum Weekday1 day1 = SunDay1;
printf("%d\n", day1); //9
return 0;
}
typedef 自定义类型
概念:typedef声明为现有类型创建一个新的名字(类型别名),在结构体定义以及一些数组等地方大量地用到。它只是对C标准库中的数据类型增加一个别名,并没有创建新的数据类型。
与#define的区别:
- define是在预编译时处理的,它只是做简单的字符串替换,是针对文本的;
- typedef是在编译时处理的,不是简单的字符串替换,它是针对语义的。
typedef int myint; //声明int的别名为myint
myint a;
typedef struct Student { //声明struct Student的别名为St
int num;
char name[10];
} St;
St student1;
typedef char * Str; //声明str为字符指针类型名
Str s; //定义一个字符指针变量