自学内容网 自学内容网

顺序表操作

题目:

1、通过C语言的数组,实现一个顺序表,对学生信息进行CRUD操作

2、通过命令行窗口,输入操作指令,对顺序表进行操作

  • mymain.h (亮点:使用了转移表,避免大量了printf和switch...case...)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mylist.h"

typedef struct{
char desc[100];//描述
int (*p)(PList);
}Cmd;

int main(int argc, const char *argv[])
{
// 初始化学生表
PList L = createList();
if(NULL == L){
printf("系统初始化失败,系统即将退出.\n");
return -1;
}

// 定义并初始化指令表
Cmd cmdArr[] = {
{"输入学生表的内容", inputList},
{"打印学生表的内容", outputList},
{"插入一名学生", insertStu},
{"删除一名学生", deleteStu},
{"查询学生信息", selectStu},
{"更新学生信息", updateStu},
{"从头部插入一名学生信息", insertHead},
{"从尾部插入一名学生信息", insertRear},
{"删除头部的一名学生", deleteHead},
{"删除尾部的一名学生", deleteRear},
{"去除重复的学生信息", distinct},
{"通过姓名查询学生信息", findAll},
};
int cmdArrLen = sizeof(cmdArr)/sizeof(Cmd);
printf("指令的长度=[%d]\n", cmdArrLen);

while(1){
// 打印操作界面
printf("***************************************\n");
for(int i=0;i<cmdArrLen;i++){
printf("%02d、输入指令[%d]执行操作[%s]\n", i, i, cmdArr[i].desc);
}
// 接受用户指令,执行相关的操作
int userInput=-1;
printf("请输入指令:");
scanf("%d", &userInput);
// 指令的非法性判断
if(userInput<0||userInput>=cmdArrLen){
printf("输入的指令非法!\n");
continue;
}

// 执行相关的指令
cmdArr[userInput].p(L);

// 打印指令的执行结果
// outputList(L);
}

return 0;
}
  • mylist.h
#ifndef _MYLIST_H_
#define _MYLIST_H_

/**********头文件引用************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/**********宏定义************************/
#define MAX 30 //学生数量的上限

/**********结构体定义************************/
typedef struct{
int id;//学号
char name[20];//姓名
int age;//年龄
char major[20];//专业
}Stu, *PStu;

typedef struct{
Stu data[MAX]; // 学生信息
int len; // 统计学生个数
}List,*PList;

/**********函数声明************************/
PList createList(); //顺序表创建函数

int inputList(PList L);//输入学生表内容
int outputList(PList L);//打印顺序打印学生表内容
int insertStu(PList L);//在数组下标为pos的位置之前插入一个元素
int deleteStu(PList L);//删除下标为pos的元素,1-成功,0-失败
int insertStu(PList L);//在数组下标为pos的位置之前插入一个元素
int deleteStu(PList L);//删除下标为pos的元素,1-成功,0-失败
int selectStu(PList L);//查找下标为pos的元素,并打印出来
int updateStu(PList L);//更新
int insertHead(PList L);
int insertRear(PList L);
int deleteHead(PList L);
int deleteRear(PList L);
int distinct(PList L);//去重
int findAll(PList L);//找到所有名字为name的元素并进行打印

int isFull(PList L);//判断学生表是否满,返回1-满,返回0-未满
int isEmpty(PList L);//判断学生表是否为空,返回1-空,返回0-不为空

#endif
  • mylist.c
#include "mylist.h"


//创建顺序表并返回顺序表地址
PList createList(){
PList L=malloc(sizeof(List));
if(NULL == L){
printf("申请空间失败.\n");
return NULL;
}
L->len = 0;
printf("学生表创建成功.\n");
return L;
}

int inputList(PList L){
int num=0;
while(1){
printf("请输入学生的总数: ");
scanf("%d", &num);
if(num>0&&num<MAX)
break;
printf("输入不合法,请重新输入\n");
}
for(int i=0;i<num;i++){
printf("请输入第%d个学生信息:", i+1);
printf("请输入学号:");
scanf("%d", &L->data[i].id);
printf("请输入年龄:");
scanf("%d", &L->data[i].age);
printf("请输入姓名:");
scanf("%s", L->data[i].name);
printf("请输入专业:");
scanf("%s", L->data[i].major);
L->len++;
}
return 0;
}

int outputList(PList L){
for(int i=0;i<L->len;i++){
printf("学号:%d, 年龄:%d, 姓名:%s, 专业:%s\n", L->data[i].id,
L->data[i].age, L->data[i].name, L->data[i].major);
}
return 0;
}

int isFull(PList L){
return L->len >= MAX?1:0;
}

int isEmpty(PList L){
return L->len<=0?1:0;
}

int insertStu(PList L){
int pos=-1;
// 输入要插入的下标
while(1){
printf("请输入插入的下标:\n");
scanf("%d", &pos);

//异常判断
if(pos<0||pos > L->len||NULL == L||isFull(L)){
printf("插入异常");
continue;
}
break;
}

// 输入学生信息
Stu e;
printf("请输入学号:");
scanf("%d", &e.id);
printf("请输入年龄:");
scanf("%d", &e.age);
printf("请输入姓名:");
scanf("%s", e.name);
printf("请输入专业:");
scanf("%s", e.major);

//pos开始向后移动一个位置
for(int i=L->len;i>=pos;i--){
L->data[i] = L->data[i-1];
}

//在pos位置插入该元素
L->data[pos] = e;

// 总长度+1
L->len++;
return 0;
}

