函数指针数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
int add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int mul(int x, int y)
{
int z = 0;
z = x * y;
return z;
}
int sub(int x, int y)
{
int z = 0;
z = x - y;
return z;
}
int Div(int x, int y)
{
int z = 0;
z = x / y;
return z;
}
void menu()
{
printf("1.加法 2.减法 3.乘法 4.除法\n");
}

//对于此处这么多的函数,假如要一个一个使用则需要写出以下代码
int main()
{
menu();
int i=0;
scanf("%d",&i);
int x,y,z;
scanf("%d%d",&x,&y);
switch(i)
{
case 1:z=add(x,y);break;
case 2:z=sub(x,y);break;
case 3:z=mul(x,y);break;
case 4:z=Div(x,y);break;
}
printf("%d",z);
return 0;
}

//我们可以使用函数指针数组来存放这些函数
int main()
{
int (*p[5])(int, int) = { 0,add,sub,mul,Div };
//此处用0是为了好看,让1为add顺序对应
//需要调用是只用
int i=0;
scanf("%d",&i);
int x,y;
scanf("%d%d",&x,&y);
int z=p[i](x,y);
printf("%d",z);
}
//说实话没简单多少
//我们还可以使用函数指针来传递给一个函数
void diaoyong(int(*p)(int,int))
{
int x,y;
scanf("%d%d",&x,&y);
int z=p(x,y);
printf("%d",z);
}
int main()
{
menu();
int i=0;
scanf("%d",&i);
switch(i)
{
case 1:diaoyong(add);break;
case 2:diaoyong(sub);break;
case 3:diaoyong(mul);break;
case 4:diaoyong(Div);break;
}
}
//看起来更加的花里胡哨,真难用
1
2
3
4
5
//这里还有使用指针指向函数指针数组
//先定义一个函数指针数组
int (*p[5])(int,int);
//在创建指针
int(*(*p)[5])(int,int)

qsort排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//  qsort---排序
//1.void*
//1、此类型指针可以接受任意类型的地址
//2、此类型指针不能进行解引用
//3、此类型指针不能进行+-整数的操作
//qsort一般用法为:
//qsort(arr,sz,sizeof(arr[0]),cmp_void)
//其中cmp函数一般格式为
//int cmp (const void*e1,const void*e2)
//{
//在括号里需要是一种返回0,正数,负数的计算
//}
//展示例子
//1.首先是整形排序
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);//由于void*类型不能解引用,因此使用强制类型转换
}
//2.接着是浮点数排序
int cmp_float(const void* e1, const void* e2)
{
//此处需要利用float来返回int会警告,可利用比较大小的方式直接返回整数,但也可以不管警告
return (*(float*)e1 - *(float*)e2);
}
//3.然后是结构体排序
//定义一个结构体
struct str
{
char name[20];
int age;
};

//(1)通过年龄排序
int cmp_str_age(const void* e1, const void* e2)
{
return((struct str*)e1)->age - ((struct str*)e2)->age;
}
//(2)通过名字排序
int cmp_str_name(const void* e1, const void* e2)
{
return strcmp(((struct str*)e1)->name, ((struct str*)e2)->name);
}

int main()
{
int i = 0;
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
float arr1[10] = { 9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0,0 };
struct str s[3] = { {"张三",20},{"李四",10},{"王五",30}};

int sz = sizeof(arr) / sizeof(arr[0]);
int sz1 = sizeof(arr1) / sizeof(arr1[0]);
int sz2 = sizeof(s) / sizeof(s[0]);

qsort(arr, sz, sizeof(arr[0]), cmp_int);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");

qsort(arr1, sz1, sizeof(arr1[0]), cmp_float);
for (i = 0; i < sz1; i++)
{
printf("%f ", arr1[i]);
}
printf("\n");

qsort(s, sz2, sizeof(s[0]), cmp_str_name);
for (i = 0; i < sz2; i++)
{
printf("%s ", s[i].name);//!!加点进行访问,不要忘了
}
printf("\n");

qsort(s, sz2, sizeof(s[0]), cmp_str_age);
for (i = 0; i < sz2; i++)
{
printf("%d ", s[i].age);//!!加点进行访问,不要忘了
}
printf("\n");

}

