動態順序表實現通訊錄

系列文章目錄

【數據結構】順序表


文章目錄

  • 系列文章目錄
  • 前言
  • 一、通訊錄的功能要求
  • 二、通訊錄的代碼實現
    • 1. 新建文件
    • 2. 創建通訊錄的結構體
    • 3. 對順序表文件進行修改
    • 4. 通訊錄具體功能實現
      • 4.1. 通訊錄的初始化和銷毀
      • 4.2. 增加聯系人信息(尾插)
      • 4.3. 查找指定聯系人(通過姓名查找)
      • 4.4. 刪除指定聯系人
      • 4.5. 修改指定聯系人
      • 4.6. 顯示聯系人信息
  • 三、完整代碼
  • 四、效果展示
  • 總結


前言

回顧上文,我們初步了解了順序表,順序表的本質就是數組,但相比于單純的數組,順序表多出了一些功能——增刪查改。那么順序表究竟有什么用呢?接下來為大家使用順序表實現一個簡易的通訊錄。(使用動態順序表實現)


正文開始

一、通訊錄的功能要求

  1. 至少能夠存儲100個人的通訊信息
  2. 能夠保存用戶信息:名字、性別、年齡、電話、地址等
  3. 增加聯系人信息
  4. 刪除指定聯系人
  5. 查找指定聯系人
  6. 修改指定聯系人
  7. 顯示聯系人信息

二、通訊錄的代碼實現

1. 新建文件

順序表作為一種數據結構,只是一個工具,當我們要使用它去實現具體的東西時還需要對其進行包裝。所以,我們這里在原來順序表的基礎上新建了兩個文件——Contact.h和Contact.c。
在這里插入圖片描述
Contact.h中存放通訊錄所需的函數的聲明和結構體的聲明。
Contact.c中存放通訊錄中函數的定義。

2. 創建通訊錄的結構體

接下來我們就需要在Contact.h中創建一個通訊錄的結構體,要包含的信息有:名字、性別、年齡、電話、地址。所以我們的順序表中的元素的類型要是結構體,該結構體有5個成員。

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 20typedef struct personinform
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}perinfo;

由于我們要實現通訊錄,我們的順序表的結構體的結構體名要更改為Contact,且要在該頭文件中就要實現,因為后面有對應函數的聲明,所以我們要在Contact.h中使用前置聲明。

typedef struct Sepline Contact; // 只有前置聲明才能更改順序表的結構體名。

3. 對順序表文件進行修改

我們在Contact.h中把套在順序表上的外殼寫完,我們還要對原來的順序表進行小幅度修改,使其與我們要實現的功能匹配。
首先就要包含Contact.h這個頭文件,然后將typedef后的int改為perinfo

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
typedef perinfo SLtype;
//動態順序表
typedef struct Sepline
{SLtype* arr;int size;//有效數字大小int capacity;//動態內存大小
}SL;

最后,我們要將順序表的函數實現進行修改,原本是實現int的,現在要改為實現結構體形式。

void SLshow(SL* sl)
{printf("%s %s %s %s %s\n", "姓名", "性別", "年齡", "電話", "地址");for (int i = 0; i < sl->size; i++)printf("%3s  %3s  %3d  %3s  %3s\n", sl->arr[i].name, sl->arr[i].gender,sl->arr[i].age,sl->arr[i].tel,sl->arr[i].addr);
}

順序表的修改和查找,我選擇刪除重新實現,要修改與重寫沒什么區別。

4. 通訊錄具體功能實現

4.1. 通訊錄的初始化和銷毀

//初始化
void Con_init(Contact* con);//銷毀
void Con_des(Contact* con);
void Con_init(Contact* con)
{SLinit(con);
}void Con_des(Contact* con)
{SLdestory(con);
}

這就是使用了順序表后的情況,在具體實現函數時只需要套用之前的函數就可以了。

4.2. 增加聯系人信息(尾插)

