数据结构 - 顺序表实现通讯录

test.c文件

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1

#include "Contact.h"
int main() 
{
    Con myContacts;
    ConInit(&myContacts);
    int choice;
    int index;
    char targetName[100];
    PerInfo contact; // 创建一个新的联系人信息实例
    while (1) 
    {
        printf("\n--- 通讯录管理系统 ---\n");
        printf("1. 添加联系人到末尾\n");
        printf("2. 添加联系人到开头\n");
        printf("3. 删除最后一个联系人\n");
        printf("4. 删除第一个联系人\n");
        printf("5. 显示所有联系人信息\n");
        printf("6. 保存通讯录到文件\n");
        printf("7. 从文件加载通讯录\n");
        printf("8. 修改指定联系人的信息\n");
        printf("9. 查找指定联系人的信息\n");
        printf("10. 退出\n");
        printf("请选择一个操作:");
        int result = scanf("%d", &choice);
        if (result == 1) 
        {
            switch (choice)
            {
            case 1:
            {
                PerInfo newContact;
                printf("输入姓名:");
                scanf("%s", newContact.name);
                printf("输入性别:");
                scanf("%s", newContact.gender);
                printf("输入年龄:");
                scanf("%d", &newContact.age);
                printf("输入电话:");
                scanf("%s", newContact.telephone);
                printf("输入地址:");
                scanf("%s", newContact.address);
                ConPushBack(&myContacts, newContact);
                break;
            }
            case 2:
            {
                PerInfo newContact;
                printf("输入姓名:");
                scanf("%s", newContact.name);
                printf("输入性别:");
                scanf("%s", newContact.gender);
                printf("输入年龄:");
                scanf("%d", &newContact.age);
                printf("输入电话:");
                scanf("%s", newContact.telephone);
                printf("输入地址:");
                scanf("%s", newContact.address);
                ConPushFront(&myContacts, newContact);
                break;
            }
            case 3:
                ConPopBack(&myContacts);
                break;
            case 4:
                ConPopFront(&myContacts);
                break;
            case 5:
                ConDisplayAll(&myContacts);
                break;
            case 6:
                ConSave(&myContacts, "contacts.csv");
                break;
            case 7:
                ConLoad(&myContacts, "contacts.csv");
                break;
            case 8:
                printf("请输入要修改的联系人索引:");
                scanf("%d", &index);
                // 此处你需要一种方法来获取新的联系人信息
                // 可以是一个函数,或者直接在这里收集
                printf("输入新的姓名:");
                scanf("%s", contact.name);
                printf("输入新的性别:");
                scanf("%s", contact.gender);
                printf("输入新的年龄:");
                scanf("%d", &contact.age);
                printf("输入新的电话:");
                scanf("%s", contact.telephone);
                printf("输入新的地址:");
                scanf("%s", contact.address);
                // 在修改之前确保索引是有效的
                if (index >= 0 && index < myContacts.size) {
                    ConModify(&myContacts, index, contact);
                }
                else {
                    printf("无效的索引。\n");
                }
                break;
            case 9:
                printf("请输入要查找的联系人姓名:");
                scanf("%s", targetName);
                ConSearch(&myContacts, targetName);

                break;
            case 10:
                ConDestroy(&myContacts);
                printf("退出程序。\n");
                return 0;
            default:
                printf("无效选项,请重新选择。\n");
            }
        }
        else
        {
            // 读取失败,清理输入流
            while (getchar() != '\n'); // 读取并丢弃直到一个新行
            printf("输入无效,请输入一个数字。\n");
        }

    }
    return 0;
}