字符串函数及字符函数的运用

strcat的运用

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
char arr1[30] = "abc";
char arr2[] = "cdf";
strcat(arr1, arr2);
//将arr2接在arr1后面,从arr1的\0开始接
printf("%s", arr1);//结果abcdef
//自己给自己追加时不能使用此函数!!
//为什么?
//举例 :当我的字符串为"abcdef\0"时,我们把\0直接追加掉了从而导致
追加的字符串找不到\0也就无法停止追加
//假如要使用则需strncat
}

strncat的运用

1
2
3
4
5
6
7
8
9
与srencat类似,只是在参数中多了一个所传元素个数,不需要去寻找\0
也就能够做到自己追加自己,并且当它所追加的元素个数大于字符串的时候,只追加到字符串的\0
举例:
int main()
{
char arr1[30] = "abc";
strncat(arr1, arr1,strlen(arr1));//多了一个所传的长度
printf("%s", arr1);//结果为abcabc
}

strstr的运用

1
2
3
4
5
6
7
8
9
//判断一个字符串是否在另一个字符串内,如果不在返回NULL,如果在返回第一个值的地址
int main()
{
char arr1[30] = "abcdef";
char arr2[] = "abcd";//必须是连续的存在于arr1
char *ret=strstr(arr1,arr2);
//在arr1中寻找arr2,找到了返回第一个值的地址
printf("%p", ret);
}

strlen

1
2
1.注意事项,strlen返回的值时size_t为unsigned int类型,即他没有负数。
2.返回\0前的数,不包含\0

strcpy

1
2
3
4
5
6
7
8
9
10
int main()
{
//我们很早就学过,strcpy是吧一个字符串拷贝到另一个字符串中
//举例:
char arr1[] = "abcdef";
char arr2[] = "666";
strcpy(arr1, arr2);//把arr2拷贝到arr1里,包括\0
//注意返回的是arr1的首地址,char*
printf("%s", arr1);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
接下来自己实现一次
char * my_strcpy(char*arr1,const char*arr2)
{
assert(arr1!=NULL);
assert(arr2!=NULL);
char* ret = arr1;
//很好的算法思路
while (*arr1++ = *arr2++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "666";
//那么自己实现一次
my_strcpy(arr1, arr2);//把arr2拷贝到arr1里,包括\0
printf("%s", arr1);
}

strncpy

1
2
3
4
5
6
7
8
9
//6.strncpy  指定个数的拷贝
int main()
{
char a[] = "abcdef";
char b[] = "efg";
strncpy(a, b, 4);
strcpy(a, b, 5);//当拷贝的字符串不够拷贝时,他会将不够的自动补\0,或者报错
printf("%s",a);
}

strcmp

1
2
3
4
5
6
7
8
比较两个字符串的大小
int main()
{
char a[] = "abc";
char b[] = "efg";
int ret = strcmp(a, b);//a>b返回正数 a<b返回负数 a=b返回0
printf("%d", ret);
}

strncmp

1
与上面同理,指定个数的比较

1
2
NULL --空指针
NUL,Null--\0

strtok

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//7.strtok  分割字符串
int main()
{
char a[] = "123456@666666.com";
char b[111111] = { 0 };
strcpy(b, a);
const char* p = "@.";
//!!!!!!!strtok的第一个参数如果为NULL,那么函数将在第一个字符串中被保存的位置开始,查找下一个标记

//char* ret=strtok(a, p);
//printf("%s\n", ret);
//ret = strtok(NULL, p);
//printf("%s\n", ret);
// ret = strtok(NULL, p);
//printf("%s\n", ret); 这样写太土了,我们利用strtok找不到时返回NULL可以写出以下简便代码

char* ret = NULL;
for (ret = strtok(a, p); ret != NULL; ret = strtok(NULL, p))
{
printf("%s\n", ret);
}
}

strerror

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//8.strerror
//首先了解错误码和错误信息
// 0 ------ No error
// 1 ------ Operation not permitted
// 2 ------ No such file or direction
//errno 是一个全局的错误码变量
//当c语言的库函数在执行过程中,放生了错误,就会把相应的对应码存在errno中
int main()
{
FILE* p = fopen("text.txt", "r");//后面是打开text.txt的意思
if (p == NULL)
{
printf("%s\n", strerror(errno));
}
else
printf("open file success");
}

转大小写函数

tolower
toupper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
char C = 'C';
char d = 'd';
char c = tolower(C);//小写不动,大写转小写
char D = toupper(d);//大写不动,小写转大写
printf("%c", c);
printf("%c", D);

//假如需要把一整个字符串改成大小写
//使用while循环
int i = 0;
char a[] = "I am a Student";
while (a[i])
{
a[i] = toupper(a[i]);
i++;
}
printf("%s", a);
}
}

