C语言编写学生成绩管理系统-要求有增删改查(C语言基础题-9道)

1-5题

C语言基础例题1-3题-指针篇
C语言基础例题4-5题-二维数组篇
C语言基础例题6-7题-结构体篇

题目

例题8(难度★ ★ ★ ★ ☆)

编写一个学生成绩管理系统,实现以下功能:

  1. 添加学生信息:从键盘输入学生的姓名和成绩,将学生信息添加到系统中。
  2. 删除学生信息:从键盘输入要删除的学生姓名,若学生存在则将其从系统中删除。
  3. 查找学生信息:从键盘输入要查询的学生姓名,若学生存在则显示学生姓名和成绩,否则提示查无此人。
  4. 修改学生成绩:从键盘输入要修改成绩的学生姓名和新的成绩,若学生存在则将其成绩修改为新的成绩。
  5. 显示所有学生信息:显示系统中所有学生的姓名和成绩。
  6. 退出程序:结束学生成绩管理系统。

运行结果如下所示:
在这里插入图片描述

例题9(难度★ ★ ☆ ☆ ☆)

编写一个程序,要求用户输入一个字符串,然后计算该字符串的长度,并输出结果。

测试用例
输入:“Hello” 输出:长度为5
输入:“This is a test” 输出:长度为14
输入:“1234567890” 输出:长度为10
输入:" " 输出:长度为1
输入:“” 输出:长度为0
输入:“Special characters: *&^%$#@!” 输出:长度为28

答案

例题8

答案1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义学生信息结构体
typedef struct
{
    
    
    char name[20];
    int score;
} Student;

// 定义链表节点结构体
typedef struct Node
{
    
    
    Student data;
    struct Node *next;
} Node;

// 在链表末尾添加新节点(学生信息)
void addStudent(Node *head)
{
    
    
    Node *p = head;
    while (p->next != NULL)
    {
    
    
        p = p->next;
    }

    Node *newNode = (Node *)malloc(sizeof(Node));
    printf("请输入学生姓名:");
    scanf("%s", newNode->data.name);
    printf("请输入成绩:");
    scanf("%d", &(newNode->data.score));
    newNode->next = NULL;

    p->next = newNode;

    printf("添加成功!\n");
}

// 根据学生姓名删除节点
void deleteStudent(Node *head)
{
    
    
    char name[20];
    printf("请输入要删除的学生姓名:");
    scanf("%s", name);

    Node *p = head->next;
    Node *prev = head;

    while (p != NULL)
    {
    
    
        if (strcmp(p->data.name, name) == 0)
        {
    
     // 学生姓名匹配,删除节点
            prev->next = p->next;
            free(p);
            printf("删除成功!\n");
            return;
        }

        prev = p;
        p = p->next;
    }

    printf("查无此人!\n");
}

// 根据学生姓名查找学生信息
void findStudent(Node *head)
{
    
    
    char name[20];
    printf("请输入要查询的学生姓名:");
    scanf("%s", name);

    Node *p = head->next;

    while (p != NULL)
    {
    
    
        if (strcmp(p->data.name, name) == 0)
        {
    
     // 学生姓名匹配,显示学生信息
            printf("姓名:%s\t成绩:%d\n", p->data.name, p->data.score);
            return;
        }

        p = p->next;
    }

    printf("查无此人!\n");
}

// 根据学生姓名修改学生成绩
void modifyScore(Node *head)
{
    
    
    char name[20];
    int newScore;
    printf("请输入要修改成绩的学生姓名:");
    scanf("%s", name);
    printf("请输入新的成绩:");
    scanf("%d", &newScore);

    Node *p = head->next;

    while (p != NULL)
    {
    
    
        if (strcmp(p->data.name, name) == 0)
        {
    
     // 学生姓名匹配,修改成绩
            p->data.score = newScore;
            printf("修改成功!\n");
            return;
        }

        p = p->next;
    }

    printf("查无此人!\n");
}

// 显示所有学生信息
void displayStudents(Node *head)
{
    
    
    Node *p = head->next;

    while (p != NULL)
    {
    
    
        printf("姓名:%s\t成绩:%d\n", p->data.name, p->data.score);
        p = p->next;
    }
}