contact.c文件

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
//通讯录的初始化
void ConInit(Con* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

//通讯录的扩容
void ConCheckcapacity(Con* ps)
{
	if (ps->size == ps->capacity)
	{
		assert(ps);
		int newcapacity = ps->capacity == 0 ? INIT_CAPACITY : ps->capacity * 2;
		PerInfo* temp = (PerInfo*)realloc(ps->arr, newcapacity * sizeof(PerInfo));
		if (temp == NULL)
		{
			perror("realloc:");
			exit(1);
		}
		else
		{
			ps->arr = temp;
			ps->capacity = newcapacity;
		}
	}
}

//通讯录的销毁
void ConDestroy(Con* ps)
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

//添加联系人信息到第一个位置
void ConPushFront(Con* ps, PerInfo newContact)
{
	assert(ps);
	ConCheckcapacity(ps);
	for (int i = ps->size - 1;i >= 0;i--)
	{
		ps->arr[i + 1] = ps->arr[i];
	}
	ps->arr[0] = newContact;
	ps->size++;
}

//添加联系人信息到最后一个位置
void ConPushBack(Con* ps, PerInfo newContact)
{
	assert(ps);
	ConCheckcapacity(ps);
	ps->arr[ps->size] = newContact;
	ps->size++;
}

//删除第一个联系人信息
void ConPopFront(Con* ps)
{
	assert(ps);
	if (ps->size == 0) 
	{
		printf("提示:这个联系人列表是空的,没有东西可以删除\n");
		return;
	}
	else
	{
		for (int i = 0;i < ps->size - 1; i++)
		{
			ps->arr[i] = ps->arr[i + 1];
		}
		ps->size--;
	}
	printf("提示:第一个联系人删除成功\n");
}


//删除最后一个联系人信息
void ConPopBack(Con* ps)
{
	assert(ps);  // 确保通讯录指针不为空
	if (ps->size == 0) {
		printf("提示:通讯录为空,没有可以删除的联系人\n");
		return;
	}

	ps->size--;  // 减少通讯录的大小,移除最后一个元素
	printf("提示:最后一个联系人已成功删除\n");
}

//修改指定联系人的信息
void ConModify(Con* ps, int index, PerInfo updatedContact)
{
	assert(ps);
	if (index < 0 || index >= ps->size) {
		printf("输入的索引无效,无法修改联系人信息。\n");
		return;
	}
	// 更新指定索引处的联系人信息
	ps->arr[index] = updatedContact;
	//将新的联系人信息 updatedContact 赋值给 arr 数组的第 index 个位置。这个操作实质上是一个结构体赋值操作,它将 updatedContact 结构体的所有成员(包括姓名、性别、年龄、电话号码和地址等)复制到 arr[index] 所指向的结构体中。这意味着原来存储在该索引位置的联系人信息会被完全替换为新提供的信息。
	printf("联系人信息已成功更新:%s %s %d %s %s\n", updatedContact.name, updatedContact.gender, updatedContact.age, updatedContact.telephone, updatedContact.address);
}


//查找指定联系人的信息
void ConSearch(Con* ps, const char* targetName)
{
	assert(ps);  // 确保通讯录指针不为空
	int found = 0;  // 用于记录是否找到联系人

	for (int i = 0; i < ps->size; i++) {
		if (strcmp(ps->arr[i].name, targetName) == 0) {
			printf("找到联系人: 姓名:%s, 性别:%s, 年龄:%d, 电话:%s, 地址:%s\n",
				ps->arr[i].name, ps->arr[i].gender, ps->arr[i].age,
				ps->arr[i].telephone, ps->arr[i].address);
			found = 1;  // 标记为找到
		}
	}

	if (!found) {
		printf("未找到联系人:%s\n", targetName);
	}
}


// 打印所有联系人信息
void ConDisplayAll(Con * ps)
{
	assert(ps);  // 确保通讯录指针不为空
	if (ps->size == 0) {
		printf("通讯录为空,没有联系人信息可显示。\n");
		return;
	}

	printf("通讯录包含以下联系人:\n");
	for (int i = 0; i < ps->size; i++) {
		printf("%d. 姓名:%s, 性别:%s, 年龄:%d, 电话:%s, 地址:%s\n",
			i + 1,
			ps->arr[i].name,
			ps->arr[i].gender,
			ps->arr[i].age,
			ps->arr[i].telephone,
			ps->arr[i].address);
	}
}

// 保存所有联系人信息到文件
void ConSave(Con* ps, const char* filename)
{
	assert(ps);  // 确保通讯录指针不为空
	FILE* file = fopen(filename, "w");  // 打开文件用于写入
	if (file == NULL) {
		perror("无法打开文件");
		return;
	}

	// 写入通讯录大小,可用于加载数据
	fprintf(file, "%d\n", ps->size);
	for (int i = 0; i < ps->size; i++) {
		fprintf(file, "%s,%s,%d,%s,%s\n",
			ps->arr[i].name,
			ps->arr[i].gender,
			ps->arr[i].age,
			ps->arr[i].telephone,
			ps->arr[i].address);
	}

	fclose(file);  // 关闭文件
	printf("通讯录已成功保存到文件:%s\n", filename);
}

// 加载通讯录数据
void ConLoad(Con* ps, const char* filename)
{
	assert(ps);
	FILE* file = fopen(filename, "r");
	if (file == NULL) {
		perror("无法打开文件");
		return;
	}

	int size;
	fscanf(file, "%d\n", &size);  // 读取通讯录大小
	for (int i = 0; i < size; i++) {
		PerInfo info;
		fscanf(file, "%[^,],%[^,],%d,%[^,],%[^\n]\n",
			info.name,
			info.gender,
			&info.age,
			info.telephone,
			info.address);
		ConPushBack(ps, info);  // 将读取的信息添加到通讯录
	}

	fclose(file);
	printf("通讯录数据已从文件:%s 加载完成\n", filename);
}

contact.h文件

cpp 复制代码
#pragma once

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

#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 12
#define ADDR_MAX 100
#define INIT_CAPACITY 4

typedef struct PersonInfo {
    char name[NAME_MAX];
    char gender[SEX_MAX];
    int age;
    char telephone[TEL_MAX];
    char address[ADDR_MAX];
} PerInfo;

typedef struct Contact {
    PerInfo* arr;
    int size;
    int capacity;
} Con;

// Function declarations
void ConInit(Con* ps);
void ConCheckcapacity(Con* ps);
void ConDestory(Con* ps);
void ConPushFront(Con* ps, PerInfo newContact);
void ConPushBack(Con* ps, PerInfo newContact);
void ConPopFront(Con* ps);
void ConPopBack(Con* ps);
void ConModify(Con* ps, int index, PerInfo updatedContact);
void ConSearch(Con* ps, const char* targetName);
void ConDisplayAll(Con* ps);
void ConSave(Con* ps, const char* filename);
void ConLoad(Con* ps, const char* filename);
相关推荐
就爱学编程1 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
波音彬要多做4 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Noah_aa4 小时前
代码随想录算法训练营第五十六天 | 图 | 拓扑排序(BFS)
数据结构
KpLn_HJL5 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
AC使者10 小时前
5820 丰富的周日生活
数据结构·算法
无 证明11 小时前
new 分配空间;引用
数据结构·c++
别NULL15 小时前
机试题——疯长的草
数据结构·c++·算法