memcpy和memmove

1
2
3
4
5
6
7
8
9
10
11
//9.memcpy
//strcpy只能拷贝字符串,具有局限性,而memcpy能拷贝任意类型,实例如下
//只处理不重叠的内存拷贝,重叠交给memmove,但此编译器可用
int main()
{
char a[] = { 0,1,2,3,4,5,6,7,8,9 };
memcpy(a+2, a, 3);
int i;
for (i = 0; i < 10; i++)
printf("%d", a[i]);
}

自定义数据结构

结构体内存偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
对于结构体struct类型占用空间有着他独特的占用方式
首先他每种类型对于起始值有着特定的偏移量,其值等于它所占用空间与
系统默认偏移量的较小值。同时其对齐量必须为其偏移量的整数倍
举个例子:
struct s
{
char a; //首先char占用空间位1,是1和8的较小值,对齐量为1的整数倍,所以其占用空间可以从起始值开始。为1;
int b; //其次int占用空间为4,是4和8的较小值,对齐量就要为4的整数倍,所以其占用空间需要先浪费三个,到起始值往下的第四个位置开始占用4个字节,也就是已经占用了7个字节
char c; //这里同1,又占用了一个字节,总共9个字节,但结构体所占空间需为最大偏移量的整数倍因此总共占有12个字节;

//!!!//如果结构体里嵌套结构体,那么对齐量为里面结构体的最大对齐量。
};
因此,在设计结构体时,尽量把占用内存小的集中在一起;
同时我们还可以设置默认对齐数
#pragma pack (4)//设置默认对齐数
#pragma pack ()//取消默认对齐数

offsetof()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stddef.h>
struct s
{
char a;
int b;
char c;
};
int main()
{
printf("%d", offsetof(struct s, a));
printf("%d", offsetof(struct s, b));
printf("%d", offsetof(struct s, c));

}
计算偏移量

位段—二进制位

1
2
3
4
5
6
7
8
9
eg:
struct s
{
int a:2;
int b:20;
int c:23;
int d:32 //后面的数字不能大于32(四个字节)
};
//内存占用一个整型一个整型的拿出来
1
2
3
4
5
6
7
8
9
struct s
{
char a:3;
char b:4;
char c:5;
char d:4;
//此为字符型
} 注意!,假如位数不够存放数,例如
s.a=10 //10时1010,只存放010;,不够则补0

枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
//2.枚举--enum
enum sex
{
//枚举的可能取值是常量
MALE,//默认是0
FEMALE,//默认是0+1
SECRET,//默认是0+1+1
NONE=10//假如要赋初始值可以直接=
};
int main()
{
enum sex const s=MALE;
}

联合

1
2
3
4
5
6
7
//3.联合--union
union un
{
int a;
char c; //注意,因为他们俩共同占用一块空间,所以为联合体,char的那块共用了,所以他们的地址相同
//占用空间大小至少是最大成员的大小
};

动态内存分配

malloc free

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//1.malloc与free
#include<stdlib.h>
int main()
{
//首先向内存申请40个整形空间
int* p = (int*)malloc(40 * sizeof(int));//这里用整形举例,前面的标准是void*因此等号右边需要进行强制类型转换
int i = 0;
int n = 10;
if (p == NULL)//开辟失败会返回一个空指针
{
printf("%s", strerror(errno));//当开辟错误时,输出错误的原因
}
else
{
for (i = 0; i < n; i++)
{
*(p + i) = i;
}
for (i = 0; i < n; i++)
{
printf("%d ", *(p + i));
}
}
free(p);//释放开辟剩余的空间,但p并没有变化
p = NULL;//因此直接把p变为空指针,才能保证安全
return 0;
}

