https://www.bilibili.com/video/av77591213
==================
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
我测试了一下,就有一个函数不能用,其余的都是正常的,学到了不少东西啊
还有,判断2个字符串,是否相同,得用strcmp函数,而不是 ==
//============================================================================
// Name : LinkBlank.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<stdbool.h>
#define NO_LENGTH 20
#define NAME_LENGTH 11
/* 定义学生结构体的数据结构 */
typedef struct Student{
char studentNo[NO_LENGTH];
char studentName[NAME_LENGTH];
}st;
/* 定义每条记录或节点的数据结构 */
typedef struct node
{
struct Student data; //数据域
struct node *next; //指针域
}Node, *Link; //Node为node类型的别名,Link为node类型的指针别名
//定义提示菜单
void myMenu(){
printf(" * * * * * * * * * 菜 单 * * * * * * * * * *\n");
printf(" 1 增加学生记录 2 删除学生记录 \n");
printf(" 3 查找学生记录 4 修改学生记录 \n");
printf(" 5 统计学生人数 6 显示学生记录 \n");
printf(" 7 退出系统 \n");
printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
}
void inputStudent(Link l){
printf("请输入学生学号:");
scanf("%s", l->data.studentNo);
printf("请输入学生的姓名:");
scanf("%s", l->data.studentName);
//每个新创建的节点的next域都初始化为NULL
l->next = NULL;
}
//这个是干嘛的???
void inputStudentNo(char s[], char no[]){ //数组名当做函数形参
printf("请输入要%s的学生学号:", s); //char s中的s,代表 修改 查询,删除,等字样
scanf("%s", no);
}
//作业内容,我自己编写的
void displayNode(Link head){
// 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
Link p;
p = head->next;
while (p!=NULL)
{
printf("学生的学号是:%s \n", p->data.studentNo);
printf("学生的姓名是:%s \n", p->data.studentName);
p = p->next;
}
}
/* 增加学生记录 */
bool addNode(Link head){
Link p, q; //p,q两个节点一前一后
Link node; //node指针指向新创建的节点
node = (Link)malloc(sizeof(Node));
inputStudent(node); //传入一个节点,手动输入学生学号和学生姓名这2个数据,传入到结点node当中!,有意思的操作!
q = head;
p = head->next; //q指向head后面的第一个有效节点
if (head->next == NULL)
//链表为空时
head->next = node;
else { //当链表不为空,说明链表本身就有数据的时候,执行下段代码。。
//循环访问链表中的所有节点
while (p != NULL){
if (node->data.studentNo < p->data.studentNo){
//如果node节点的学号比p节点的学号小,则插在p的前面,完成插入后,提前退出子程序
q->next = node;
node->next = p;
return true;
}
else{
//如果node节点的学号比p节点的学号大,继续向后移动指针(依然保持pq一前一后)q....p 这样的顺序。
q = p;
p = p->next;
}
}
//如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
q->next = node;
}
return true;
}
//老师留下的作业,自己完成需要
bool deleteNode(Link head){
// 按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("删除", no);
Link p, q;
if (head==NULL ||head->next==NULL ) //如果链表没有数据,返回false
{
return false;
}
q = head;
p = head->next; //初始化。q,p两个指针,一前一后。
while (p!=NULL)
{
if (strcmp(p->data.studentNo, no) == 0) //判断2个字符串相同,不能用==,而应该用strcmp函数!
{
q->next = p->next;
free(p);
return true;
}
else //如果没有找到,就让两个指针,同时往下一个结点去遍历
{
q = p;
p = p->next;
}
}
//如果循环遍历结束,都没有找到相对应的学号,说过指定学号不在链表当中
return false;
}
//老师留下的作业,自己完成需要,查找学生记录
bool queryNode(Link head){
// 按照给定的学号查询学生记录,如果查询成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("查找", no);
//printf("要查找的数组序号是:%s \n", no);
Link p;
p = head->next;
while (p!=NULL)
{
/*printf("学生的姓名是: %s \n", p->data.studentNo);
printf("学生的姓名是: %s \n", p->data.studentName);*/
if (strcmp(p->data.studentNo,no)==0 ) //判断2个字符串相同,不能用==,而应该用strcmp函数!
{
printf("成功了!该学生的姓名是: %s", p->data.studentName);
return true;
}
p = p->next;
}
//如果循环结束了,说明没有找到
return false;
}
//老师留下的作业,自己完成需要
bool modifyNode(Link head){
// 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
//输入要处理的学号-----------只修改学号,不修改姓名?还是2者都可以随便修改?
char no[NO_LENGTH];
inputStudentNo("修改", no);
if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
{
return false;
}
Link p;
p = head->next;
while (p != NULL)
{
if (strcmp(p->data.studentNo, no) == 0) //当找到用户的学号的时候,
{
printf("学生的姓名是: %s \n", p->data.studentName);
scanf("把此学生姓名修改为: %s \n", p->data.studentName);
return true;
}
p = p->next;
}
return false;
}
//老师留下的作业,自己完成需要
int countNode(Link head){
//统计学生人数,扫描链表统计节点个数,返回节点数
Link p;
int count = 0;
p = head->next;
if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
{
return false;
}
while (p!=NULL)
{
p = p->next;
count++;
}
//填充代码
return count; //注意count的初始值和返回值之间的关系。
}
//老师留下的作业,自己完成需要,我自己写的不知道是否可以。
int clearLink(Link head){
Link q, p;
//遍历链表,用free语句删除链表中用malloc建立起的所有的节点
if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
{
return false;
}
while (head->next!=NULL)
{
q = head;
head = head->next;
free(q);
}
return true;
}
int main() {
int select;
int count;
Link head; // 定义链表
//建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的数据
head = (Link)malloc(sizeof(Node));
head->next = NULL;
while (1)
{
myMenu();
printf("\n请输入你的选择(0-7):"); //显示提示信息
scanf("%d", &select);
switch (select)
{
case 1:
//增加学生记录
if (addNode(head))
printf("成功插入一个学生记录。\n\n");
break;
case 2:
//删除学生记录
if (deleteNode(head))
printf("成功删除一个学生记录。\n\n");
else
printf("没有找到要删除的学生节点。\n\n");
break;
case 3:
//查询学生记录
if (queryNode(head))
printf("成功找到学生记录。\n\n");
else
printf("没有找到要查询的学生节点。\n\n");
break;
case 4:
//修改学生记录
if (modifyNode(head))
printf("成功修改一个学生记录。\n\n");
else
printf("没有找到要修改的学生节点。\n\n");
break;
case 5:
//统计学生人数
count = countNode(head);
printf("学生人数为:%d\n\n", count);
break;
case 6:
//显示学生记录
displayNode(head);
break;
case 7:
//退出前清除链表中的所有结点
clearLink(head);
return 0;
default:
printf("输入不正确,应该输入0-7之间的数。\n\n");
break;
}
}
return 0;
}
=========
我在网上,找到了一个学生的学习笔记,写的比我的好,细节很到位
网址:https://www.yuque.com/jason2018/euoi7a/mxiowo
//============================================================================
// Name : LinkBlank.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<stdbool.h>
#define NO_LENGTH 20
#define NAME_LENGTH 11
/* 定义学生结构体的数据结构 */
typedef struct Student{
char studentNo[NO_LENGTH];
char studentName[NAME_LENGTH];
}st;
/* 定义每条记录或节点的数据结构 */
typedef struct node
{
struct Student data; //数据域
struct node *next; //指针域
}Node, *Link; //Node为node类型的别名,Link为node类型的指针别名
//定义提示菜单
void myMenu(){
printf(" * * * * * * * * * 菜 单 * * * * * * * * * *\n");
printf(" 1 增加学生记录 2 删除学生记录 \n");
printf(" 3 查找学生记录 4 修改学生记录 \n");
printf(" 5 统计学生人数 6 显示学生记录 \n");
printf(" 7 退出系统 \n");
printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
}
void inputStudent(Link l){
printf("请输入学生学号:");
scanf("%s", l->data.studentNo);
printf("请输入学生的姓名:");
scanf("%s", l->data.studentName);
//每个新创建的节点的next域都初始化为NULL
l->next = NULL;
}
//这个是干嘛的???
void inputStudentNo(char s[], char no[]){ //数组名当做函数形参
printf("请输入要%s的学生学号:", s); //char s中的s,代表 修改 查询,删除,等字样
scanf("%s", no);
}
//作业内容,我自己编写的
void displayNode(Link head){
// 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
Link p;
p = head->next;
while (p!=NULL)
{
printf("学生的学号是:%s \n", p->data.studentNo);
printf("学生的姓名是:%s \n", p->data.studentName);
p = p->next;
}
}
/* 增加学生记录 */
bool addNode(Link head){
Link p, q; //p,q两个节点一前一后
Link node; //node指针指向新创建的节点
node = (Link)malloc(sizeof(Node));
inputStudent(node); //传入一个节点,手动输入学生学号和学生姓名这2个数据,传入到结点node当中!,有意思的操作!
q = head;
p = head->next; //q指向head后面的第一个有效节点
if (head->next == NULL)
//链表为空时
head->next = node;
else { //当链表不为空,说明链表本身就有数据的时候,执行下段代码。。
//循环访问链表中的所有节点
while (p != NULL){
if (node->data.studentNo < p->data.studentNo){
//如果node节点的学号比p节点的学号小,则插在p的前面,完成插入后,提前退出子程序
q->next = node;
node->next = p;
return true;
}
else{
//如果node节点的学号比p节点的学号大,继续向后移动指针(依然保持pq一前一后)q....p 这样的顺序。
q = p;
p = p->next;
}
}
//如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
q->next = node;
}
return true;
}
//老师留下的作业,自己完成需要
bool deleteNode(Link head){
// 按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("删除", no);
Link p, q;
if (head==NULL ||head->next==NULL ) //如果链表没有数据,返回false
{
return false;
}
q = head;
p = head->next; //初始化。q,p两个指针,一前一后。
while (p!=NULL)
{
if (strcmp(p->data.studentNo, no) == 0) //判断2个字符串相同,不能用==,而应该用strcmp函数!
{
q->next = p->next;
free(p);
return true;
}
else //如果没有找到,就让两个指针,同时往下一个结点去遍历
{
q = p;
p = p->next;
}
}
//如果循环遍历结束,都没有找到相对应的学号,说过指定学号不在链表当中
return false;
}
//插入一个学生记录
void insertNode(Link head, Link newNode)
{
Link p, q;
bool flag = false; //是否插入成功
p = head;
q = head->next;
//如果是空链表
if (head->next == NULL)
{
head->next = newNode;
flag = true;
}
else
{
//不是空链表
while (q != NULL)
{
/*
① str1小于str2,返回负值或者-1(VC返回-1);
② str1等于str2,返回0;
③ str1大于str2,返回正值或者1(VC返回1);
*/
if (strcmp(newNode->data.studentNo, q->data.studentNo) < 0) //如果newnode小于studentNo,就进行下列操作。。
{
p->next = newNode; //如果不明白,画一下图,立马就明白了。
newNode->next = q;
flag = true;
break;
}
else //如果新增的学生序号大于q->学生序号,那么就顺着循序往下移动。精妙的操作
{
p = q;
q = q->next;
}
}
}
if (q == NULL && flag == false) //如果q指针带头了,或者flag=false,那么久
{
p->next = newNode;
}
}
//老师留下的作业,自己完成需要,查找学生记录
bool queryNode(Link head){
// 按照给定的学号查询学生记录,如果查询成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("查找", no);
//printf("要查找的数组序号是:%s \n", no);
Link p;
p = head->next;
while (p!=NULL)
{
/*printf("学生的姓名是: %s \n", p->data.studentNo);
printf("学生的姓名是: %s \n", p->data.studentName);*/
if (strcmp(p->data.studentNo,no)==0 ) //判断2个字符串相同,不能用==,而应该用strcmp函数!
{
printf("成功了!该学生的姓名是: %s", p->data.studentName);
return true;
}
p = p->next;
}
//如果循环结束了,说明没有找到
return false;
}
//老师留下的作业,自己完成需要
bool modifyNode(Link head){
// 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
//输入要处理的学号-----------只修改学号,不修改姓名?还是2者都可以随便修改?
char no[NO_LENGTH];
char no_new[NO_LENGTH]; //新学号
char name_new[NAME_LENGTH]; //新姓名
int select; //功能选择
Link p, q;
inputStudentNo("修改", no);
printf("请输入需要修改的项目: 1 学号 2 姓名\n");
scanf("%d", &select);
p = head;
q = head->next;
while (q != NULL)
{
if (strcmp(q->data.studentNo, no) == 0) //当在链表中遍历到该学生学号的时候,
{
if (select == 1)
{
p->next = q->next;
q->next = NULL;
printf("请输入该学生的新学号:");
scanf("%s", no_new);
strcpy(q->data.studentNo, no_new);
insertNode(head, q);
}
else
{
printf("请输入该学生的新姓名:");
scanf("%s", name_new);
strcpy(q->data.studentName, name_new);
}
return true;
}
else
{
p = q;
q = q->next;
}
}
return false;
}
//老师留下的作业,自己完成需要
int countNode(Link head){
//统计学生人数,扫描链表统计节点个数,返回节点数
Link p;
int count = 0;
p = head->next;
if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
{
return false;
}
while (p!=NULL)
{
p = p->next;
count++;
}
//填充代码
return count; //注意count的初始值和返回值之间的关系。
}
//老师留下的作业,自己完成需要,我自己写的不知道是否可以。
int clearLink(Link head){
Link q, p;
//遍历链表,用free语句删除链表中用malloc建立起的所有的节点
if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
{
return false;
}
while (head->next!=NULL)
{
q = head;
head = head->next;
free(q);
}
return true;
}
int main() {
int select;
int count;
Link head; // 定义链表
//建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的数据
head = (Link)malloc(sizeof(Node));
head->next = NULL;
while (1)
{
myMenu();
printf("\n请输入你的选择(0-7):"); //显示提示信息
scanf("%d", &select);
switch (select)
{
case 1:
//增加学生记录
if (addNode(head))
printf("成功插入一个学生记录。\n\n");
break;
case 2:
//删除学生记录
if (deleteNode(head))
printf("成功删除一个学生记录。\n\n");
else
printf("没有找到要删除的学生节点。\n\n");
break;
case 3:
//查询学生记录
if (queryNode(head))
printf("成功找到学生记录。\n\n");
else
printf("没有找到要查询的学生节点。\n\n");
break;
case 4:
//修改学生记录
if (modifyNode(head))
printf("成功修改一个学生记录。\n\n");
else
printf("没有找到要修改的学生节点。\n\n");
break;
case 5:
//统计学生人数
count = countNode(head);
printf("学生人数为:%d\n\n", count);
break;
case 6:
//显示学生记录
displayNode(head);
break;
case 7:
//退出前清除链表中的所有结点
clearLink(head);
return 0;
default:
printf("输入不正确,应该输入0-7之间的数。\n\n");
break;
}
}
return 0;
}
网友评论