int main()
{
    
    
    Node *head = (Node *)malloc(sizeof(Node));
    head->next = NULL;

    int option;

    do
    {
    
    
        printf("【菜单】\n");
        printf("1. 添加学生信息\n");
        printf("2. 删除学生信息\n");
        printf("3. 查找学生信息\n");
        printf("4. 修改学生成绩\n");
        printf("5. 显示所有学生信息\n");
        printf("6. 退出程序\n");
        printf("\n请选择菜单选项:");
        scanf("%d", &option);

        switch (option)
        {
    
    
        case 1:
            addStudent(head);
            break;
        case 2:
            deleteStudent(head);
            break;
        case 3:
            findStudent(head);
            break;
        case 4:
            modifyScore(head);
            break;
        case 5:
            displayStudents(head);
            break;
        case 6:
            printf("程序结束!\n");
            break;
        default:
            printf("错误!没有此选项!\n");
            break;
        }
    } while (option != 6);

    // 释放链表内存
    Node *p = head;
    while (p != NULL)
    {
    
    
        Node *temp = p->next;
        free(p);
        p = temp;
    }

    return 0;
}
解析

struct _StudentItem:定义了学生信息的结构体。它包含一个char数组name用于存储学生姓名,一个int变量score用于存储成绩。

struct Node:定义了链表节点的结构体。它包含了一个Student类型的数据成员data用于存储学生信息,以及一个指向下一个节点的指针next。

addStudent:在链表末尾添加新节点(学生信息)。该函数首先遍历链表,找到最后一个节点,然后创建一个新节点,要求用户输入学生的姓名和成绩,并将新节点添加到链表末尾。

deleteStudent:根据学生姓名删除节点。该函数要求用户输入要删除的学生姓名,然后从链表头开始遍历每个节点,寻找匹配的学生姓名。如果找到匹配的节点,则删除该节点,并释放内存。如果没有找到匹配的节点,输出"查无此人!"。

findStudent:根据学生姓名查找学生信息。该函数要求用户输入要查询的学生姓名,然后从链表头开始遍历每个节点,寻找匹配的学生姓名。如果找到匹配的节点,则输出该学生的姓名和成绩。如果没有找到匹配的节点,输出"查无此人!"。

modifyScore:根据学生姓名修改学生成绩。该函数要求用户输入要修改成绩的学生姓名和新的成绩,然后从链表头开始遍历每个节点,寻找匹配的学生姓名。如果找到匹配的节点,则修改该节点的成绩为新的成绩。如果没有找到匹配的节点,输出"查无此人!"。

displayStudents:显示所有学生信息。该函数从链表头开始遍历每个节点,并输出每个节点的学生姓名和成绩。

在主函数里,我们首先创建了一个链表头指针head,然后使用一个菜单循环,等待用户输入菜单选项。根据用户的选择,调用相应的函数执行相应的功能。直到用户选择退出程序为止。最后,释放了链表的内存。

相比起答案2,这个的链表位置是添加在最后的,每次都要遍历一次,这一步可以优化。

答案2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义学生信息结构体
typedef struct _StudentItem
{
    
    
    char name[9];
    float grade;
} StudentItem;
// 定义链表节点结构体
typedef struct _StudentNode
{
    
    
    StudentItem item;
    struct _StudentNode *next;
} StudentNode;
// 在链表开头添加新节点(学生信息)
void AddStudent(StudentNode **student);
// 根据学生姓名删除节点
void DeleteStudent(StudentNode **student, char *name);
// 根据学生姓名修改学生成绩
void ModifyGrades(StudentNode *student, float grade);
// 显示所有学生信息
void displayStudents(StudentNode **student);
// 根据学生姓名查找学生信息
StudentNode *FindStudent(StudentNode **student, char *name);
// 释放链表内存
void FreeNode(StudentNode **student);