calloc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//2.calloc
//与malloc一致,只是使用时有一点差别,并且他会初始化所有值为0;
int main()
{
int* p = (int*)calloc(10, sizeof(int));
int i = 0;
int n = 10;
if (p == NULL)//开辟失败会返回一个空指针
{
printf("%s", strerror(errno));//当开辟错误时,输出错误的原因
}
else
{
for (i = 0; i < n; i++)
{
*(p + i) = i;
}
for (i = 0; i < n; i++)
{
printf("%d ", *(p + i));
}
}
free(p);//释放开辟剩余的空间,但p并没有变化
p = NULL;//因此直接把p变为空指针,才能保证安全
return 0;
}

realloc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//3.realloc:调整动态内存
//首先一点注意,假如后面的内存足够多,realloc将直接在后面追加内存,并返回原来的地址
//假如不够多,会重新开辟一片新的空间,并把原来的数据填充到新的中,释放旧的内存空间,返回新的地址,也就是返回的地址p会变化
int main()
{
int* p = (int*)malloc(20);
if (p == NULL)
{
printf("%s", strerror(errno));
}
else
{
int i = 0;
for (i = 0; i < 5; i++)
{
*(p + i) = i;
}
for (i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
}
int* p2 = (int*)realloc(p, 20);//得用一个新变量来接受realloc的返回值
if (p2 != NULL)
{
p=p2;//开辟成功的时候才把p2赋给p
}
for (i = 0; i < 5; i++)
{
*(p2 + i) = i;
}
for (i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
free(p);
p = NULL;
return 0;
}
1
2
其次,可以用realloc实现malloc的功能
int *p=realloc(NULL,20);

文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//int main()
//{
//. 表示当前路径
// .. 表示上一级路径
//fopen("C:\\Users\\陈亮\\Pictures\\Screenshots","r");//绝对路径
//fopen("text.txt", "r");//相对路径
//FILE* pf = fopen("text.txt", "r");
//if (pf == NULL)
//{
// printf("%s\n", strerror(errno));
//}
//fclose(pf);
//pf = NULL;
//return 0;
//}

写入文件

写一个字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//int main()
//{
// FILE* pfwrite = fopen("text.txt", "w");
// if (pfwrite == NULL)
// {
// printf("%s\n", strerror(errno));
// return 0;
// }
// fputc('c', pfwrite);
// fputc('l', pfwrite);
// fputc('6', pfwrite);
//
// fclose(pfwrite);
// pfwrite = NULL;
// return 0;
//}

写一个字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//6.fputs
int main()
{
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
printf("%s", strerror(errno));
return 0;
}
fputs("hello", pf);//把hello写到pf里
fclose(pf);
pf = NULL;
return 0;
}

格式化写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct str
{
int n;
char a[100];
char b;
};

int main()
{
struct str s={ 100,"cl",'a' };
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
return 0;
}
fprintf(pf, "%d %s %c", s.n,s.a,s.b);
}

二进制写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//7.fwrite
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "张三",20,22.2 };
FILE* pf = fopen("text.txt", "wb");//以二进制形式写文件
if (pf == NULL)
{
return 0;
}
fwrite(&s, sizeof(struct S), 1, pf);//从s中将1个sizeof(s)的数据写入pf
fclose(pf);
pf = NULL;
return 0;
}

读文件

1.读字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//int main()
//{
// FILE* pfread = fopen("text.txt", "r");
// if (pfread == NULL)
// {
// printf("%s\n", strerror(errno));
// return 0;
// }
// printf("%c",fgetc(pfread));
// printf("%c", fgetc(pfread));
// printf("%c", fgetc(pfread));
// fclose(pfread);
// pfread = NULL;
// return 0;
//}

读字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//5.fgets
int main()
{
char buf[1000];
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
printf("%s", strerror(errno));
return 0;
}
fgets(buf, sizeof(buf), pf); //从pf中获取字符串拷贝到buf里,会包括换行符
printf("%s", buf);
fclose(pf);
pf = NULL;
return 0;
}

格式化读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct str
{
int n;
char a[100];
char b;
};

