C语言小项目:通讯录

用C语言实现通讯录,将信息保存在文件中

项目说明:

通讯录全部采用C语言实现,用链表实现增加、删除、修改、查找等功能,还有命令解析函数(将输入分解成主命令、姓名、电话),联系人信息是保存在文件中,每次程序运行和结束时都会读取文件中的信息。

提示:

节点里定义的都是指针,增加新节点时要开辟新的内存,删除节点时要记得及时释放内存,防止内存溢出。

示例代码:

头文件:头文件中是宏定义和函数原型声明。

#ifndef _MAIN_H_
#define _MAIN_H_

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>

typedef struct node{	 //定义节点类型,采用的双向链表,删除和插入比较方便
	
	char *name;
	char *telephone;
	struct node *next;
	struct node *prior;

}NODE, *PNODE;

#define ADD 1
#define DELETE 2
#define FIND 3
#define LIST 4
#define MODIFY 5
#define QUIT 6
#define HELP 7

PNODE creat_head();//创建头结点
void display(const PNODE head);
void add(const PNODE head, char *name, char *telephone);//增加联系人
int analyse(char *buf, char *cmd, char *name, char *telephone);//解析指令
void delete(const PNODE head, char *name);//删除联系人
PNODE find(PNODE head, char *name);//查找联系人
void modify(PNODE head, char *name, char *telephone);//修改联系人
void help();//显示操作信息
int  read_list(PNODE head);//程序运行时,将保存在文件中的联系人信息读取出来
void write_list(PNODE head);//程序结束时,将链表中的联系人写入文件中保存起来

#endif

main.c文件:主要是程序的执行流程,代码简洁明了。

#include"main.h"

int main(){

	char buf[40] = {0};
	char cmd[20] = {0};
	char name[20] = {0};
	char telephone[20] = {0};

	help();
	PNODE head = creat_head();//创建头结点,不含有效信息
	read_list(head);	//将文件中保存的数据读取出来
	int i;
	while(1){
		fgets(buf, sizeof(buf), stdin);
		buf[strlen(buf) - 1] = 0;	//fgets()函数会把换行符读入,将最后一个字符置为0
		i = analyse(buf, cmd, name, telephone);	//将输入的命令解析成指令、姓名、电话号码

		//根据命令解析函数返回的值,调用不同的函数,实现不同的功能man
		switch(i){
			case ADD: add(head, name, telephone);
					break;
			case DELETE: delete(head, name);
					break;
			case FIND: find(head, name);
					break;
			case LIST: display(head);
					break;
			case MODIFY: modify(head, name, telephone);
					break;
			case QUIT: write_list(head); //将链表的数据写进文件中
					   exit(0);
					break;
			case HELP: help();
					break;
		}

	}
	
	return 0;

}

list.c文件:此文件中是各函数的定义。

#include"main.h"

PNODE creat_head(){//创建头结点

	PNODE head = (PNODE)malloc(sizeof(NODE));
	head->name = (char *)malloc(6);
	head->telephone = (char *)malloc(6);
	head->name = "head";
	head->telephone = "-111";
	head->next = head;
	head->prior = head;

	return head;
}

void display(const PNODE head){//打印通讯录
	
	PNODE pnew = head->next;
	while(pnew != head){
		printf("%s:%s\n", pnew->name, pnew->telephone);
		pnew = pnew->next;
	}

}

void add(const PNODE head, char *name, char *telephone){//增加联系人
	
	//开辟一个新节点并赋值
	PNODE pnode = (PNODE)malloc(sizeof(NODE));
	pnode->name = (char *)malloc(strlen(name));
	pnode->telephone = (char *)malloc(strlen(telephone));
	strcpy(pnode->name, name);
	strcpy(pnode->telephone, telephone);

	//插入新节点
	pnode->next = head->next;
	head->next->prior = pnode;
	head->next = pnode;
	pnode->prior = head;

}