int main(void)
{
    
    
    StudentNode *student = NULL, *target;
    int selection;
    char name[9];
    float grade;
    printf("【菜单】\n1.添加学生信息\n2.删除学生信息\n3.查找学生信息\n4.修改学生成绩\n5.显示所有学生信息\n6.退出程序\n");
    while (scanf("%d", &selection) == 1 && selection != 6)
    {
    
    
        switch (selection)
        {
    
    
        case 1:
            AddStudent(&student);
            break;
        case 2:
            printf("请输入要删除的学生名:");
            scanf("%s", name);
            DeleteStudent(&student, name);
            break;
        case 3:
            printf("请输入要查询的学生名:");
            scanf("%s", name);
            target = FindStudent(&student, name);
            if (target == NULL)
                printf("查无此人!\n");
            else
                printf("姓名:%s\t成绩:%f\n", target->item.name, target->item.grade);
            break;
        case 4:
            printf("请输入要修改成绩的学生名:");
            scanf("%s", name);
            target = FindStudent(&student, name);
            if (target == NULL)
                printf("查无此人!\n");
            else
            {
    
    
                printf("请输入新的成绩:");
                scanf("%f", &grade);
                ModifyGrades(target, grade);
                puts("修改成功");
            }
            break;
        case 5:
            displayStudents(&student);
            break;
        default:
            printf("错误!没有此选项!\n");
            break;
        }
        printf("继续输入选项:\n");
    }
    FreeNode(&student);
    getchar();
    getchar();
    return 0;
}
void AddStudent(StudentNode **student)
{
    
    
    StudentNode *temp = (StudentNode *)malloc(sizeof(StudentNode));
    printf("请输入学生姓名:");
    scanf("%s", temp->item.name);
    printf("请输入成绩:");
    scanf("%f", &temp->item.grade);
    temp->next = *student;
    *student = temp;
}
void DeleteStudent(StudentNode **student, char *name)
{
    
    
    StudentNode *target = *student, *prev;
    // 学生姓名匹配,删除节点
    if (target != NULL && !strcmp(target->item.name, name))
    {
    
    
        *student = target->next;
    }
    else
    {
    
    
        prev = target;
        target = target->next;
        while (target != NULL)
        {
    
    
            // 学生姓名匹配,删除节点
            if (!strcmp(target->item.name, name))
            {
    
    
                prev->next = target->next;
                break;
            }
            prev = target;
            target = target->next;
        }
    }
    if (target != NULL)
    {
    
    

        free(target);
        printf("删除成功!\n");
    }
    else
    {
    
    
        printf("删除失败!\n");
    }
}
void ModifyGrades(StudentNode *student, float grade)
{
    
    
    student->item.grade = grade;
}
StudentNode *FindStudent(StudentNode **student, char *name)
{
    
    
    StudentNode *p = *student;
    while (p != NULL)
    {
    
    
        // 学生姓名匹配,返回学生节点
        if (!strcmp(p->item.name, name))
            break;
        p = p->next;
    }
    return p;
}
void displayStudents(StudentNode **student)
{
    
    
    const StudentNode *p = *student;
    if (*student == NULL)
    {
    
    
        printf("没有学生数据\n");
    }
    else
    {
    
    
        while (p != NULL)
        {
    
    
            printf("姓名:%s\t成绩%f\n", p->item.name, p->item.grade);
            p = p->next;
        }
    }
}
void FreeNode(StudentNode **student)
{
    
    
    StudentNode *target=*student,*next;
    while(target!=NULL)
    {
    
    
        next=target->next;
        free(target);
        target=next;
    }
}
解析

我们使用链表来存储学生的信息,也就是姓名和成绩。根据题目要求需要实现添加学生、删除学生、查找学生、修改学生的成绩、显示所有学生的信息,退出的功能。

首先,我们定义了两个结构体:StudentItem 和 StudentNode。StudentItem 用来存储学生的姓名和成绩,而 StudentNode 用来表示链表中的节点,它包含一个 StudentItem 类型的变量和一个指向下一个节点的指针。