int main()
{
struct str s={0 };
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
return 0;
}
fscanf(pf, "%d %s %c", &s.n, &s.a, &s.b);
printf("%d %s %c", s.n, s.a, s.b);
return 0;
}

二进制读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fread//用法和fwrite相似
struct S
{
char name[20];
int age;
float score;
};
int main()
{
//struct S s = { "张三",20,22.2 };
struct S tmp = { 0 };
FILE* pf = fopen("text.txt", "rb");//以二进制形式写文件
if (pf == NULL)
{
return 0;
}
fread(&tmp, sizeof(struct S), 1, pf);//从pf中将1个sizeof(s)的数据读到tmp
printf("%d", tmp.age);
fclose(pf);
pf = NULL;
return 0;
}

从键盘输入,输出到屏幕,都是外部设备

1
2
3
4
5
6
7
8
9
10
11
12
//键盘-标准输入设备
//屏幕-标准输出设备
//程序默认打开的两个流设备
//stdin
//stdout
//stderr 三者都是FILE*
//eg:
//int main()
//{
// int ch = fgetc(stdin);
// fputc(ch, stdout);
//}

fgets和fputs使用记录

1
2
3
4
5
6
7
8
9
10
11
//两者一起用一下记忆:
int main()
{
char buf[1024];
fgets(buf, sizeof(buf), stdin);//从标准输入流输入
fputs(buf, stdout);//从标准输出流输出

//可变为
gets_s(buf);
puts(buf);
}

fscanf和fprintf使用记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct str
{
int n;
char a[100];
char b;
};

int main()
{
struct str s={0 };
fscanf(stdin, "%d %s %c", &s.n, &s.a, &s.b);
fprintf(stdout, "%d %s %c", s.n, s.a, s.b);
return 0;
}

sprintf和sscanf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct str
{
int n;
char a[100];
char b;
};

int main()
{
struct str s={100,"cl",'c'};
struct str tmp= { 0 };
char buf[1024];
sprintf(buf, "%d %s %c", s.n, s.a, s.b);
//把s里的数据转化为字符串,存到buf
sscanf(buf, "%d %s %c", &tmp.n, &tmp.a, &tmp.b);
//把buf里的数据转化为tmp里的数据

return 0;
}

8.文件的随机读写 fseek,ftell,rewind

fseek

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
return 0;
}
//1.定位文件指针
fseek(pf, -2, SEEK_END);
//2.读取文件
int ch = fgetc(pf);
printf("%c", ch);
}

ftell

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
return 0;
}
//1.定位文件指针
fseek(pf, -2, SEEK_END);
int pos = ftell(pf);//求出偏移量
printf("%d", pos);
}

rewind

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
return 0;
}
//1.定位文件指针
fseek(pf, -2, SEEK_END);
int pos = ftell(pf);//求出偏移量
rewind(pf);//返回起始位置
printf("%d", pos);
}

9.文件结束判定

1
2
feof(pf);
一般用在文件读完时判断是否是文件结尾

链表

简介

1
对于链表,其实就是把结构体一个一个链起来,利用struct*next来解决;

头插法

很简单的一种创建链表的方式
下面展示效果
单独效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct stu* createlink()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
int n;
scanf("%d", &n);
int i;
for (i = 0; i < n; i++)
{
struct stu* p = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", p->name, p->num, &p->score);
p->next = h->next;
h->next = p;
}
return h; //头插法
}

在程序中效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
struct stu
{
char name[10];
char num[10];
int score;
struct stu* next;
};
struct stu* createlink()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
int n;
scanf("%d", &n);
int i;
for (i = 0; i < n; i++)
{
struct stu* p = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", p->name, p->num, &p->score);
p->next = h->next;
h->next = p;
}
return h; //头插法
}
void printlink(struct stu* h)
{
h = h->next;
while (h != NULL)
{
printf("%s %s %d\n", h->name, h->num, h->score);
h = h->next;
}
}
int main()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
h = createlink();
printlink(h);
free(h);
h = NULL;
return 0;
}

尾插法

单独效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

struct stu* createlink()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
struct stu*r = h;
int n,i;
scanf("%d", &n);
for (i = 0; i < n; i++)
{
struct stu* p = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", p->name, p->num, &p->score);
r->next = p;
p->next = NULL;
r = p;
} //尾插法
return h;
}

