欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言代碼實現(xiàn)通訊錄管理系統(tǒng)

 更新時間:2022年06月15日 11:39:34   作者:?°九三??  
這篇文章主要為大家詳細介紹了C語言代碼實現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了C語言實現(xiàn)通訊錄管理系統(tǒng),供大家參考,具體內容如下

一、需求分析

運用C語言實現(xiàn)一個簡單的通訊錄管理系統(tǒng),要求對數(shù)據(jù)有 增刪改查清排顯 等功能的實現(xiàn)(這里由于還沒學到文件,所以下面所有的存儲都是在內存中,也就是當程序結束的時候添加的信息都會清空掉 - 后續(xù)會加以改進的)

二、程序結構

在基本的程序設計中,都會將項目分為三個文件:

1、test.c - 主函數(shù)(負責調用各個功能的接口)
2、contact.c - 實現(xiàn)各個模塊的功能
3、contact.h - 用于存放頭文件、宏定義、函數(shù)聲明等

三、頭文件內容的介紹

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

#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 50
#define TELE_MAX 12

#define DEFAULT_SZ 3

// 數(shù)組版本
//typedef struct PeoInfo
//{
//?? ?char name[NAME_MAX];
//?? ?int age;
//?? ?char sex[SEX_MAX];
//?? ?char addr[ADDR_MAX];
//?? ?char tele[TELE_MAX];
//}PeoInfo;
//
//typedef struct Contact
//{
//?? ?//PeoInfo data[MAX]; ?// 存放信息
//?? ?PeoInfo data[MAX];
//?? ?int sz; // 存放通訊錄有幾個人的信息
//}Contact;

// 每個人的基本信息
typedef struct PeoInfo
{
?? ?char name[NAME_MAX];
?? ?int age;
?? ?char sex[SEX_MAX];
?? ?char addr[ADDR_MAX];
?? ?char tele[TELE_MAX];
}PeoInfo;

typedef struct Contact
{
?? ?//PeoInfo data[MAX]; ?// 存放信息
?? ?PeoInfo* data;
?? ?int sz; // 存放通訊錄有幾個人的信息
?? ?int capacity; // 記錄當前通訊錄的最大容量
}Contact;


void DestoryContact(Contact* pc);
void InitContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(const Contact* pc);
void DeleteContact(Contact* pc);
void SearchContact(const Contact* pc);
void ModifyContact(Contact* pc);
void SortContact(Contact* pc);

里面被注釋的代碼則是之前的數(shù)組版本,規(guī)定死了通訊錄大??;而下面我們會用動態(tài)增容來進行實現(xiàn)。頭文件里面用宏定義主要為了之后我們更改對應的大小的時候更加的方便;結構體主要存放的就是三大部分:

1. 一個指向每個人基本信息的結構體指針;2. sz記錄著通訊錄的記錄條數(shù);3. capacity 存放通訊錄的容量

四、模塊化實現(xiàn)各個功能

(1)主函數(shù)實現(xiàn)

int main()
{
?? ?int input = 0;
?? ?Contact con; // 創(chuàng)建通訊錄

?? ?InitContact(&con);

?? ?do
?? ?{
?? ??? ?menu();
?? ??? ?printf("請選擇:->");
?? ??? ?scanf("%d", &input);

?? ??? ?switch (input)
?? ??? ?{
?? ??? ?case ADD:
?? ??? ??? ?AddContact(&con);
?? ??? ??? ?break;
?? ??? ?case DEL:
?? ??? ??? ?DeleteContact(&con);
?? ??? ??? ?break;
?? ??? ?case SEARCH:
?? ??? ??? ?SearchContact(&con);
?? ??? ??? ?break;
?? ??? ?case MODIFY:
?? ??? ??? ?ModifyContact(&con);
?? ??? ??? ?break;
?? ??? ?case SORT:
?? ??? ??? ?SortContact(&con);
?? ??? ??? ?break;
?? ??? ?case SHOW:
?? ??? ??? ?ShowContact(&con);
?? ??? ??? ?break;
?? ??? ?case EXIT:
?? ??? ??? ?DestoryContact(&con);
?? ??? ??? ?printf("退出\n");
?? ??? ??? ?break;
?? ??? ?default:
?? ??? ??? ?printf("輸入錯誤,請重新輸入\n");
?? ??? ??? ?break;
?? ??? ?}
?? ?} while (input);

?? ?return 0;
}

