基於單連結串列的班級通訊錄
需求分析
將全班同學的通訊資訊存入一個順序表。元素中的通訊資訊包括每一位同學的:學號、姓名、性別、宿舍、聯絡電話等。要求能夠利用姓名和序號進行有關查詢、插入、刪除、更新等操作。
(1)以順序表作為儲存班級通訊錄的儲存結構,首先需要定義一個順序表資料結構,其中每個元素是一條同學通訊資訊,包括學號、姓名、性別、宿舍、聯絡電話等欄位。
(2)將本班的通訊資訊輸入文字檔案“通訊錄.txt”中,需要實現檔案讀寫功能。當程式啟動時,需要將檔案中的資訊讀入順序表中,當程式結束時,需要將記憶體中的通訊錄順序表中的資訊重新寫入檔案。
(3)需要實現向順序表中追加一條通訊錄記錄的功能,即順序表的插入功能。通過提示資訊,讓使用者將一條通訊錄記錄的各個欄位資訊輸入記憶體,構成一個順序表元素,然後將其作為一個整體插入順序表最後一條記錄之後,該功能在讀取檔案資訊,建立順序表是也需要用到。
(4)需要實現查詢功能,包括通過姓名查詢:給定一個姓名,返回其通訊資訊和在表中的位置;通過序號查詢:給定一個姓名,返回其通訊資訊和在表中的位置。
(5)需要實現在給定位置增加一條記錄的功能,該位置可以直接設定,也可以通過查詢得到,比如先查到姓名為“XXX”的學生的通訊資訊在表中的位置,然後在該記錄的後面插入一條新的記錄。
(6)需要實現刪除給定位置記錄的功能,該位置可以直接設定,也可以通過查詢得到,比如先查到姓名為“XXX”的學生的通訊資訊在表中的位置,然後將該記錄刪除之。
詳細設計
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define OK 1
#define ERROR 0
#define MAX 100
typedef int Status;
typedef char ElemType;
//結點定義
typedef struct telebook //通訊錄結點資料域
{
char num[MAX]; //學號
char name[MAX]; //姓名
char sex[MAX]; //性別
char hostel[MAX]; //宿舍
char telephone[MAX]; //電話號碼
}telebook;
typedef struct LNode //連結串列結點
{
telebook data; //結點資料域
struct LNode* next; //結點指標域
}LNode, * LinkList;
void readFile(LinkList& L);//讀取文字資訊
Status InitList_L(LinkList& L);//單連結串列的初始化
void Find_Name(LinkList& L); //按姓名查詢
void Find_Num(LinkList& L); //按姓名查詢
Status CreateFromTail(LinkList& L); //採用尾插法在尾部插入元素
Status ListInsert_L(LinkList& L);//在單鏈線性表L的第i個元素之前插入元素
Status ListInsert_LName(LinkList& L);//在單鏈線性表L的姓名元素之前插入元素
Status Fund_LName(LinkList& L); //尋找該姓名的位置
Status ListDelete_L(LinkList& L);//刪除第i個元素
Status ListDelete_LName(LinkList& L); //刪除姓名為“XXX”的學生記錄
void saveFile(LinkList& L); //儲存通訊錄到檔案
void PrintElem(LinkList L);//列印出所有元素
void List_free(LinkList L); //銷燬連結串列
Status InitList_L(LinkList& L)//單連結串列的初始化
{
L = (LNode*)malloc(sizeof(LNode)); //申請結點空間
if (L == NULL) //判斷是否有足夠的記憶體空間
printf("申請記憶體空間失敗\n");
L->next = NULL; //將next設定為NULL,初始長度為0的單連結串列
return OK;
}
void readFile(LinkList& L) //讀取檔案資訊
{
LinkList q, p;
FILE* fp;
p = L;
q = (LNode*)malloc(sizeof(LNode));
char name[20] = "通訊錄.txt";
if ((fp = fopen(name, "r")) == NULL)
{
printf("error\n");
exit(0);
}
while (p->next != NULL)
{
p = p->next;
}
while (fscanf(fp, "%s%s%s%s%s\n", q->data.num, q->data.name, q->data.sex, q->data.hostel, q->data.telephone) != EOF)
{
q->next = NULL;
p->next = q;
p = q;
q = (LNode*)malloc(sizeof(LNode));
}
printf(" 檔案讀取成功! \n");
fclose(fp);
}
void Find_Name(LinkList& L) //按姓名查詢
{
LinkList q, p;
q = L->next;
printf("輸入要查詢的姓名:\n");
p = (LNode*)malloc(sizeof(LNode));
scanf("%s", p->data.name);
while (q != NULL && strcmp(q->data.name, p->data.name) != 0)
{
q = q->next;
}
if (q == NULL)
{
printf("通訊錄中沒有這個姓名!\n");
}
else
{
printf("已經找到此聯絡人!\n");
printf("學號\t\t姓名\t\t性別\t\t宿舍\t\t電話號碼 \n");
printf("%s\t\t%s\t\t%s\t\t%s\t\t%s\n", q->data.num, q->data.name, q->data.sex, q->data.hostel, q->data.telephone);
}
}
void Find_Num(LinkList& L) //按學號查詢
{
LinkList q, p;
q = L->next;
printf("輸入要查詢的編號:\n");
p = (LNode*)malloc(sizeof(LNode));
scanf("%s", p->data.num);
while (q != NULL && strcmp(q->data.num, p->data.num) != 0)
{
q = q->next;
}
if (q == NULL)
{
printf("通訊錄中沒有這個編號!\n");
}
else
{
printf("已經找到此聯絡人!\n");
printf("學號\t\t姓名\t\t性別\t\t宿舍\t\t電話號碼 \n");
printf("%s\t\t%s\t\t%s\t\t%s\t\t%s\n", q->data.num, q->data.name, q->data.sex, q->data.hostel, q->data.telephone);
}
}
Status CreateFromTail(LinkList& L) //採用尾插法在尾部插入元素
{
LinkList r, s;
r = L; //r指標始終動態指向連結串列的當前表尾
while (r->next)
{//尾插法,直接把指標移位到尾部
r = r->next;
}
s = (LinkList)malloc(sizeof(LNode));
printf("在尾部插入的聯絡人資訊為:\n");
printf("學號\t\t姓名\t\t性別\t\t宿舍\t\t電話號碼 \n");
scanf("%s%s%s%s%s", s->data.num, s->data.name, s->data.sex, s->data.hostel, s->data.telephone);
s->next = NULL;
r->next = s;
return OK;
}
Status ListInsert_L(LinkList& L)//在單鏈線性表L的第i個元素之前插入元素
{
LinkList s, p = L;
int j = 0, i;
printf("輸入要插入的位置:");
scanf("%d", &i);
while (p && j < i)
{ // 尋找第i個結點
p = p->next;
++j;
}
if (!p || j > i) { printf("----無此位置新增失敗-----\n"); return ERROR; } // i小於1或者大於表長
s = (LinkList)malloc(sizeof(LNode)); // 生成新結點
printf("插入的聯絡人資訊為:\n");
printf("學號\t\t姓名\t\t性別\t\t宿舍\t\t電話號碼 \n");
scanf("%s%s%s%s%s", s->data.num, s->data.name, s->data.sex, s->data.hostel, s->data.telephone);
s->next = p->next; // 插入L中
p->next = s;
return OK;
} // LinstInsert_L
Status Fund_LName(LinkList& L) //尋找該姓名的位置
{
LinkList s, p = L->next;
int i = 0;
s = (LNode*)malloc(sizeof(LNode));
scanf("%s", s->data.name);
while (p != NULL && strcmp(p->data.name, s->data.name) != 0)
{
p = p->next;
++i;
}
return i + 1;
}
Status ListInsert_LName(LinkList& L)//在單鏈線性表L的姓名元素之前插入元素
{
LinkList s, q = L, p = L->next;
printf("輸入要在誰的姓名之前新增資訊:");
int i = Fund_LName(L);
int j = 0;
while (q && j < i - 1)
{ // 尋找第i-1個結點
q = q->next;
++j;
}
if (p == NULL) { printf("----查無此人新增失敗-----\n"); return ERROR; } // 如果沒有找到
s = (LinkList)malloc(sizeof(LNode)); // 生成新結點
printf("插入的聯絡人資訊為:\n");
printf("學號\t\t姓名\t\t性別\t\t宿舍\t\t電話號碼 \n");
scanf("%s%s%s%s%s", s->data.num, s->data.name, s->data.sex, s->data.hostel, s->data.telephone);
s->next = q->next; // 插入L中
q->next = s;
return OK;
}
Status ListDelete_L(LinkList& L)//刪除第i個元素
{
LinkList p = L, q;
int j = 0, i;
printf("輸入要刪除的位置:");
scanf("%d", &i);
while (p->next && j < i)
{ // 尋找第i個結點,並令p指向其前趨
p = p->next; ++j;
}
if (!(p->next) || j > i) { printf("----查無此人刪除失敗-----\n"); return ERROR; } // 刪除位置不合理
q = p->next;
p->next = q->next; // 刪除並釋放結點
free(q);
printf("----刪除成功-----\n");
return OK;
} // ListDelete_L
Status ListDelete_LName(LinkList& L) //刪除姓名為“XXX”的學生記錄
{
LinkList p = L, q;
printf("輸入要刪除的學生的姓名:");
int j = 0, i = Fund_LName(L);
while (p->next && j < i - 1)
{ // 尋找第i個結點,並令p指向其前趨
p = p->next; ++j;
}
if (!(p->next) || j > i - 1) { printf("----查無此人刪除失敗-----\n"); return ERROR; } // 刪除位置不合理
q = p->next;
p->next = q->next; // 刪除並釋放結點
free(q);
printf("----刪除成功-----\n");
return OK;
}
void PrintElem(LinkList L)//列印出所有元素
{
LinkList p = L->next;
printf("當前的資訊為:\n");
while (p != NULL)
{
printf("%s\t\t%s\t\t%s\t\t%s\t\t%s\n", p->data.num, p->data.name, p->data.sex, p->data.hostel, p->data.telephone);
p = p->next;
}
printf("\n");
}
void saveFile(LinkList& L) //儲存通訊錄到檔案
{
FILE* fp;
LinkList p;
p = L;
if ((fp = fopen("通訊錄.txt", "wt")) == NULL) exit(0); // "wt"方式開啟檔案時,如果原始檔中有內容,追加
if (p == NULL || p->next == NULL) //連結串列為空
printf("您的操作有誤,請確保您的通訊錄不為空!\n");
else
{
p = p->next;
while (p != NULL)
{
fprintf(fp, "%s\t\t%s\t\t%s\t\t%s\t\t%s", p->data.num, p->data.name, p->data.sex, p->data.hostel, p->data.telephone);
fprintf(fp, "\n");
p = p->next;
}
fclose(fp);
printf("通訊錄已儲存!\n");
}
}
void List_free(LinkList L) //銷燬連結串列
{
LinkList p;
while (L != NULL)
{
p = L;
L = L->next;
free(p);
}
}
/*readFile(L) InitList_L(L) Find_Name(L) Find_Num(L) CreateFromTail(L) ListInsert_L(L) ListInsert_LName(L)
ListDelete_L(L) ListDelete_LName(L) saveFile(L)
PrintElem(L) List_free(L)*/
int main()
{
int n=1;
LinkList L;
InitList_L(L);
while (n != 0)
{
printf("*****************************基於單連結串列的班級通訊錄*****************************\n\n");
printf(" 1:讀取檔案(**請先讀取檔案**) | 2:通過姓名查詢聯絡人\n\n");
printf(" 3:通過學號查詢聯絡人 | 4:在最後新增某學生資訊\n\n");
printf(" 5:將新聯絡人加在第i條記錄之前 | 6:將新聯絡人加在“XXX”的學生之前\n\n");
printf(" 7:刪除第i條記錄 | 8:刪除姓名為“XXX”的學生記錄\n\n");
printf(" 9:顯示結果 | 0:退出程式並儲存 \n\n");
printf("********************************************************************************\n");
printf("請選擇操作<1-9>,退出<0>:");
scanf("%d", &n);
switch (n)
{
case 1:readFile(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 2:Find_Name(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 3:Find_Num(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 4:CreateFromTail(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 5:ListInsert_L(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 6:ListInsert_LName(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 7:ListDelete_L(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 8:ListDelete_LName(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 9:PrintElem(L);
system("pause");//輸入任意鍵繼續
system("cls");//清屏
break;
case 0:saveFile(L); List_free(L);
system("cls");//清屏
break;
}
}
}
測試檔案
測試與結果
(1)讀取檔案
(2)通過姓名查詢聯絡人
(3)通過學號查詢聯絡人
(4)在最後新增某學生資訊
(5)將新聯絡人加在第i條記錄之前
(6)將新聯絡人加在“XXX”的學生之前
(7)刪除第i條記錄
(8)刪除姓名為“XXX”的學生記錄
(9)退出程式並儲存
相關文章
- 【練手小專案】簡易通訊錄:單連結串列實現
- 連結串列基礎2(超簡單)--單連結串列的插入和刪除
- 連結串列 - 單向連結串列
- 012 通過連結串列學習Rust之持久化單連結串列Rust持久化
- 連結串列-單連結串列實現
- 資料結構_連結串列的原理與應用1_單連結串列(基於C語言實現)資料結構C語言
- 022 通過連結串列學Rust之為什麼要非安全的單連結串列Rust
- 單連結串列
- 單連結串列的建立
- 資料結構-單連結串列、雙連結串列資料結構
- 簡單的單向連結串列
- 單雙連結串列
- 單連結串列建立連結串列出現問題
- 55-將單連結串列原地逆置(有頭結點的單連結串列)
- 單向連結串列的建立
- 資料結構_連結串列_單向迴圈連結串列 & 雙向連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- 關於單連結串列反轉的一點整理
- 資料結構__連結串列_單連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- 基於WebSocket的modbus通訊(三)- websocket和串列埠Web串列埠
- 資料結構與演算法——連結串列 Linked List(單連結串列、雙向連結串列、單向環形連結串列-Josephu 問題)資料結構演算法
- 資料結構實驗之連結串列五:單連結串列的拆分資料結構
- 資料結構之連結串列篇(單連結串列的常見操作)資料結構
- 資料結構--單連結串列(通過陣列實現)資料結構陣列
- 014 通過連結串列學習Rust之持久化連結串列的DropRust持久化
- 連結串列基礎總結
- 【連結串列問題】刪除單連結串列的中間節點
- 單連結串列成環
- 棧_單向連結串列
- 12.19單向連結串列
- 【程式碼隨想錄】二、連結串列:2、設計連結串列
- 【程式碼隨想錄】二、連結串列:1、移除連結串列元素
- 02-單連結串列的操作
- 單連結串列的排序問題排序
- 016 通過連結串列學習Rust之安全的雙連結串列佈局Rust
- 單連結串列的逆序輸出 PTA6-1 單連結串列逆轉 為例
- 單向連結串列————遍歷、查詢、插入結點 (基於C語言實現)C語言
- 手寫單連結串列基礎之增,刪,查!附贈一道連結串列題
- 資料結構--陣列、單向連結串列、雙向連結串列資料結構陣列