程序效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
struct stu
{
char name[10];
char num[10];
int score;
struct stu* next;
};
struct stu* createlink()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
struct stu*r = h;
int n,i;
scanf("%d", &n);
for (i = 0; i < n; i++)
{
struct stu* p = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", p->name, p->num, &p->score);
r->next = p;
p->next = NULL;
r = p;
} //尾插法
return h;
}
void printlink(struct stu* h)
{
h = h->next;
while (h != NULL)
{
printf("%s %s %d\n", h->name, h->num, h->score);
h = h->next;
}
}
int main()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
h = createlink();
printlink(h);
free(h);
h = NULL;
return 0;
}

利用前趋结点来插入数据

单独效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void insert(struct stu* h)
{
struct stu* x = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", x->name, x->num, &x->score);
struct stu* p, *q;
q = h;
p = h->next;
while (p != NULL && x->score>p->score)
//一直找,直到找到x在q和p之间
{
q = p;
p = p->next;
}
x->next = p;
q->next = x;
}

程序效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
struct stu
{
char name[10];
char num[10];
int score;
struct stu* next;
};
struct stu* createlink()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
int n;
scanf("%d", &n);
int i;
for (i = 0; i < n; i++)
{
struct stu* p = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", p->name, p->num, &p->score);
p->next = h->next;
h->next = p;
}
return h; //头插法
}
void insert(struct stu* h)
{
struct stu* x = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", x->name, x->num, &x->score);
struct stu* p, *q;
q = h;
p = h->next;
while (p != NULL && x->score>p->score)
{
q = p;
p = p->next;
}
x->next = p;
q->next = x;
}
void printlink(struct stu* h)
{
h = h->next;
while (h != NULL)
{
printf("%s %s %d\n", h->name, h->num, h->score);
h = h->next;
}
}
int main()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
h = createlink();
insert(h);
printlink(h);
free(h);
h = NULL;
return 0;
}

利用插入数据来进行链表排序

单独效果
此处第六行用此图片进行解释,其大意就是将后面的所有东西放到h那条链表中
图片解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void sort(struct stu* h)
{
struct stu* p, * q;
if (h->next != NULL)
{
p = h->next->next;
h->next->next = NULL;
while (p != NULL)
{
q = p;
p = p->next;
insert(h, q);
}
}
}

程序效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
struct stu
{
char name[10];
char num[10];
int score;
struct stu* next;
};
struct stu* createlink()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
int n;
scanf("%d", &n);
int i;
for (i = 0; i < n; i++)
{
struct stu* p = (struct stu*)malloc(sizeof(struct stu));
scanf("%s%s%d", p->name, p->num, &p->score);
p->next = h->next;
h->next = p;
}
return h; //头插法
}
void insert(struct stu* h,struct stu*x)
{
struct stu* p, *q;
q = h;
p = h->next;
while (p != NULL && x->score>p->score)
{
q = p;
p = p->next;
}
x->next = p;
q->next = x;
}
void sort(struct stu* h)
{
struct stu* p, * q;
if (h->next != NULL)
{
p = h->next->next;
h->next->next = NULL;
while (p != NULL)
{
q = p;
p = p->next;
insert(h, q);
}
}
}
void printlink(struct stu* h)
{
h = h->next;
while (h != NULL)
{
printf("%s %s %d\n", h->name, h->num, h->score);
h = h->next;
}
}
int main()
{
struct stu* h = (struct stu*)malloc(sizeof(struct stu));
h->next = NULL;
h = createlink();
sort(h);
printlink(h);
free(h);
h = NULL;
return 0;
}

查找数据

1
2
3
4
5
6
7
8
9
10
11
12
13
struct stu* search(struct stu* h, char x[])
{
stu* p = h->next;
while (p != NULL)
{
if (strcmp(p->num, x) == 0)
{
return p;
}
p = p->next;
}
return NULL;
}

删除数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void delete_d(struct stu* h, char x[])
{
stu* q = h;
stu* p = h->next;
while (p != NULL)
{
if (strcmp(p->num, x) == 0)
{
q->next = p->next;
free(p);
break;
}
q = p;
p = p->next;
}
}