一般函數(shù)的主函數(shù)里面都可以用do ……while結構來控制程序的執(zhí)行順序,在case后面用的則是 枚舉常量 ,這樣能做到更好的見名知意。

(2)初始化通訊錄

void InitContact(Contact* pc)
{
?? ?assert(pc);
?? ?pc->sz = 0;
?? ?PeoInfo* tmp = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
?? ?if (tmp != NULL)
?? ?{
?? ??? ?pc->data = tmp;
?? ?}
?? ?else
?? ?{
?? ??? ?printf("InitContact()::%s\n", strerror(errno));
?? ?}

?? ?pc->capacity = DEFAULT_SZ;
}

這里設定了通訊錄的起始大小,后面可以通過動態(tài)增容來擴大(而數(shù)組版本的話就沒有這么靈活了)

(3)添加聯(lián)系人信息

void check_capacity(Contact* pc)
{
?? ?assert(pc);
?? ?if (pc->sz == pc->capacity)
?? ?{
?? ??? ?// 增容
?? ??? ?PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2)*sizeof(PeoInfo));
?? ??? ?if (tmp != NULL)
?? ??? ?{
?? ??? ??? ?pc->data = tmp;
?? ??? ??? ?pc->capacity += 2;
?? ??? ??? ?printf("增容成功\n");
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?printf("InitContact()::%s\n", strerror(errno));
?? ??? ?}
?? ?}
}

void AddContact(Contact* pc)
{
?? ?assert(pc);
?? ?check_capacity(pc);

?? ?// 添加內容
?? ?printf("名字:");
?? ?scanf("%s", pc->data[pc->sz].name);
?? ?printf("年齡:");
?? ?scanf("%d", &(pc->data[pc->sz].age));
?? ?printf("性別:");
?? ?scanf("%s", pc->data[pc->sz].sex);
?? ?printf("地址:");
?? ?scanf("%s", pc->data[pc->sz].addr);
?? ?printf("電話:");
?? ?scanf("%s", pc->data[pc->sz].tele);
?? ?
?? ?pc->sz++;
?? ?printf("添加成功\n");
}

這里實現(xiàn)了一個check_capacity 的接口,用來判斷當前通訊錄是否存滿了;若滿了則進行擴容(一般按2倍進行擴容),注意:添加成功后需要對 sz++

(4)刪除聯(lián)系人信息

int FindByName(const Contact* pc, char* name)
{
?? ?int i = 0;
?? ?for (i = 0; i < pc->sz; i++)
?? ?{
?? ??? ?if (strcmp(pc->data[i].name, name) == 0)
?? ??? ?{
?? ??? ??? ?return i;
?? ??? ?}
?? ?}
?? ?return -1;
}

void DeleteContact(Contact* pc)
{
?? ?char name[NAME_MAX] = { 0 };
?? ?assert(pc);

?? ?if (pc->sz == 0)
?? ?{
?? ??? ?printf("通訊錄為空\n");
?? ??? ?return;
?? ?}

?? ?// 根據(jù)輸入的人名進行刪除
?? ?printf("請輸入要刪除的人名:");
?? ?scanf("%s", name);

?? ?int pos = FindByName(pc, name);

?? ?if (pos == -1)
?? ?{
?? ??? ?printf("要刪除的人不存在\n");
?? ?}
?? ?else
?? ?{
?? ??? ?// 刪除
?? ??? ?//int j = 0;
?? ??? ?//for (j = pos; j < pc->sz-1; j++) ?// sz-1為了防止j+1非法訪問
?? ??? ?//{
?? ??? ?//?? ?pc->data[j] = pc->data[j + 1];
?? ??? ?//}

?? ??? ?//pc->sz--;
?? ??? ?//printf("刪除成功\n");
?? ??? ?//if (pc->sz>1)
?? ??? ?memmove((pc->data) + pos, (pc->data) + pos + 1, (pc->sz - pos)*sizeof(PeoInfo));
?? ??? ?pc->sz--;
?? ?}
}

