本次通訊錄的代碼已經放到我的Gitee倉庫中,感興趣的小伙伴可以去看看
靜態通訊錄
在我們學習完C語言的結構體、指針以及動態內存管理之后,我們就可以實現一些有意思的小項目了,通過這些小項目可以加深我們對于相關知識的理解。
靜態通訊錄主要要求有
- 靜態大小,可以記錄10個人的信息(大小自己定)
- 記錄的信息如下:名字、性別、年齡、電話、住址
- 可以實現聯系人的增刪查改
為了方便代碼的管理和維護,我們分文件實現以上的要求
- contact.h 用于聲明相關的接口
- contact.c 用于實現相關的接口
- test.c 用于測試相關的接口
contact.h
在contact.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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
//首先引入需要用到的頭文件 #include<stdio.h> #include<stdlib.h> #include<string.h> //確定每一個聯系人名字、電話等信息的范圍大小 #define MAX_NAME 10 #define MAX_PHONE 20 #define MAX_ADDR 25 // 確定通訊錄的總大小 #define MAX_CAPACITY 10 //由于每一個聯系人都有多個信息,因此需要定義一個結構體類型來管理 //定義聯系人相關信息的結構體 typedef struct PeoInfo { char name[MAX_NAME]; char sex; int age; char phone[MAX_PHONE]; char address[MAX_ADDR]; }peo; //通訊錄內包含多個成員,因此也需要統一管理,所以還是使用結構體 //定義一個通訊錄結構體,管理通訊錄和記錄有效聯系人個數信息 typedef struct Contact { peo data[MAX_CAPACITY]; //這里是一個數組,數組的每一個元素都是一個結構體 int size; }con; //------------------------------------------------------ //以下是相關接口的聲明 //菜單接口 void menu(); //對結構體變量進行初始化 void InitContact(con* con); //打印通訊錄信息 void Print(con* con); //實現增加聯系人的接口 void AddContact(con* con); //實現刪除聯系人的接口 void DelContact(con* con); //實現查找聯系人的接口 void SearchContact(con* con); //實現修改聯系人的接口 void ModifyContact(con* con); |
contact.c
contact.c是整個項目的關鍵,需要對相關接口進行定義
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
//通訊錄各個接口的實現 //首先引入.h文件 #include"Contact.h" //菜單接口 void menu() { printf ( "*******************************\n" ); printf ( "********靜態簡易通訊錄*********\n" ); printf ( "******* 0.退出通訊錄 ******\n" ); printf ( "******* 1.增加聯系人 ******\n" ); printf ( "******* 2.刪除聯系人 ******\n" ); printf ( "******* 3.查找聯系人 ******\n" ); printf ( "******* 4.修改聯系人 ******\n" ); printf ( "******* 5.打印聯系人 ******\n" ); printf ( "*******************************\n" ); printf ( "\n" ); } //對結構體變量進行初始化 void InitContact(con* con) { //結構體的初始化一般用memset //我們首先讓通訊錄結構體變量的數組一開始為0 memset (con->data, 0, sizeof (con->data)); con->size = 0; //同時由于此時一個聯系人的信息都沒有,所以size也是0 } //打印通訊錄信息 void Print(con* con){ int i = 0; if (con->size == 0) { printf ( "暫無可打印信息\n" ); return ; } printf ( "name\tsex\tage\tphone\taddress\n" ); for (i = 0; i < con->size; i++) { printf ( "%s\t%c\t%d\t%s\t%s\n" , con->data[i].name, con->data[i].sex, con->data[i].age, con->data[i].phone, con->data[i].address); } } //實現增加聯系人的接口 void AddContact(con* con) { if (con->size == MAX_CAPACITY) { printf ( "容量已滿,無法增加\n" ); return ; } printf ( "請輸入姓名:\n" ); scanf ( "%s" , con->data[con->size].name); getchar (); printf ( "請選擇性別:(m表示男,w表示女)\n" ); scanf ( "%c" , &(con->data[con->size].sex)); printf ( "請輸入年齡:\n" ); scanf ( "%d" , &(con->data[con->size].age)); printf ( "請輸入手機號碼:\n" ); scanf ( "%s" , con->data[con->size].phone); printf ( "請輸入住址:\n" ); scanf ( "%s" , con->data[con->size].address); con->size++; } //實現刪除聯系人的接口 void DelContact(con* con) { if (con->size == 0) { printf ( "暫無可以刪除的信息" ); return ; } printf ( "請輸入你要刪除的聯系人的姓名:\n" ); char name[MAX_NAME] = {0}; scanf ( "%s" , name); int i = 0; for (i = 0; i < con->size; i++) { if ( strcmp (name, (con->data)[i].name) == 0) { int j = 0; for (j = i; j < con->size - 1; j++) { memmove (&(con->data[j]), &(con->data[j + 1]), sizeof (con->data[0])); } con->size--; return ; } } printf ( "你輸入的聯系人不存在\n" ); } //實現查找聯系人的接口 void SearchContact(con* con) { if (con->size == 0) { printf ( "暫無查找的信息" ); return ; } printf ( "請輸入你要查找的聯系人的姓名:\n" ); char name[MAX_NAME] = { 0 }; scanf ( "%s" , name); int i = 0; for (i = 0; i < con->size; i++) { if ( strcmp (name, (con->data)[i].name) == 0) { printf ( "%s\t%c\t%d\t%s\t%s\n" , con->data[i].name, con->data[i].sex, con->data[i].age, con->data[i].phone, con->data[i].address); return ; } } printf ( "你想要查找的聯系人不存在\n" ); } //實現修改聯系人的接口 void ModifyContact(con* con) { if (con->size == 0) { printf ( "暫無可以修改的信息" ); return ; } printf ( "請輸入你要修改的聯系人的姓名:\n" ); char name[MAX_NAME] = { 0 }; scanf ( "%s" , name); int i = 0; for (i = 0; i < con->size; i++) { if ( strcmp (name, (con->data)[i].name) == 0) { printf ( "請重新輸入姓名:\n" ); scanf ( "%s" , con->data[i].name); getchar (); printf ( "請重新選擇性別:(m表示男,w表示女)\n" ); scanf ( "%c" , &(con->data[i].sex)); printf ( "請重新輸入年齡:\n" ); scanf ( "%d" , &(con->data[i].age)); printf ( "請重新輸入手機號碼:\n" ); scanf ( "%s" , con->data[i].phone); printf ( "請重新輸入住址:\n" ); scanf ( "%s" , con->data[i].address); return ; } } printf ( "你想要修改的聯系人不存在\n" ); } |
提示
我們在實現接口的時候,如果形參傳入的是指針,一般都需要先判斷一下傳入的指針是否為空指針,以免造成非法訪問,但是由于我的疏忽,就沒有寫上去了!
test.c
test.c就是用來測試相關接口的文件,可以根據自己的想法來設定
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
|
#include"Contact.h" int main() { //創建結構體并且初始化 con c; InitContact(&c); menu(); int input = 0; while (1) { printf ( "請輸入你的選擇:\n" ); scanf ( "%d" , &input); switch (input) { case 1: AddContact(&c); break ; case 2: DelContact(&c); break ; case 3: SearchContact(&c); break ; case 4: ModifyContact(&c); break ; case 5: Print(&c); break ; case 0: printf ( "退出通訊錄\n" ); break ; default : printf ( "你的輸入有誤,請重新選擇\n" ); break ; } if (input == 0) { break ; } } return 0; } |
動態通訊錄
靜態通訊錄有一個缺點,那就是通訊錄的大小,也就是只能存儲的聯系人是要求確定大小的,大小給多了浪費空間,給少了又不夠用。
動態通訊錄就是通過動態內存管理的函數來實現動態開辟空間大小,以滿足需要的。
contact.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
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
|
//動態版本通訊錄的實現 #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX_NAME 15 #define MAX_PHONE 15 #define MAX_ADDR 25 //給定通訊錄默認大小為5,不夠可以增容 #define DefaultSize 5 //聯系人結構體的聲明 typedef struct PeoInfo { char name[MAX_NAME]; char sex; short age; char phone[MAX_PHONE]; char addr[MAX_ADDR]; }peo; //通訊錄結構體的聲明 typedef struct Contact { peo* p; //我們通過指針的方式來管理聯系人數組 int capacity; int size; }con; //菜單函數 void menu(); //初始化通訊錄 void InitCon(con* c); //銷毀通訊錄 void DestoryCon(con* c); //檢查容量的接口 void CheckCapacity(con* c); //打印聯系人信息 void Print(con* c); //聯系人的增加 void AddCon(con* c); //聯系人的刪除 void DelCon(con* c); //聯系人的查找 void SearchCon(con* c); //聯系人的修改 void ModifyCon(con* c); //------------------------------------------- //下面是我通過快排的原理,手寫的快排來實現一下通過聯系人名字和年齡排序的接口 //通過名字來排序 void SortByname(con* c); //通過年齡來排序 void SortByage(con* c); void Swap( char * p1, char * p2, int width); void QSort( void * p, int num, int width, int (*cmp)( const void * , const void * )); int cmpbyname( const void * p1, const void * p2); int cmpbyage( const void * p1, const void * p2); |
contact.c
關鍵接口的實現和靜態通訊錄的大同小異,只不過我們需要多定義一個檢查空間的接口
每次增加聯系人的時候,就調用這個接口,做到滿了就增容
其中增容接口使用的時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
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
#include"contact.h" //菜單函數 void menu() { printf ( "******************************************\n" ); printf ( "************* 動態版通訊錄 ***********\n" ); printf ( "************* 1.增加聯系人 ***********\n" ); printf ( "************* 2.刪除聯系人 ***********\n" ); printf ( "************* 3.查找聯系人 ***********\n" ); printf ( "************* 4.修改聯系人 ***********\n" ); printf ( "************* 5.按名字排序 ***********\n" ); printf ( "************* 6.按年齡排序 ***********\n" ); printf ( "************* 7.打印聯系人 ***********\n" ); printf ( "************* 0.退出通訊錄 ***********\n" ); printf ( "******************************************\n" ); } //初始化通訊錄 void InitCon(con* c) { //這里也可以用relloc函數來初始化,這樣的話就會有初始值 c->p = (con*) malloc (DefaultSize * sizeof (peo)); c->capacity = DefaultSize; c->size = 0; } //銷毀通訊錄 void DestoryCon(con* c) { free (c->p); c->p = NULL; c->capacity = 0; c->size = 0; } //檢查容量的接口 void CheckCapacity(con* c) { if (c->capacity == c->size) { //每次增容二倍 peo* tmp = (peo*) realloc (c->p, 2 * (c->capacity) * sizeof (peo)); if (tmp != NULL) { c->p = tmp; c->capacity = 2 * c->capacity; printf ( "增容成功\n" ); } else { printf ( "增容失敗\n" ); exit (1); } } } //打印聯系人信息 void Print(con* c) { if (c->size == 0) { printf ( "暫無可以打印的信息\n" ); return ; } printf ( "name\tsex\tage\tphone\taddress\n" ); int i = 0; for (i = 0; i < c->size; i++) { printf ( "%s\t%c\t%d\t%s\t%s\n" , c->p[i].name, c->p[i].sex, c->p[i].age, c->p[i].phone, c->p[i].addr); } } //聯系人的增加 void AddCon(con* c) { //每一次增加聯系人都要先檢查容量是否足夠 CheckCapacity(c); printf ( "請輸入名字:>\n" ); scanf ( "%s" , c->p[c->size].name); getchar (); printf ( "請輸入性別:>(m表示男,w表示女)\n" ); scanf ( "%c" , &(c->p[c->size].sex)); printf ( "請輸入年齡:>\n" ); scanf ( "%d" , &(c->p[c->size].age)); printf ( "請輸入電話:>\n" ); scanf ( "%s" , c->p[c->size].phone); printf ( "請輸入地址:>\n" ); scanf ( "%s" , c->p[c->size].addr); c->size++; printf ( "添加成功\n" ); } //聯系人的刪除 void DelCon(con* c) { printf ( "請輸入你想要刪除的聯系人的名字\n" ); char name[MAX_NAME]; scanf ( "%s" , name); int i = 0; for (i = 0; i < c->size; i++) { if ( strcmp (name, c->p[i].name) == 0) { int j = i; for (j = i; j < c->size - 1; j++) { memmove (&(c->p[j]), &(c->p[j + 1]), sizeof (c->p[0])); } c->size--; return ; } } printf ( "你想要刪除的聯系人不存在\n" ); } //聯系人的查找 void SearchCon(con* c) { printf ( "請輸入你想要查找的人的名字:\n" ); char name[MAX_NAME]; scanf ( "%s" , name); int i = 0; for (i = 0; i < c->size; i++) { if ( strcmp (name, c->p[i].name) == 0) { printf ( "%s\t%c\t%d\t%s\t%s\n" , c->p[i].name, c->p[i].sex, c->p[i].age, c->p[i].phone, c->p[i].addr); return ; } } printf ( "你想要查找的聯系人不存在\n" ); } //聯系人的修改 void ModifyCon(con* c) { printf ( "請輸入你想要修改的人的名字:\n" ); char name[MAX_NAME]; scanf ( "%s" , name); int i = 0; for (i = 0; i < c->size; i++) { if ( strcmp (name, c->p[i].name) == 0) { printf ( "請重新輸入名字:>\n" ); scanf ( "%s" , c->p[i].name); getchar (); printf ( "請重新輸入性別:>(m表示男,w表示女)\n" ); scanf ( "%c" , &(c->p[i].sex)); printf ( "請重新輸入年齡:>\n" ); scanf ( "%d" , &(c->p[i].age)); printf ( "請重新輸入電話:>\n" ); scanf ( "%s" , c->p[i].phone); printf ( "請重新輸入地址:>\n" ); scanf ( "%s" , c->p[i].addr); return ; } } printf ( "你想要修改的聯系人不存在\n" ); } //通過名字來排序 void SortByname(con* c) { QSort(c->p, c->size, sizeof (c->p[0]),cmpbyname ); } //通過年齡來排序 void SortByage(con* c) { QSort(c->p, c -> size, sizeof (c->p[0]), cmpbyage); } |
qsort.c
這是我根據快速排序的原理,手寫的快速排序
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
|
#include"contact.h" //快排的交換函數 void Swap( char * p1, char * p2, int width) { int i = 0; for (i = 0; i < width; i++) { char tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2++; } } //手寫快排來進行通訊錄排序 void QSort( void * p, int num, int width, int (*cmp)( const void *, const void *)) { int i = 0; for (i = 0; i < num - 1; i++) { int j = 0; for (j = 0; j < num - 1 - i; j++) { if (cmp(( char *)p + j * width, ( char *)p + (j + 1) * width) > 0) { Swap(( char *)p + j * width, ( char *)p + (j + 1) * width, width); } } } } int cmpbyage( const void * p1, const void * p2) { return (*(peo*)p1).age - (*(peo*)p2).age; } int cmpbyname( const void * p1, const void * p2) { return strcmp (((peo*)p1)->name,((peo*)p2)->name); } |
test.c
test.c用于測試相關的接口,可以根據自己的想法來測試
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
|
#include"contact.h" int main() { menu(); int input = 0; con c; InitCon(&c); while (1) { printf ( "請輸入你的選擇:\n" ); scanf ( "%d" , &input); switch (input) { case 1: AddCon(&c); break ; case 2: DelCon(&c); break ; case 3: SearchCon(&c); break ; case 4: ModifyCon(&c); break ; case 5: SortByname(&c); break ; case 6: SortByage(&c); break ; case 7: Print(&c); break ; case 0: printf ( "退出通訊錄\n" ); break ; } if (input == 0) { DestoryCon(&c); break ; } } return 0; } |
到此這篇關于C語言靜態與動態通訊錄的實現流程詳解的文章就介紹到這了,更多相關C語言 通訊錄內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/weixin_61021362/article/details/121113744