int deleteStu(PList L){
int pos=-1;
//下标
while(1){
printf("请输入删除的元素下标:\n");
scanf("%d", &pos);

//异常判断
if(NULL == L|| isEmpty(L)||pos<0||pos>L->len-1){
printf("输入不合法,请重新输入\n");
continue;
}
break;
}

for(int i=pos;i<L->len-1;i++){
L->data[i]=L->data[i+1];
}

L->len--;
return 1;
}

int selectStu(PList L){
int pos=-1;
while(1){
printf("请输入查询的元素下标:");
scanf("%d", &pos);

//异常判断
if(NULL == L|| isEmpty(L)||pos<0||pos>L->len-1){
printf("输入不合法,请重新输入\n");
continue;
}
break;
}

printf("学号:%d, 年龄:%d, 姓名:%s, 专业:%s\n", L->data[pos].id,
L->data[pos].age, L->data[pos].name, L->data[pos].major);



return 0;
}

int updateStu(PList L){
int pos=-1;
// 下标
while(1){
printf("请输入更新的元素下标:\n");
scanf("%d", &pos);

//异常判断
if(pos<0||pos > L->len-1){
printf("输入异常");
continue;
}
break;
}

// 输入学生信息
Stu e;
printf("请输入学号:");
scanf("%d", &e.id);
printf("请输入年龄:");
scanf("%d", &e.age);
printf("请输入姓名:");
scanf("%s", e.name);
printf("请输入专业:");
scanf("%s", e.major);

L->data[pos] = e;
printf("更新成功.\n");
return 0;
}

int insertHead(PList L){
int pos=0;

// 输入学生信息
Stu e;
printf("请输入学号:");
scanf("%d", &e.id);
printf("请输入年龄:");
scanf("%d", &e.age);
printf("请输入姓名:");
scanf("%s", e.name);
printf("请输入专业:");
scanf("%s", e.major);

//pos开始向后移动一个位置
for(int i=L->len;i>=pos;i--){
L->data[i] = L->data[i-1];
}

//在pos位置插入该元素
L->data[pos] = e;

// 总长度+1
L->len++;
return 0;
}


int insertRear(PList L){
int pos=L->len;

// 输入学生信息
Stu e;
printf("请输入学号:");
scanf("%d", &e.id);
printf("请输入年龄:");
scanf("%d", &e.age);
printf("请输入姓名:");
scanf("%s", e.name);
printf("请输入专业:");
scanf("%s", e.major);

//pos开始向后移动一个位置
for(int i=L->len;i>=pos;i--){
L->data[i] = L->data[i-1];
}

//在pos位置插入该元素
L->data[pos] = e;

// 总长度+1
L->len++;

return 0;
}

int deleteHead(PList L){
int pos=0;
//下标
while(1){
printf("请输入删除的元素下标:\n");
scanf("%d", &pos);

//异常判断
if(NULL == L|| isEmpty(L)||pos<0||pos>L->len-1){
printf("输入不合法,请重新输入\n");
continue;
}
break;
}

for(int i=pos;i<L->len-1;i++){
L->data[i]=L->data[i+1];
}

L->len--;
return 0;
}

int deleteRear(PList L){
int pos=L->len-1;
//下标
while(1){
printf("请输入删除的元素下标:\n");
scanf("%d", &pos);

//异常判断
if(NULL == L|| isEmpty(L)||pos<0||pos>L->len-1){
printf("输入不合法,请重新输入\n");
continue;
}
break;
}

for(int i=pos;i<L->len-1;i++){
L->data[i]=L->data[i+1];
}

L->len--;
return 1;
}

int isEqual(Stu s1, Stu s2){
if(s1.id != s2.id)
return 0;
if(s1.age != s2.age)
return 0;
if(strcmp(s1.name, s2.name) != 0)
return 0;
if(strcmp(s1.major, s2.major) != 0)
return 0;

return 1;
}

int distinct(PList L){
for(int i=0;i<L->len;i++){
for(int j=L->len-1;j>i;j--){
if(isEqual(L->data[i], L->data[j])){
for(int k=i;k<L->len-1;k++){
L->data[k]=L->data[k+1];
}
L->len--;
}
}
}
return 0;
}

int findAll(PList L){
char name[100];
printf("请输入要查询的学生姓名:\n");
scanf("%s", name);
int sub=-1;
for(int i=0;i<L->len;i++){
if(strcmp(L->data[i].name, name) == 0){
printf("姓名[%s]的下标是[%d]\n", name, i);
sub = i;
}
}
if(sub == -1){
printf("该学生不存在.\n");
}
return 0;
}

需要探究的问题:

1、转移表的使用,特别在参数数量和类型都不确定的情况,如何处理。可以看看pirntf函数的源码是怎么编写的;

2、mylist.c 目前的代码量是319行,有时间可以缩写下,挑战100行以下(static 函数的封装);

3、C语言中,是否也有深浅拷贝,以及相关的应用;

4、头文件卫士的应用,避免同一个头文件重复引用和循环引用(参考华为的C编码规范)。


原文地址:https://blog.csdn.net/tjzhuorui/article/details/142369360

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!