這里我就只做了按照名字進行刪除,你們也可以都嘗試一下喲。下面寫了兩種刪除方法(這里的按名字刪除前需要進行查找,因此我們也可以直接使用我們下面要實現(xiàn)的查找函數(shù),但如果查找里面進行了其他功能,那時不能直接使用的喲)

(5)查找聯(lián)系人信息

void SearchContact(const Contact* pc)

{
?? ?char name[NAME_MAX] = { 0 };
?? ?assert(pc);

?? ?if (pc->sz == 0)
?? ?{
?? ??? ?printf("通訊錄為空\n");
?? ??? ?return;
?? ?}

?? ?printf("請輸入要查找的姓名:");
?? ?scanf("%s", name);
?? ?int i = FindByName(pc, name);

?? ?if(-1 == i)
?? ?{
?? ??? ?// 沒有找到
?? ??? ?printf("你要查找的人不存在\n");
?? ?}
?? ?else
?? ?{
?? ??? ?// 找到了
?? ??? ?printf("%-10s\t%-5s\t%-5s\t%-20s\t%-13s\n",?
?? ??? ??? ??? ?"姓名", "年齡", "性別", "地址", "電話");
?? ??? ?printf("%-10s\t%-5d\t%-5s\t%-20s\t%-13s\n",
?? ??? ??? ?pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
?? ?}
}

這里如果查找到了后,我打印顯示了一下

(6)更改聯(lián)系人信息

void ModifyContact(Contact* pc)
{
?? ?char name[NAME_MAX] = { 0 };
?? ?assert(pc);

?? ?if (pc->sz == 0)
?? ?{
?? ??? ?printf("通訊錄為空\n");
?? ??? ?return;
?? ?}

?? ?printf("請輸入要修改信息的姓名:");
?? ?scanf("%s", name);

?? ?int i = FindByName(pc, name);

?? ?// 修改內容
?? ?printf("新的名字:");
?? ?scanf("%s", pc->data[i].name);
?? ?printf("新的年齡:");
?? ?scanf("%d", &(pc->data[i].age));
?? ?printf("新的性別:");
?? ?scanf("%s", pc->data[i].sex);
?? ?printf("新的地址:");
?? ?scanf("%s", pc->data[i].addr);
?? ?printf("新的電話:");
?? ?scanf("%s", pc->data[i].tele);

?? ?printf("修改后的信息為:\n");

?? ?printf("%-10s\t%-5s\t%-5s\t%-20s\t%-13s\n", "姓名", "年齡", "性別", "地址", "電話");
?? ?printf("%-10s\t%-5d\t%-5s\t%-20s\t%-13s\n",
?? ??? ?pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
}

(7)顯示所有聯(lián)系人信息

void ShowContact(const Contact* pc)
{
?? ?assert(pc);
?? ?// 打印標題
?? ?printf("%-10s\t%-5s\t%-5s\t%-20s\t%-13s\n", "姓名", "年齡", "性別", "地址", "電話");
?? ?int i = 0;
?? ?for (i = 0; i < pc->sz; i++)
?? ?{
?? ??? ?printf("%-10s\t%-5d\t%-5s\t%-20s\t%-13s\n",
?? ??? ??? ?pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
?? ?}
}

直接遍歷打印即可

(8)對聯(lián)系人信息進行排序

int cmp_by_name(const void* e1, const void* e2)
{
?? ?return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

int cmp_by_age(const void* e1, const void* e2)
{
?? ?return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
?? ?// return strcmp(, ((PeoInfo*)e2)->name);
}

void SortContact(Contact* pc)
{
?? ?int choice = 0;
?? ?printf("請選擇:(1、按姓名;2、按年齡)");
?? ?scanf("%d", &choice);

?? ?if (1 == choice)
?? ?{
?? ??? ?qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_name);

?? ??? ?printf("排序后的數(shù)據(jù):\n");
?? ??? ?ShowContact(pc);
?? ?}
?? ?else if (2 == choice)
?? ?{
?? ??? ?qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_age);
?? ??? ?printf("排序后的數(shù)據(jù):\n");
?? ??? ?ShowContact(pc);
?? ?}
?? ?else
?? ?{
?? ??? ?printf("輸入有誤\n");
?? ?}
}

這里使用qsort實現(xiàn)的排序,可以對 姓名 或 年齡進行排序的

(9)退出時銷毀通訊錄

void DestoryContact(Contact* pc)
{
?? ?assert(pc);
?? ?free(pc->data);
?? ?pc->data = NULL;
}

直接將里面指向有效內容的 pc->data 進行free釋放就行,因為它本來就是動態(tài)開辟的,后面要有個好習慣,free之后將其置為NULL,不然就為野指針了。

總結:

以上就是動態(tài)增容版本通訊錄的全部代碼,盡管用了動態(tài)增容,里面仍然會存在很多的空間浪費,后面等博主學了鏈表后,在進行改進。

希望這篇文章對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • C語言中getchar的用法以及實例解析

    C語言中getchar的用法以及實例解析

    getchar()是stdio.h中的庫函數(shù),它的作用是從stdin流中讀入一個字符,下面這篇文章主要給大家介紹了關于C語言中getchar的用法以及實例的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-03-03
  • 利用C語言模擬實現(xiàn)qsort,strcpy,strcat,strcmp函數(shù)

    利用C語言模擬實現(xiàn)qsort,strcpy,strcat,strcmp函數(shù)

    這篇文章主要為大家詳細介紹了如何通過C語言模擬實現(xiàn)qsort(采用冒泡的方式),strcpy,strcat,strcmp等函數(shù),文中的示例代碼講解詳細,感興趣的可以了解一下
    2022-11-11
  • C++中浮點類型的具體使用

    C++中浮點類型的具體使用

    C++提供了不同精度的浮點類型,主要有?float、double?和?long?double,這些浮點類型具有不同的字節(jié)大小和范圍,用于滿足不同應用場景的精度要求,本文主要介紹了C++中浮點類型的具體使用,感興趣的可以了解一下
    2023-08-08
  • VS及Unity安裝和使用Nuget包

    VS及Unity安裝和使用Nuget包

    本文主要介紹了VS及Unity安裝和使用Nuget包,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • C++設計模式編程中簡單工廠與工廠方法模式的實例對比

    C++設計模式編程中簡單工廠與工廠方法模式的實例對比

    這篇文章主要介紹了C++設計模式編程中簡單工廠與工廠方法模式的實例對比,文中最后對兩種模式的優(yōu)缺點總結也比較詳細,需要的朋友可以參考下
    2016-03-03
  • C++分析講解類的靜態(tài)成員函數(shù)如何使用

    C++分析講解類的靜態(tài)成員函數(shù)如何使用

    與靜態(tài)數(shù)據(jù)成員不同,靜態(tài)成員函數(shù)的作用不是為了對象之間的溝通,而是為了能處理靜態(tài)數(shù)據(jù)成員,靜態(tài)成員函數(shù)沒有this指針。既然它沒有指向某一對象,也就無法對一個對象中的非靜態(tài)成員進行默認訪問
    2022-04-04
  • C++ LeeCode題目:比特位計數(shù)和買賣股票的最佳時機

    C++ LeeCode題目:比特位計數(shù)和買賣股票的最佳時機

    這篇文章主要介紹了基于C語言計算比特位計數(shù)和買賣股票的最佳時機,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2021-07-07
  • C++構造函數(shù)的一些注意事項總結

    C++構造函數(shù)的一些注意事項總結

    構造函數(shù)是創(chuàng)建類對象,并且在創(chuàng)建完成前,對類進行初始化的特殊函數(shù),下面這篇文章主要給大家介紹了關于C++構造函數(shù)的一些注意事項,需要的朋友可以參考下
    2021-11-11
  • 聊一聊OpenCV相機標定

    聊一聊OpenCV相機標定

    這篇文章主要為大家詳細介紹了OpenCV相機標定的相關資料,即獲得相機參數(shù)的過程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C++靜態(tài)庫與動態(tài)庫文件的生成和使用教程

    C++靜態(tài)庫與動態(tài)庫文件的生成和使用教程

    庫文件是計算機上的一類文件,可以簡單的把庫文件看成一種代碼倉庫,它提供給使用者一些可以直接拿來用的變量、函數(shù)和類,下面這篇文章主要給大家介紹了關于C++靜態(tài)庫與動態(tài)庫文件的生成和使用的相關資料,需要的朋友可以參考下
    2023-03-03

最新評論