一.在指定位置之前插入数据(SeqList.c)
(1)定义函数(SLInsert)
void SLInsert(SL* ps, int pos, SLDataType x) { assert(ps); assert(pos >= 0 && pos <= ps->size); //插入数据:空间够不够 SLCheckCapacity(ps); //让pos及以后的数据整体往后挪动一位 for (int i = ps->size;i > pos; i--) { ps->arr[i] = ps->arr[i - 1];//arr[pos + 1] = arr[pos] } ps->arr[pos] = x; ps->size++; }(2)注意事项
1.pos不能越界,有条件限制(双等号)
2.插入数据之前,调用函数检查空间够不够
3.让pos及以后的数据整体往后挪动一位
4.arr[pos + 1] = arr[pos]
(3)测试函数(test.c)
void SLTest01() { SL s1; SLInit(&s1); SLPushBack(&s1, 1); SLPushBack(&s1, 2); SLPushBack(&s1, 3); SLPushBack(&s1, 4); SLPrint(s1); SLInsert(&s1, 0, 99); SLInsert(&s1, s1.size, 88); SLPrint(s1); SLDestroy(&s1); }运行结果如下:
1 2 3 4
99 1 2 3 4 88
二.删除指定位置的数据(SeqList.c)
void SLErase(SL* ps, int pos) { assert(ps); assert(pos >= 0 && pos < ps->size); for (int i = 0; i < ps->size - 1; i++) { ps->arr[i] = ps->arr[i + 1]; } ps->size--; }(1)测试函数(test.c)
void SLTest01() { SL s1; SLInit(&s1); SLPushBack(&s1, 1); SLPushBack(&s1, 2); SLPushBack(&s1, 3); SLPushBack(&s1, 4); SLPrint(s1); SLErase(&s1, 1); SLPrint(s1); SLDestroy(&s1); }运行结果如下:
1 2 3 4
2 3 4
三.查找数据位置(SeqList.c)
int SLFind(SL* ps, SLDataType x) { assert(ps); for (int i = 0; i < ps->size; i++) { if (ps->arr[i] == x) { return i;//找到啦 } } return -1; }四.顺序表的应用——通讯录!!!!!
(一).顺序表可以存储自定义类型的数据
(二).typedef struct personInfo SLDataType;来方便后续类型的替换
(三).Contact.h是通讯录的头文件,Contact.c是通讯录的实现文件
(四).定义联系人数据结构(Contact.h)
#define NAME_MAX 20 #define GENDER_MAX 10 #define TEL_MAX 20 #define ADDR_MAX 100 //定义联系人数据结构 //姓名 性别 年龄 电话 地址 typedef struct personInfo { char name[NAME_MAX]; char gender[GENDER_MAX]; int age; char tel[TEL_MAX]; char addr[ADDR_MAX]; }peoInfo;注意注意!!!
1.要用到顺序表相关方法,对通讯录的操作实际就是对顺序表进行操作。只需要给顺序表改个名字,叫做通讯录。
2.为了防止报错,(SeqList.h)要加上#include"Contact.h"和typedef peoInfo SLDataType;还有(Contact.h)要加上typedef struct SeqList Contact;[注意是最开始的SeqList顺序表重定义为Contact通讯录]
(五).通讯录的头文件(Contact.h)
#define NAME_MAX 20 #define GENDER_MAX 10 #define TEL_MAX 20 #define ADDR_MAX 100 //定义联系人数据结构 //姓名 性别 年龄 电话 地址 typedef struct personInfo { char name[NAME_MAX]; char gender[GENDER_MAX]; int age; char tel[TEL_MAX]; char addr[ADDR_MAX]; }peoInfo; typedef struct SeqList Contact; //通讯录的相关方法 //通讯录的初始化 void ContactInit(Contact* con); //通讯录的销毁 void ContactDesTroy(Contact* con); //通讯录添加数据 void ContactAdd(Contact* con); //通讯录删除数据 void ContactDel(Contact* con); //通讯录的修改 void ContactModify(Contact* con); //通讯录查找 void ContactFind(Contact* con); //展示通讯录数据 void ContactShow(Contact* con);(六).通讯录的初始化(Contact.c)
//通讯录的初始化 void ContactInit(Contact* con) { //实际上进行的是顺序表的初始化,顺序表的初始化已经实现好了 SLInit(con);//con传过来的已经是地址*了,不需要再取地址& }(七).通讯录的销毁(Contact.c)
//通讯录的销毁 void ContactDesTroy(Contact* con) { SLDestroy(con); }(八).通讯录添加数据(Contact.c)
void ContactAdd(Contact* con) { peoInfo info; printf("请输入要添加的联系人姓名:\n"); scanf_s("%s", info.name); printf("请输入要添加的联系人性别:\n"); scanf_s("%s", info.gender); printf("请输入要添加的联系人年龄:\n"); scanf_s("%d", &info.age);//注意要取地址! printf("请输入要添加的联系人电话:\n"); scanf_s("%s", info.tel); printf("请输入要添加的联系人地址:\n"); scanf_s("%s", info.addr); SLPushBack(con, info);//往通讯录中添加联系人数据!!!!!! }(九).通讯录查找(Contact.c)
1.通讯录查找联系人姓名(初步)
int FindByName(Contact* con, char name[]) { for (int i = 0; i < con->size; i++) { if (0 == strcmp(con->arr[i].name, name))//字符串的比较用strcmp函数 { //找到了 return i; } } return -1; }注意注意:问题!!!
"=="不能用于直接比较结构体!字符串要用strcmp函数来比较,记得先加头文件:#include <string.h>
拓展strcmp函数:int strcmp(const char* str1,const char* str2);
返回0:str1 等于 str2;返回>0:str1 大于 str2;返回<0:str1 小于 str2;
比较规则:按字典序依次比较对应字符的ASCII码,遇到不同字符或\0时停止。
2.通讯录查找并展示联系人信息(进阶)
void ContactFind(Contact* con) { char name[NAME_MAX]; printf("请输入要查找的联系人姓名\n"); scanf("%s", name); int find = FindByName(con, name); if (find < 0) { printf("要查找的联系人数据不存在\n"); } printf("%s %s %s %s %s\n", "姓名","性别", "年龄", "电话", "地址"); printf("%s %s %d %s %s\n",con->arr[find].name, con->arr[find].gender, con->arr[find].age, con->arr[find].tel, con->arr[find].addr); }注意注意:问题!!!
*con为指针,表示时为con->arr[find].age
con为字符串,表示时为con.arr[find].age
(十).通讯录删除数据(Contact.c)
void ContactDel(Contact* con) { //要删除的数据必须要存在,才能执行删除操作 //先查找 char name[NAME_MAX]; printf("请输入要删除的联系人姓名:\n"); scanf("%s", name); int find = FindByName(con, name); if (find < 0) { printf("要删除的联系人数据不存在\n"); return;//直接回车 } //要删除的联系人数据存在,知道了要删除的联系人数据的下标 SLErase(con, find); printf("删除成功!\n"); }(十一).展示通讯录数据(Contact.c)
void ContactShow(Contact* con) { printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址"); for (int i = 0; i < con->size; i++) { printf("%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); } }(十二).通讯录的修改(Contact.c)
void ContactModify(Contact* con) { //要修改的联系人数据存在 char name[NAME_MAX]; printf("请输入要修改的用户姓名:\n"); scanf("%s", name); int find = FindByName(con, name); if (find < 0) { printf("要修改的联系人数据不存在!\n"); return; } //直接修改 printf("请输入新的姓名:\n"); scanf("%s", con->arr[find].name); printf("请输入新的性别:\n"); scanf("%s", con->arr[find].gender); printf("请输入新的年龄:\n"); scanf("%d", &con->arr[find].age);//age不是数组,要取地址!!!!! printf("请输入新的电话:\n"); scanf("%s", con->arr[find].tel); printf("请输入新的地址:\n"); scanf("%s", con->arr[find].addr); }(十三).通讯录的测试方法(test.c)
初阶方法!!!
#include "SeqList.h" //通讯录的测试方法 void ContactTest01() { Contact con;//创建的通讯录对象实际上就是顺序表对象,等价于 SL s1; ContactInit(&con); ContactAdd(&con); ContactAdd(&con); ContactShow(&con); ContactDel(&con); ContactShow(&con); ContactFind(&con); ContactShow(&con); ContactModify(&con); ContactShow(&con); ContactDesTroy(&con); } int main() { ContactTest01(); return 0; }进阶方法!!!!!(菜单menu)
#include "SeqList.h" void menu() { printf("************************通讯录********************\n"); printf("************1.增加联系人 2.删除联系人***********\n"); printf("************3.修改联系人 4.查找联系人***********\n"); printf("************5.展示联系人 0. 退出***************\n"); printf("**************************************************\n"); } int main() { int op = -1; Contact con; ContactInit(&con); do { menu(); printf("请选择你的操作:\n"); scanf("%d", &op); //要根据对应的op执行不同的操作 switch (op) { case 1: ContactAdd(&con); break; case 2: ContactDel(&con); break; case 3: ContactModify(&con); break; case 4: ContactFind(&con); break; case 5: ContactShow(&con); break; case 0: printf("退出通讯录...\n"); break; default: printf("输入错误,请重新选择您的操作!\n"); break; } } while (op != 0); ContactDesTroy(&con); return 0; }(十四).问题分析(2)
问题一:typedef struct personInfo {...} peoInfo;遇到 “personInfo: struct 类型重定义” 错误,错误行在SeqList.h中
原因:重复包含头文件:要是在多个源文件或者头文件里重复包含了定义 struct personInfo 的头文件,就会造成结构体被多次定义。
解决办法:在Contact.h中使用头文件保护机制:在头文件里运用 #ifndef、#define 和 #endif 来避免头文件被重复包含。
示例如下:(Contact.h)
#ifndef PERSON_INFO_H //1 #define PERSON_INFO_H //2 #define NAME_MAX 20 #define GENDER_MAX 10 #define TEL_MAX 20 #define ADDR_MAX 50 typedef struct personInfo { char name[NAME_MAX]; char gender[GENDER_MAX]; int age; char tel[TEL_MAX]; char addr[ADDR_MAX]; } peoInfo; #endif //PERSON_INFO_H问题二:在SeqList.h中加上:
#define _CRT_SECURE_NO_WARNINGS 1