然后,我们实现一些函数来完成不同的操作。AddStudent 函数用于在链表开头添加一个新的学生节点;DeleteStudent 函数用于根据学生的姓名来删除对应的节点;ModifyGrades 函数根据学生的姓名来修改他们的成绩;displayStudents 函数显示所有学生的信息;FindStudent 函数根据学生的姓名来查找他们的信息;最后,FreeNode 函数用来释放链表的内存。

在主函数中,我们通过一个循环来让用户选择要执行的操作。根据用户的输入,我们会调用相应的函数来处理操作。比如,如果用户选择添加学生,我们会创建一个新的节点,然后获取学生的姓名和成绩,最后将其添加到链表的开头。

如果要删除学生,我们先根据学生的姓名找到对应的节点,然后将其从链表中删除并释放其内存。修改学生的成绩,先根据学生的姓名找到对应的节点,然后更改他的成绩。显示所有学生的信息,就遍历链表并打印每个学生的姓名和成绩。

在程序结束时,记得释放链表的内存。

相比答案1,这个链表的开头只使用了一个指针,没有一个空的结构体,所以省了一个结构体的空间,嗯,没什么用。而且造成添加等操作会多出几行代码来。

另外就是链表的添加顺序了,这个是添加在开头,速度很快,答案一添加之前还要找到末尾,较慢。

例题9

答案1

#include <stdio.h>
int main(void)
{
    
    
    int sum = 0;
    while (getchar() != '\n')
        sum++;
    printf("长度为%d\n", sum);

    getchar();
    return 0;
}
解析

首先定义一个整型变量sum并初始化为0。然后使用一个while循环来读取用户输入的字符,每读取一个字符,就将sum的值加1,直到遇到换行符\n为止。这样就可以统计出用户输入的字符个数。

接着使用printf函数打印出统计得到的字符长度。

这个方法比下面两个简单,但是缺点是从缓冲区独走字符后,全部都删掉了,没有保存下来用户输入的字符串。

答案2

#include <stdio.h>
#include <string.h>
int main(void)
{
    
    
    char str[50];
    int i = 0;
    printf("请输入:");
    while ((str[i] = getchar()) != '\n')
        i++;
    str[i] = '\0'; // 添加字符串结束符
    printf("长度为%d\n", strlen(str));
    getchar();
    return 0;
}
解析

char str[50]; 声明一个字符数组 str,用于存储用户输入的字符串,最大长度为 50。

int i = 0; 声明一个整型变量 i,用于循环和计数。

while ((str[i] = getchar()) != ‘\n’)。这个循环的作用是逐个字符读取用户输入并存储到 str 中,直到遇到换行符 \n 为止。

i++; 每次循环结束后将变量 i 自增,用于确保存储下一个字符的位置。

printf(“长度为%d\n”, strlen(str)); 输出字符串的长度,使用了 strlen 函数来计算字符串的长度。

比答案1要多几个步骤,而且此处直接延伸答案1的算法,不去使用strlen也可以。

答案3

#include <stdio.h>
#include <string.h>

int main()
{
    
    
    char str[100];
    printf("请输入一个字符串: ");
    fgets(str, 100, stdin);

    // 去掉输入字符串的换行符
    str[strcspn(str, "\n")] = 0;

    int length = strlen(str);
    printf("输入字符串的长度为: %d\n", length);
    
    return 0;
}
解析

char str[100]; 声明一个字符数组 str,用于存储用户输入的字符串,最大长度为 100。

fgets(str, 100, stdin); 使用 fgets 函数从标准输入流 stdin 中获取用户输入的字符串,最多读取 99 个字符(包括空字符),并存储到 str 中。

str[strcspn(str, “\n”)] = 0; 使用 strcspn 函数找到 str 中换行符 \n 的位置,并将其替换为字符串结束符 \0,从而去掉字符串结尾的换行符。

int length = strlen(str); 使用 strlen 函数计算字符串 str 的长度,并将结果存储在 length 变量中。

printf(“输入字符串的长度为: %d\n”, length); 输出字符串的长度。

比前两个看着额,至少这道题不是在学fgets和strcspn之前出现的,所以老师看了都会夸你。

猜你喜欢

转载自blog.csdn.net/weixin_44499065/article/details/134244634