//插入(后插)
void Con_insert(Contact* con);
void Con_insert(Contact* con)
{perinfo x = { 0 };printf("請輸入聯系人姓名:");scanf("%s", x.name);printf("請輸入聯系人性別:");scanf("%s", x.gender);printf("請輸入聯系人年齡:");scanf("%d", &x.age);printf("請輸入聯系人電話:");scanf("%s", x.tel);printf("請輸入聯系人地址:");scanf("%s", x.addr);SL_in_back(con, x);
}

4.3. 查找指定聯系人(通過姓名查找)

int Con_find_name(Contact* con, char name[]);
int Con_find_name(Contact* con, char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(name, con->arr[i].name))return i;}return -1;
}

4.4. 刪除指定聯系人

//指定刪除
void Con_del(Contact* con);
void Con_del(Contact* con)
{char name[20];printf("請輸入需要刪除的聯系人:");scanf("%s", name);int find = Con_find_name(con, name);if (find != -1){SLindel(con, find);printf("刪除成功\n");}else{printf("需要刪除的聯系人不存在\n");}
}

4.5. 修改指定聯系人

//修改
void Con_fix_name(Contact* con);
void Con_fix_name(Contact* con)
{char name[20];printf("請輸入需要修改的聯系人姓名:");scanf("%s", name);int find = Con_find_name(con, name);perinfo x = { 0 };printf("請輸入修改后的姓名:");scanf("%s", x.name);printf("請輸入修改后的性別:");scanf("%s", x.gender);printf("請輸入修改后的年齡:");scanf("%d", &x.age);printf("請輸入修改后的電話:");scanf("%s", x.tel);printf("請輸入修改后的地址:");scanf("%s", x.addr);con->arr[find] = x;
}

4.6. 顯示聯系人信息

//展示
void Con_show(Contact* con);
void Con_show(Contact* con)
{SLshow(con);
}

這些通訊錄的函數的實現基本都通過調用了順序表的函數,大大減少了我們需要寫的代碼量,而且還不用考慮數據是如何增加,刪除等。當然,前提是順序表的函數沒有寫錯。

三、完整代碼

Contact.h

#pragma once#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 20typedef struct personinform
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}perinfo;typedef struct Sepline Contact; // 只有前置聲明才能更改順序表的結構體名。//初始化
void Con_init(Contact* con);//銷毀
void Con_des(Contact* con);//插入(后插)
void Con_insert(Contact* con);//指定刪除
void Con_del(Contact* con);//展示
void Con_show(Contact* con);//查找
int Con_find_name(Contact* con, char name[]);//修改
void Con_fix_name(Contact* con);

Sepline.h

#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
typedef perinfo SLtype;
//動態順序表
typedef struct Sepline
{SLtype* arr;int size;//有效數字大小int capacity;//動態內存大小
}SL;//順序表初始化
void SLinit(SL* sl);//順序表銷毀
void SLdestory(SL* sl);//后插
void SL_in_back(SL* sl, SLtype x);//前插
void SL_in_front(SL* sl, SLtype x);//后刪
void SL_out_back(SL* sl);//前刪
void SL_out_front(SL* sl);//展示
void SLshow(SL* sl);//查找
int SLfind(SL* sl, SLtype n);//修改
void SLfix(SL* sl, int n);//指定位置增加
void SLinsert(SL* sl, int n, SLtype x);//指定位置刪除
void SLindel(SL* sl, int n);//擴展空間
void SLapply(SL* sl);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1#include "Sepline.h"
#include "Contact.h"void Con_init(Contact* con)
{SLinit(con);
}void Con_des(Contact* con)
{SLdestory(con);
}void Con_insert(Contact* con)
{perinfo x = { 0 };printf("請輸入聯系人姓名:");scanf("%s", x.name);printf("請輸入聯系人性別:");scanf("%s", x.gender);printf("請輸入聯系人年齡:");scanf("%d", &x.age);printf("請輸入聯系人電話:");scanf("%s", x.tel);printf("請輸入聯系人地址:");scanf("%s", x.addr);SL_in_back(con, x);
}int Con_find_name(Contact* con, char name[])
{for (int i = 0; i < con->size; i++){if (0 == strcmp(name, con->arr[i].name))return i;}return -1;
}void Con_del(Contact* con)
{char name[20];printf("請輸入需要刪除的聯系人:");scanf("%s", name);int find = Con_find_name(con, name);if (find != -1){SLindel(con, find);printf("刪除成功\n");}else{printf("需要刪除的聯系人不存在\n");}
}void Con_show(Contact* con)
{SLshow(con);
}void Con_fix_name(Contact* con)
{char name[20];printf("請輸入需要修改的聯系人姓名:");scanf("%s", name);int find = Con_find_name(con, name);perinfo x = { 0 };printf("請輸入修改后的姓名:");scanf("%s", x.name);printf("請輸入修改后的性別:");scanf("%s", x.gender);printf("請輸入修改后的年齡:");scanf("%d", &x.age);printf("請輸入修改后的電話:");scanf("%s", x.tel);printf("請輸入修改后的地址:");scanf("%s", x.addr);con->arr[find] = x;
}

