当前位置:网站首页>Simple C language address book
Simple C language address book
2022-06-11 14:42:00 【qq_ forty-two million one hundred and twenty thousand eight hun】
C Language address book
List of articles
- C Language address book
- The main function
- Architecture design
- Source code
- Code analysis
- Linked list implementation and data structure definition
- Implementation of the functions of the data structure operation interface layer
- Implementation of business logic functions
- Interface layer implementation of file saving and loading
- The business logic layer implementation of file saving and loading
- Experience
The main function
- Add a person
- Print shows all people
- Delete a person
- Find a person
- Save the file
- Load the file
Architecture design
I think for me, a rookie who doesn't have an overall design, this design method really brightens my eyes .
The main design is to divide the program into three supporting layers 、 Interface layer and business logic layer , Each layer will only use the functions provided by the layer below it , For example, business layer functions will call interface layer functions , The functions of the interface layer call the functions of the support layer , It will not let the business layer directly call the functions of the support layer .

Source code
/* * 2022 year 6 month 7 Japan 10:29:41 * Address book management system * Three layers : Support layer 、 The interface layer 、 Business logic layer * Two way linked list as data structure * * */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Using macro definition to make program code more intuitive
#define NAME_LENGTH 16
#define PHONE_LENGTH 32
#define BUFFER_LENGTH 128
// The minimum value for reading a line of data from a file is 5, namely name:
#define MIN_TOKEN_LENGTH 5
// For future improvements , The function change of output information can be modified as a whole as long as it is modified here
#define INFO printf
// Use macro definition to realize the operation of support layer , Note that the macro definition is a direct replacement
// take item Insert list List the head
//LIST_INSERT(ps, *ppeople) When here list yes *pperson, The type is (struct person *) Direct replacement
// To list Adding parentheses is equivalent to (*pperson)
#define LIST_INSERT(item, list) do{
\ item->prev = NULL; \ item->next = list; \ if((list) != NULL) (list)->prev = item; \ (list) = item; \ }while(0)
#define LIST_REMOVE(item ,list) do{
\ if(item->prev != NULL) item->prev->next = item->next; \ if(item->next != NULL) item->next->prev = item->prev; \ if(item == list) list = item->next; \ item->prev = item->next = NULL; \ }while(0) // Only once
struct person
{
char name[NAME_LENGTH];
char phone[PHONE_LENGTH];
struct person *next;
struct person *prev; // The design is a two-way linked list , Easy to delete nodes
};
// Address book class , It is equivalent to a management class
struct contacts
{
struct person *people; // Point to the address list
int count;
};
enum {
OPER_INSERT = 1,
OPER_PRINT,
OPER_DELETE,
OPER_SEARCH,
OPER_SAVE,
OPER_LOAD
};
//define interface , The interface layer will use the functions of the support layer
int person_insert(struct person **ppeople, struct person *ps)
{
if(ps == NULL) return -1;
LIST_INSERT(ps, *ppeople);
return 0;
}
int person_delete(struct person **ppeople, struct person *ps)
{
if(ps == NULL) return -1;
LIST_REMOVE(ps, *ppeople);
return 0;
}
struct person * person_search(struct person *people, const char *name)
{
struct person *item = NULL;
for(item = people; item != NULL; item = item->next)
{
//strcmp Equal to 0
if(!strcmp(name, item->name))
break;
}
return item;
}
int person_traverse(struct person *people)
{
struct person *item = NULL;
for(item = people; item != NULL;item = item->next)
{
INFO("name: %s,phone: %s\n", item->name, item->phone);
}
return 0; // Successfully returns 0
}
// Put the address book ( Linked list )people Save information to file filename in
int save_file(struct person *people, const char *filename)
{
FILE *fp = fopen(filename, "w");
if(fp == NULL) return -1;
struct person *item = NULL;
for(item = people; item != NULL; item = item->next)
{
fprintf(fp, "name: %s, phone: %s\n", item->name, item->phone);
fflush(fp); // Refresh content to disk , The previous content is to write to the buffer ( Memory ) in
}
fclose(fp);
}
//@length: by buffer Actual length ( A contact's record )
int parser_token(char *buffer, int length, char *name, char *phone)
{
if(buffer == NULL) return -1;
if(length < MIN_TOKEN_LENGTH) return -2;
int i = 0, j = 0, status = 0;
// The obtained data content is in the form of name: wangbojing,telephone: 15889650380
// Resolve the name
// Adopt the method of state machine
for(i = 0; buffer[i] != ',';++i)
{
// The state will change after encountering a space , After that, it's the name we want
if(buffer[i] == ' ')
{
status = 1;
}
else if(status == 1)
{
name[j++] = buffer[i];
}
}
status = 0;
j = 0;
for(;i < length; ++i)
{
if(buffer[i] == ' ')
{
status = 1;
}
else if(status == 1)
{
phone[j++] = buffer[i];
}
}
INFO("file token : %s ---- %s\n", name, phone);
return 0;
}
// take filename The data read from the file is written to ( Load into ) To the address book people in
//count:contacts Members of the object , Change the number of contacts
int load_file(struct person **ppeople, int *count,const char *filename)
{
FILE *fp = fopen(filename, "r");
if(fp == NULL)
return -1;
//fp The internal pointer loops without being at the end of the file
while(!feof(fp))
{
char buffer[BUFFER_LENGTH] = {
0};
// from fp Read length in the file referred to BUFFER_LENGTH Data to buffer in , Stop at line breaks or endings
fgets(buffer, BUFFER_LENGTH, fp);
int length = strlen(buffer);
INFO("length : %d\n", length);
//name: wangbojing,telephone: 15889650380
char name[NAME_LENGTH] = {
0};
char phone[PHONE_LENGTH] = {
0};
// Failed to parse the content , Jump out of this cycle
if(0 != parser_token(buffer, length, name, phone))
{
continue;
}
// Insert address book ( Linked list )
struct person *p = (struct person*)malloc(sizeof(struct person));
if(p == NULL) return -2;
//memcpy() Will be copied name The front of the memory content NAME_LENGTH Byte to p->name On the memory address .
memcpy(p->name, name, NAME_LENGTH);
memcpy(p->phone, phone, PHONE_LENGTH);
person_insert(ppeople, p);
(*count)++;
}
fclose(fp);
return 0;
}
//define interface end
// Implementation of business logic
int insert_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
struct person *p = (struct person*)malloc(sizeof(struct person));
memset(p, 0x00, sizeof(struct person));
if(p == NULL)
return -2;
//name
INFO("Please input name: \n");
scanf("%s", p->name);
//phone
INFO("Please input phone: \n");
scanf("%s", p->phone);
//add people
// If cts->people by NULL, What we want to change is cts->people Value , So you have to send the address
// so person_insert The first parameter here must be a second level pointer
if(0 != person_insert(&cts->people, p))
{
free(p);
return -3;
}
cts->count++; // Number of contacts updated
INFO("insert success!\n");
return 0;
}
int print_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
//cts->people
person_traverse(cts->people);
return 0;
}
int delete_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
//name
INFO("Please input name: \n");
char name[NAME_LENGTH] = {
0};
scanf("%s",name);
//person
// Find and then delete
struct person *ps = person_search(cts->people, name);
if(ps == NULL)
{
INFO("Person don't exist!\n");
return -2;
}
//delete
// If you delete the last element or the first element ( First element )
// Change people Value , So this parameter needs to be passed to the address
// So the parameter type is a two-level pointer struct person **
person_delete(&cts->people, ps);
free(ps);
INFO("Delete success!\n");
return 0;
}
int search_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
//name
INFO("Please input name: \n");
char name[NAME_LENGTH] = {
0};
scanf("%s",name);
//person
struct person *ps = person_search(cts->people, name);
if(ps == NULL)
{
INFO("Person don't exist!\n");
return -2;
}
INFO("name:%s, phone: %s\n",ps->name, ps->phone);
return 0;
}
int save_entry(struct contacts * cts)
{
if(cts == NULL) return -1;
INFO("Please input save filename:\n");
char filename[NAME_LENGTH] = {
0};
scanf("%s", filename);
save_file(cts->people, filename);
}
int load_entry(struct contacts * cts)
{
if(cts == NULL) return -1;
INFO("Please input load filename:\n");
char filename[NAME_LENGTH] = {
0};
scanf("%s", filename);
load_file(&cts->people, &cts->count, filename);
}
void menu_info()
{
INFO("\n******************************************************\n");
INFO("*****1.Add Person\t\t2.Print Person *******\n");
INFO("*****3.Del Person\t\t4.Search Person ******\n");
INFO("*****5.Save Person\t\t6.Load Person ********\n");
INFO("*****Other Key for Exiting Program *******************\n");
INFO("\n******************************************************\n");
}
int main()
{
struct contacts *cts = (struct contacts*)malloc(sizeof(struct contacts));
if(cts == NULL) return -1;
// Initialize structure
memset(cts, 0x00, sizeof(struct contacts));
while(1)
{
menu_info();
int select = 0;
scanf("%d", &select);
switch(select)
{
// Call the functions of the business logic layer
case OPER_INSERT:
insert_entry(cts);
break;
case OPER_PRINT:
print_entry(cts);
break;
case OPER_DELETE:
delete_entry(cts);
break;
case OPER_SEARCH:
search_entry(cts);
break;
case OPER_SAVE:
save_entry(cts);
break;
case OPER_LOAD:
load_entry(cts);
break;
default:
goto exit;
}
}
exit:
free(cts);
return 0;
}
Code analysis
Linked list implementation and data structure definition
This program uses a two-way linked list to store the address book :
struct person
{
char name[NAME_LENGTH];
char phone[PHONE_LENGTH];
struct person *next;
struct person *prev; // The design is a two-way linked list , Easy to delete nodes
};
Address book management class , Easy to operate
struct contacts
{
struct person *people; // Point to the address list
int count;
};
Implement the header insertion and deletion of the linked list in the interface layer , Note that the macro definition is a direct text substitution , Pay attention to brackets , Prevent problems caused by priorities .
#define LIST_INSERT(item, list) do{
\ item->prev = NULL; \ item->next = list; \ if((list) != NULL) (list)->prev = item; \ (list) = item; \ }while(0)
#define LIST_REMOVE(item ,list) do{
\ if(item->prev != NULL) item->prev->next = item->next; \ if(item->next != NULL) item->next->prev = item->prev; \ if(item == list) list = item->next; \ item->prev = item->next = NULL; \ }while(0) // Only once
Implementation of the functions of the data structure operation interface layer
//define interface , The interface layer will use the functions of the support layer
// The reason why ppeople The second level pointer is used because , When the incoming if is NULL, That is, when the node is inserted for the first time
// We need to change the value of its first level pointer .
int person_insert(struct person **ppeople, struct person *ps)
{
if(ps == NULL) return -1;
LIST_INSERT(ps, *ppeople);
return 0;
}
// If you delete last element , Then the pointer to the linked list ( Class A ) To be changed to NULL, So pass the secondary pointer
int person_delete(struct person **ppeople, struct person *ps)
{
if(ps == NULL) return -1;
LIST_REMOVE(ps, *ppeople);
return 0;
}
struct person * person_search(struct person *people, const char *name)
{
struct person *item = NULL;
for(item = people; item != NULL; item = item->next)
{
//strcmp Equal to 0
if(!strcmp(name, item->name))
break;
}
return item;
}
int person_traverse(struct person *people)
{
struct person *item = NULL;
for(item = people; item != NULL;item = item->next)
{
// here INFO Is a macro definition
INFO("name: %s,phone: %s\n", item->name, item->phone);
}
return 0; // Successfully returns 0
}
Implementation of business logic functions
Define different operations as anonymous enumerations instead of directly using numbers
enum {
OPER_INSERT = 1,
OPER_PRINT,
OPER_DELETE,
OPER_SEARCH,
OPER_SAVE,
OPER_LOAD
};
main Function provides users with the display and selection of functions :
void menu_info()
{
INFO("\n******************************************************\n");
INFO("*****1.Add Person\t\t2.Print Person *******\n");
INFO("*****3.Del Person\t\t4.Search Person ******\n");
INFO("*****5.Save Person\t\t6.Load Person ********\n");
INFO("*****Other Key for Exiting Program *******************\n");
INFO("\n******************************************************\n");
}
int main()
{
struct contacts *cts = (struct contacts*)malloc(sizeof(struct contacts));
if(cts == NULL) return -1;
// Initialize structure
memset(cts, 0x00, sizeof(struct contacts));
while(1)
{
menu_info();
int select = 0;
scanf("%d", &select);
switch(select)
{
// Call the functions of the business logic layer
case OPER_INSERT:
insert_entry(cts);
break;
case OPER_PRINT:
print_entry(cts);
break;
case OPER_DELETE:
delete_entry(cts);
break;
case OPER_SEARCH:
search_entry(cts);
break;
case OPER_SAVE:
save_entry(cts);
break;
case OPER_LOAD:
load_entry(cts);
break;
default:
goto exit;
}
}
exit:
free(cts);
return 0;
}
Function implementation of business logic layer
// Implementation of business logic
int insert_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
struct person *p = (struct person*)malloc(sizeof(struct person));
memset(p, 0x00, sizeof(struct person));
if(p == NULL)
return -2;
//name
INFO("Please input name: \n");
scanf("%s", p->name);
//phone
INFO("Please input phone: \n");
scanf("%s", p->phone);
//add people
// If cts->people by NULL, What we want to change is cts->people Value , So you have to send the address
// so person_insert The first parameter here must be a second level pointer
if(0 != person_insert(&cts->people, p))
{
free(p);
return -3;
}
cts->count++; // Number of contacts updated
INFO("insert success!\n");
return 0;
}
int print_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
//cts->people
person_traverse(cts->people);
return 0;
}
int delete_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
//name
INFO("Please input name: \n");
char name[NAME_LENGTH] = {
0};
scanf("%s",name);
//person
// Find and then delete
struct person *ps = person_search(cts->people, name);
if(ps == NULL)
{
INFO("Person don't exist!\n");
return -2;
}
//delete
// If you delete the last element or the first element ( First element )
// Change people Value , So this parameter needs to be passed to the address
// So the parameter type is a two-level pointer struct person **
person_delete(&cts->people, ps);
free(ps);
INFO("Delete success!\n");
return 0;
}
int search_entry(struct contacts *cts)
{
if(cts == NULL) return -1;
//name
INFO("Please input name: \n");
char name[NAME_LENGTH] = {
0};
scanf("%s",name);
//person
struct person *ps = person_search(cts->people, name);
if(ps == NULL)
{
INFO("Person don't exist!\n");
return -2;
}
INFO("name:%s, phone: %s\n",ps->name, ps->phone);
return 0;
}
Interface layer implementation of file saving and loading
Saving is to store the data on the linked list to a disk file , Loading is to read the contact data from the disk file and insert it into the linked list
File saving interface layer implementation
// Put the address book ( Linked list )people Save information to file filename in
int save_file(struct person *people, const char *filename)
{
FILE *fp = fopen(filename, "w");
if(fp == NULL) return -1;
struct person *item = NULL;
for(item = people; item != NULL; item = item->next)
{
fprintf(fp, "name: %s, phone: %s\n", item->name, item->phone);
fflush(fp); // Refresh content to disk , The previous content was just written to the buffer ( Memory ) in
}
fclose(fp);
}
File loading interface layer implementation
here , We need to parse the name and phone number from the file , What we have on disk is shaped like :
name: wangbojing,telephone: 15889650380
According to this format ,
We can parse the name and phone number into two parts through commas, namely
name: wangbojingandtelephone: 15889650380Then according to the finite state machine , The initial state is 0, When a space is encountered, the status changes to 1, The non space characters encountered later are names
The same is true of telephone number resolution .
//@length: by buffer Actual length ( A contact's record )
int parser_token(char *buffer, int length, char *name, char *phone)
{
if(buffer == NULL) return -1;
if(length < MIN_TOKEN_LENGTH) return -2;
int i = 0, j = 0, status = 0;
// Resolve the name
// Adopt the method of state machine
for(i = 0; buffer[i] != ',';++i)
{
// The state will change after encountering a space , After that, it's the name we want
if(buffer[i] == ' ')
{
status = 1;
}
else if(status == 1)
{
name[j++] = buffer[i];
}
}
status = 0;
j = 0;
for(;i < length; ++i)
{
if(buffer[i] == ' ')
{
status = 1;
}
else if(status == 1)
{
phone[j++] = buffer[i];
}
}
INFO("file token : %s ---- %s\n", name, phone);
return 0;
}
Interface layer implementation of loading file :
// take filename The data read from the file is written to ( Load into ) To the address book people in
//count:contacts Members of the object , Change the number of contacts
int load_file(struct person **ppeople, int *count,const char *filename)
{
FILE *fp = fopen(filename, "r");
if(fp == NULL)
return -1;
//fp The internal pointer loops without being at the end of the file
while(!feof(fp))
{
char buffer[BUFFER_LENGTH] = {
0};
// from fp Read length in the file referred to BUFFER_LENGTH Data to buffer in , Stop at line breaks or endings
fgets(buffer, BUFFER_LENGTH, fp);
int length = strlen(buffer);
INFO("length : %d\n", length);
//name: wangbojing,telephone: 15889650380
char name[NAME_LENGTH] = {
0};
char phone[PHONE_LENGTH] = {
0};
// Failed to parse the content , Jump out of this cycle
if(0 != parser_token(buffer, length, name, phone))
{
continue;
}
// Insert address book ( Linked list )
struct person *p = (struct person*)malloc(sizeof(struct person));
if(p == NULL) return -2;
//memcpy() Will be copied name The front of the memory content NAME_LENGTH Byte to p->name On the memory address .
memcpy(p->name, name, NAME_LENGTH);
memcpy(p->phone, phone, PHONE_LENGTH);
person_insert(ppeople, p);
(*count)++;
}
fclose(fp);
return 0;
}
The business logic layer implementation of file saving and loading
int save_entry(struct contacts * cts)
{
if(cts == NULL) return -1;
INFO("Please input save filename:\n");
char filename[NAME_LENGTH] = {
0};
scanf("%s", filename);
save_file(cts->people, filename);
}
int load_entry(struct contacts * cts)
{
if(cts == NULL) return -1;
INFO("Please input load filename:\n");
char filename[NAME_LENGTH] = {
0};
scanf("%s", filename);
load_file(&cts->people, &cts->count, filename);
}
Experience
This program function makes the design very clear through the three-tier design method , At the same time, macro definition is used to enhance readability , For me, it has deepened some experience of program development , Broaden your horizons .
边栏推荐
- 2022-2028 near infrared (NIR) analyzer Market Status and future development trend in the world and China
- . Net C Foundation (6): namespace - scope with name
- How to manually package your own projects
- Live800:智能客服提升客户体验的几种方式
- In depth research and analysis report on global and Chinese oleoresin product market
- In depth research and analysis report on global and Chinese high purity molybdenum market
- 02 Tekton Pipeline
- 01Tekton 初探
- Hashicopy之nomad应用编排方案05(访问web页面)
- 多云安全合规扫描平台之RiskScanner
猜你喜欢