int analyse(char *buf, char *cmd, char *name, char *telephone){//解析指令,将输入的指令分割
	char *p;
	char *q;

	//解析输入信息为命令、姓名、电话号码。strchr(char *a, char b),
	//返回字符串a中第一个字符b的地址,没有就返回NULL。
	if((p = strchr(buf, ' ')) != NULL){
		*p = 0;
		strcpy(cmd, buf);
		if((q = strchr(p+1, ' ')) != NULL){
			*q = 0;
			strcpy(name, p+1);
			strcpy(telephone, q+1);
		}
		else {
			strcpy(name, p+1);
		}
	}
	else{
		strcpy(cmd, buf);
	}
	
	//判断此次输入的是哪条指令,并返回相应的值
	if(strcmp(cmd, "add") == 0){
		return ADD;
	}
	else if(strcmp(cmd, "delete") == 0){
		return DELETE;
	}
	else if(strcmp(cmd, "find") == 0){
		return FIND;
	}
	else if(strcmp(cmd, "list") == 0){
		return LIST;
	}
	else if(strcmp(cmd, "modify") == 0){
		return 5;
	}
	else if(strcmp(cmd, "quit") == 0){
		return QUIT;
	}
	else if(strcmp(cmd, "help") == 0){
		return HELP;
	}
	else{
		return -99;
	}
}

void delete(const PNODE head, char *name){//删除指定联系人
	
	PNODE pnode = find(head, name);
	if(pnode != NULL){
		pnode->next->prior = pnode->prior;
		pnode->prior->next = pnode->next;
		
		//注意要free三次,因为这都是自己开辟的内存,要及时释放
		free(pnode->name);
		free(pnode->telephone);
		free(pnode);
		printf("Delete Success\n");
	}

}

PNODE find(PNODE head, char *name){//查找联系人
	
	PNODE pnode = head->next;
	while((strcmp(pnode->name, name) != 0) && (pnode != head)){
		pnode = pnode->next;
	}
	if(strcmp(pnode->name, name) == 0){//名字匹配成功则返回地址,失败则返回NULL
		printf("find success:%s %s\n", pnode->name, pnode->telephone);
		return pnode;
	}
	else{
		printf("No Person\n");
		return NULL;
	}
}

void modify(PNODE head, char *name, char *telephone){//修改联系人
	PNODE pnode = find(head, name);
	if(pnode != NULL){
		strcpy(pnode->telephone, telephone);
		printf("modify success:%s %s\n",pnode->name, pnode->telephone);
	}
}

void help(){//显示操作命令的详细信息

	printf("\n\n");
	printf("|********************************************************|\n");
	printf("|*                  Address Book                        *|\n");
	printf("|*    Instruction Format: command name telephone        *|\n");
	printf("|*    1.add a contact: add name telephone               *|\n");
	printf("|*    2.delete a contact: delete name                   *|\n");
	printf("|*    3.modify a contact: modify name new_telephone     *|\n");
	printf("|*    4.find a contact: find name                       *|\n");
	printf("|*    5.show all contact: list                          *|\n");
	printf("|*    6.sign out: quit                                  *|\n");
    printf("|********************************************************|\n");
    printf("\n\n");
}

void write_list(PNODE head){	//退出前将链表的数据写入文件中保存起来

	PNODE pnew = head->next;
	FILE *fp = fopen("address.txt", "w");
	while(pnew != head){
		fputs(pnew->name, fp);
		fputs(" ", fp);
		fputs(pnew->telephone, fp);
		fputs("\n", fp);
		pnew = pnew->next;
	}
	
	fclose(fp);
}

int read_list(PNODE head){	//每次启动通讯录时,将文件中的联系人信息加载进来
	char buf[40];
	char *p;

	FILE *fp = fopen("address.txt", "r");
	//如果当前没有address.txt文件,就返回
	if(fp == NULL){
		
		return 0;
	}

	//一次读取一行,即一个联系人的信息
	while(fgets(buf, sizeof(buf),fp) != NULL){
		buf[strlen(buf) - 1] = 0;	//将读出除的换行符去掉
		
		//将读取的一行数据,分割成姓名和电话号码
		if((p = strchr(buf, ' ')) == NULL){
			printf("read address fail\n");
			return 0;
		}
		*p = 0;
		add(head, buf, p+1);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值