Sepline.c

#define _CRT_SECURE_NO_WARNINGS 1#include"Sepline.h"
void SLinit(SL* sl)
{sl->arr = NULL;sl->size = sl->capacity = 0;
}void SLdestory(SL* sl)
{free(sl->arr);sl->arr = NULL;sl->size = sl->capacity = 0;
}void SLapply(SL* sl)
{if (sl->size == sl->capacity){sl->capacity = sl->capacity == 0 ? 4 : 2 * sl->capacity;SLtype* tmp = (SLtype*)realloc(sl->arr, sl->capacity * sizeof(SLtype));if (tmp == NULL){perror("realloc");exit(1);}sl->arr = tmp;tmp = NULL;}
}void SL_in_back(SL* sl, SLtype x)
{assert(sl);SLapply(sl);sl->arr[sl->size++] = x;
}void SL_in_front(SL* sl, SLtype x)
{assert(sl);SLapply(sl);for (int i = sl->size; i > 0; i--){sl->arr[i] = sl->arr[i - 1];}sl->arr[0] = x;sl->size++;
}void SL_out_back(SL* sl)
{assert(sl);assert(sl->size);sl->size--;
}void SLshow(SL* sl)
{printf("%s %s %s %s %s\n", "姓名", "性別", "年齡", "電話", "地址");for (int i = 0; i < sl->size; i++)printf("%3s  %3s  %3d  %3s  %3s\n", sl->arr[i].name, sl->arr[i].gender,sl->arr[i].age,sl->arr[i].tel,sl->arr[i].addr);
}void SL_out_front(SL* sl)
{assert(sl);assert(sl->size);for (int i = 0; i < sl->size - 1; i++)sl->arr[i] = sl->arr[i + 1];sl->size--;
}//int SLfind(SL* sl, SLtype n)
//{
//	assert(sl);
//	//assert(n >= 0 && n < sl->size);
//	for (int i = 0; i < sl->size; i++)
//	{
//		if (n == sl->arr[i])
//			return i;
//	}
//	return -1;
//}//void SLfix(SL* sl, int n)
//{
//	assert(sl);
//	assert(n >= 0 && n < sl->size);
//	int num = 0;
//	printf("請輸入修改后的數:");
//	scanf("%d", &num);
//	sl->arr[n] = num;
//}void SLinsert(SL* sl, int n, SLtype x)
{assert(sl);assert(n >= 0 && n <= sl->size);SLapply(sl);for (int i = sl->size; i > n; i--){sl->arr[i] = sl->arr[i - 1];}sl->arr[n] = x;sl->size++;
}void SLindel(SL* sl, int n)
{assert(sl);assert(n >= 0 && n < sl->size);for (int i = n; i < sl->size - 1; i++){sl->arr[i] = sl->arr[i + 1];}sl->size--;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Sepline.h"
#include "Contact.h"void menu()
{printf("\n");printf("***********通訊錄**********\n");printf("**** 1. 增加   2. 刪除 ****\n");printf("**** 3. 查找   4. 展示 ****\n");printf("**** 5. 修改   0. 退出 ****\n");printf("***************************\n");
}
void test()
{Contact con;char name[20];int choose = 0;Con_init(&con);do{menu();printf("請輸入你要進行的操作(輸入前面數字):");scanf("%d", &choose);switch (choose){case 1: Con_insert(&con);break;case 2: Con_del(&con);break;case 3:printf("請輸入你要查找的聯系人姓名:");scanf("%s", name);int find = Con_find_name(&con, name);if (find < 0)printf("沒找到\n");elseprintf("找到了,在第%d個\n", find);break;case 4: Con_show(&con);break;case 5: Con_fix_name(&con);break;case 0: printf("退出應用\n");break;default: printf("請輸入0~6之間的數\n");break;}} while (choose);Con_des(&con);
}int main()
{test();return 0;
}

四、效果展示

增加聯系人
在這里插入圖片描述
修改聯系人
在這里插入圖片描述
刪除聯系人
在這里插入圖片描述
展示聯系人
在這里插入圖片描述
查找聯系人
在這里插入圖片描述


總結

通訊錄的實現實際十分簡單,我們只要能熟練掌握順序表的功能的實現,再在順序表上套一個外殼就變成了通訊錄。我們這個通訊錄還有點小問題——無法一直保存數據。如果想要一直保存可以使用文件來操作,將每次修改的數據保存到一個文件里,每次進入程序先從該文件中讀取數據,結束時將數據傳回文件中。大家可以試著實現以下。
這里是我的解決方法:
test.c

void test()
{FILE* pf = fopen("Contact.txt", "r");Contact con;char name[20];int choose = 0;Con_init(&con);Con_insert_file(&con, pf);do{menu();printf("請輸入你要進行的操作(輸入前面數字):");scanf("%d", &choose);switch (choose){case 1: Con_insert(&con);break;case 2: Con_del(&con);break;case 3: printf("請輸入你要查找的聯系人姓名:");scanf("%s", name);int find = Con_find_name(&con, name);if (find < 0)printf("沒找到\n");elseprintf("找到了,在第%d個\n", find);break;case 4: Con_show(&con);break;case 5: Con_fix_name(&con);break;case 0: printf("退出應用\n");break;default: printf("請輸入0~6之間的數\n");break;}} while(choose);fclose(pf);pf = NULL;pf = fopen("Contact.txt", "w");for (int i = 0; i < con.size; i++){fprintf(pf, "%s %s %d %s %s\n",con.arr[i].name,con.arr[i].gender,con.arr[i].age,con.arr[i].tel,con.arr[i].addr);}fclose(pf);pf = NULL;Con_des(&con);
}

Contact.c

void Con_insert_file(Contact* con, FILE* pf)
{int ret = 0;int i = 0;while (ret != EOF){SLapply(con);ret = fscanf(pf, "%s %s %d %s %s",con->arr[i].name,con->arr[i].gender,&con->arr[i].age,con->arr[i].tel,con->arr[i].addr);if (ret != EOF){con->size++;i++;}}
}

Contact.h

//文件插入
void Con_insert_file(Contact* con, FILE* pf);

感謝觀看!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/38219.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38219.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38219.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot + 虛擬線程,性能炸裂!

一、什么是虛擬線程 虛擬線程是Java19開始增加的一個特性&#xff0c;和Golang的攜程類似&#xff0c;一個其它語言早就提供的、且如此實用且好用的功能&#xff0c;作為一個Java開發者&#xff0c;早就已經望眼欲穿了。 二、虛擬線程和普通線程的區別 “虛擬”線程&#xf…

一些硬件知識(十二)

X電容是接在火線和零線之間&#xff0c;Y電容是接在火零線和地之間。X電容濾除差模干擾&#xff0c;Y電容濾除共模干擾&#xff1a; 高頻干擾信號經過X電容后幅度沒有變化&#xff0c;相位相差180度&#xff1a; DW01電池管理芯片&#xff1a; M1、M2&#xff1a;這兩個為N溝道…

【關于C/C++中的scanf不能使用問題】

方法1&#xff1a;scanf_s 方法2&#xff1a;看見后面的日志了嗎 CRT……&#xff1f;在第一行加上#define 日志 方法3&#xff1a;#pragma warning&#xff08;disable&#xff1a;4996&#xff09; 4996是我們的報錯序號

開發筆記:vue3+ts+vant 卡片數據分頁,下拉加載,卡片左滑可刪除

效果&#xff1a; 實現 使用vantui組件 van-swipe-cell van-card &#xff08;商品卡片&#xff09; 核心代碼 const currentPage ref(1) const pageSize ref(4) const totalSize ref(10) const loading ref(false) const finished ref(false) const refreshing ref(…

Git新倉庫創建流程

平時需要創建新倉庫,老要去查代碼特別煩&#xff0c;在此寫下流程方便備用. 1.創建新的云倉庫 無論使用GitHub還是Gitee,首先要創建一個云倉庫&#xff0c;這里就直接用國內的gitee做演示了&#xff0c;githup老掛加速器太煩&#xff0c;偷個懶. 我這里創建的是一個空倉庫&…

java- Lambda表達式的實際應用

### 12. Lambda 表達式的實際應用 為了更好地理解和應用 Lambda 表達式&#xff0c;我們可以通過一些實際案例來展示其用法和優勢。 #### 12.1 使用 Lambda 表達式進行事件處理 在 GUI 編程中&#xff0c;事件處理是一個常見的任務。使用 Lambda 表達式可以簡化事件處理代碼…

Nginx主配置文件---Nginx.conf

nginx主配置文件的模塊介紹 全局塊&#xff1a; 全局塊是配置文件從開始到 events 塊之間的部分&#xff0c;其中指令的作用域是 Nginx 服務器全局。主要指令包括&#xff1a; user&#xff1a;指定可以運行 Nginx 服務的用戶和用戶組&#xff0c;只能在全局塊配置。例如&…

軟考《信息系統運行管理員》-2.2 信息系統運維的組織

2.2 信息系統運維的組織 信息系統運維的任務 數據資源管理 數據收集、數據校驗、數據錄入、數據處理 軟件資源管理 采購、保存、相關文檔保管、分發、安裝、支持、評價、培訓 硬件資源管理 檢查、維護、故障處理、更新、修復、擴充 系統安全管理 可用性、完整性、保密性、可控…

USB PD+TYPE -C快充電源中MOSFET選型,USB PD應用市場包含智能手機,平板電腦,筆記本電腦,游戲本,移動硬盤,數碼相機,電動工具等傳統領域

USB PD全稱為USB Power Delivery&#xff0c;是由USB-IF組織制定的一種快速充電協議&#xff0c;也是目前市場非常看好的一種協議&#xff0c;可以支持輸出功率高達100W&#xff1b;Type-C是一種接口規范&#xff0c;能夠支持傳輸更大的電流。USB PD應用市場不僅包含智能手機&a…

虛擬紀念展館建設的重大意義:重新定義紀念活動的未來

一、什么是虛擬紀念展館&#xff1f; 虛擬紀念展館是一種利用3D、VR等技術在線展示歷史事件、人物或文化遺產的數字化空間。這些展館通過虛擬現實、增強現實和3D建模等技術手段&#xff0c;創建出身臨其境的體驗&#xff0c;使參觀者可以在互聯網上以互動方式探索和學習。 二、…

【FPGA 學習與實踐】<初階> 項目周計劃

第1-2周&#xff1a;基礎項目 - 4位加法器和計數器 目標&#xff1a;掌握Verilog基本語法和模塊設計。 第1周&#xff1a; 學習Verilog的基本語法和結構&#xff08;模塊、端口、數據類型&#xff09;。設計并實現一個4位加法器。編寫測試平臺&#xff08;Testbench&#xff0…

提升效率就靠它們啦

Hey小伙伴們&#xff5e;&#x1f44b; 知道你們都在忙碌的工作中尋求高效的秘訣&#xff0c;今天就給大家安利五款超實用的國產工作App&#xff0c;讓你的工作生活更加得心應手哦&#xff01;&#x1f4bc;? 1??【億可達】 作為一款自動化工具&#xff0c;億可達被譽為國內…

firewalld(5)--direct

簡介 direct 是 firewalld 服務的一個功能&#xff0c;它允許用戶以更直接的方式配置防火墻規則&#xff0c;繞過通常的 firewalld 區域&#xff08;zone&#xff09;和服務的抽象層。然而&#xff0c;這個功能已經被棄用&#xff08;deprecated&#xff09;&#xff0c;并將…

詳解位運算(、|、^、^、>>、<<)

十六進制與二進制對應關系 十六進制和二進制之間的轉換非常直接&#xff0c;每個十六進制數字直接對應四個二進制位&#xff0c;并且十六進制相對二進制要更加簡潔&#xff0c;因此通常書寫位操作的代碼時會選擇使用十六進制來表示數值。 為了方便快速閱讀涉及位運算的源碼&a…

深入探索Scala的類型推斷機制

引言 Scala是一種靜態類型編程語言&#xff0c;以其強大的類型推斷系統而聞名。類型推斷允許開發者在很多情況下省略顯式的類型聲明&#xff0c;從而編寫更簡潔、更少出錯的代碼。本文將深入探討Scala的類型推斷是如何實現的&#xff0c;以及它如何幫助提高開發效率和代碼可讀…

萌啦跨境工具箱有什么作用,萌啦跨境工具箱OZON營銷神器

萌啦OZON數據平臺&#xff0c;作為專為OZON平臺商家打造的數據分析工具&#xff0c;集成了多種強大功能&#xff0c;旨在幫助商家在激烈的市場競爭中獲得數據驅動的優勢&#xff0c;實現精準運營與高效增長。那么萌啦跨境工具箱有什么作用&#xff1f;接下來介紹萌啦跨境工具箱…

全面升級廚房安全,電焰灶引領新時代

煤氣是許多家庭日常使用的能源&#xff0c;目前的普及率還是比較高的&#xff0c;但平時因煤氣泄漏而引發的事故也很多&#xff0c;只需要查看最近一個月因液化氣泄漏引起的爆炸事件屢見不鮮。打開新聞&#xff0c;我們總能時不時看到煤氣爆炸的事故&#xff0c;幸運的能夠逢兇…

代碼隨想錄算法訓練營day70 | 108. 冗余連接、109. 冗余連接II

本次題目都來自卡碼網 108. 冗余連接 無向圖&#xff0c;返回一條可以刪去的邊&#xff0c;使得結果圖是一個有著N個節點的樹&#xff08;即&#xff1a;只有一個根節點&#xff09;。 從前向后遍歷每一條邊&#xff08;因為優先讓前面的邊連上&#xff09;&#xff0c;邊的…

【2024LLM應用-數據預處理】之如何從PDF,PPT等非結構化數據提取有效信息(結構化數據JSON)?

&#x1f970;大家知道嗎,之前在給AI大模型"喂數據"的時候,我們往往需要把非結構化數據(比如PDF、PPT、Excel等)自己手動轉成結構化的格式,這可真是太累人兒了。&#x1f975; 幸好現在有了Unstructured這個神級庫,它內置的數據提取函數可以幫我們快速高效地完成這個…

ubuntu 安裝并啟用 samba

環境&#xff1a;ubuntu server 24.04 步驟如下&#xff1a; sudo apt update sudo apt install samba修改配置文件&#xff1a; sudo vi /etc/samba/smb.conf新增內容&#xff1a; [username]path /home/[username]available yesvalid users [username]read only nobrow…