Live800:智能客服提升客户体验的几种方式

. Net C Foundation (6): namespace - scope with name

Online "comment explicit" function, TME's wave point music cultivates music "private plots"

What's a good gift for the goddess Festival on March 8? Goddess Day gift sharing

mysql创建表出错1067 - Invalid default value for ‘update_time‘

Raspberry school literacy

【Try to Hack】URL

C # - how to add and read appsetting in the console application JSON file

Live800: several ways for intelligent customer service to improve customer experience

2022年全国最新消防设施操作员(初级消防设施操作员)题库及答案
随机推荐
【公开课预告】:MXPlayer OTT音视频转码实践和优化
Webgl programming guide learning (0)
In depth research and analysis report on global and Chinese content audit market
高通WLAN框架学习(29)-- 6GHz 概述
Architectural concept exploration: Taking the development of card games as an example
In depth research and analysis report on global and Chinese oleoresin product market
Hashicopy之nomad应用编排方案03(运行一个job)
树莓派知识大扫盲
PowerShell chief architect: I used my spare time to develop projects, but I was demoted by Microsoft because of my excellent performance
Taking log4j as an example, how to evaluate and classify security risks
深度剖析「圈組」關系系統設計 | 「圈組」技術系列文章
Repository Manager之Nexus
01discussion on Tekton
在微服务架构中管理技术债务
Guess numbers games
Raspberry pie obtains the function of network installation system without the help of other devices
Ali, tell me about the application scenarios of message oriented middleware?
架构概念探索:以开发纸牌游戏为例
[team learning] task06:for, if, and while
Leetcode 1963. 使字符串平衡的最小交换次数(学习)