实验14 完善课堂随机点名实验,要求:1.用文件存放学生名单;2.输出学号+姓名;3.用函数实现这一功能。

实验14
完善课堂随机点名实验,要求:1.用文件存放学生名单;2.输出学号+姓名;3.用函数实现这一功能。
c语言

私我发你文件,一步步教你

img

代码如下,可一直循环点名,直到全部学生点名完毕,可重置。
如有帮助,望采纳!

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

//课堂随机点名
//fileName:学生名单文件,格式(学号 姓名)
//num:已经点名的学生学号
//n:已经点名的学生人数
int classRollCall(const char *fileName, int num[], int *n)
{
    FILE *fp = fopen(fileName, "r");
    if(fp == NULL) {
        return -1;
    }
    int id[100], currId, m, k = 0, flag, s = 0;
    char name[100][20], currName[20];
    while (!feof(fp)) { //读取文件中的所有学生信息
        fscanf(fp, "%d %s\n", &id[k], name[k]);
        k++;
    }
    fclose(fp);
    if(*n == k) {
        printf("点名完毕!\n");
        return -2;
    }
    srand(time(NULL));
    m = rand() % (k - *n) + 1; //生成随机数,剩余的人数
    for(int i=0; i<k; i++) {
        flag = 0;
        for(int j=0; j<*n; j++) {
            if(id[i] == num[j]) {
                flag = 1;
                break;
            }
        }
        if(flag == 0) {
            s++;
            if(s == m) {
                currId = id[i];
                strcpy(currName, name[i]);
                break;
            }
        }
    }
    num[*n] = currId;
    (*n)++;
    printf("当前随机数: %d\n", m);
    printf("幸运同学学号: %d  姓名: %s\n", currId, currName);
    printf("剩余人数为: %d\n", k - *n);
    return 0;
}

int main()
{
    int select;
    int num[100], n = 0;
    while(1) {
        printf("请输入(0退出 1开始/继续点名 2重置): ");
        scanf("%d", &select);
        if(select == 0) {
            break;
        }
        else if(select == 1) {
            classRollCall("student.txt", num, &n);
        }
        else if(select == 2) {
            n = 0;
            printf("随机点名重置成功!\n");
        }
        printf("\n");
    }
    return 0;
}

如有帮助,望采纳

1. byname.h
(包含宏的定义、头文件的引用以及函数的声明和结构体的创建)
(不要忘记在后面两个文件中都要引用这个头文件)
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>

#define MAX 100

//创建一个结构体
typedef struct StuInfo
{
    int id;
    char name[MAX];
}StuInfo;

void stu_open(char* file, FILE* fp,StuInfo* s,int num);
void stu_byname(char* file,StuInfo* s,int num);
void stu_add(char* file,StuInfo* s,int num);
void stu_del(char* file,StuInfo* s,int num);
void stu_located(char* file,StuInfo* s,int num);
void stu_show(char* file,StuInfo* s,int num);
void stu_multify(char* file,StuInfo* s,int num);
void stu_sort(char* file,StuInfo* s,int num);
void stu_close(char* file, FILE* fp);

2. byname.c
(包含各种功能函数的实现)
#define _CRT_SECURE_NO_WARNINGS 1

#include "byname.h"

//将文件内容读入结构体中
void stu_open(char* file, FILE* fp,StuInfo* s,int num)
{
    int i = 0;
    //stu_write(file, fp, count);
    fscanf(fp, "%d", &num);
    for (i = 0; i < num; i++)
    {
        fscanf(fp, "%d %s", &(s[i].id), s[i].name);
    }
    return;
}

//随机点名
void stu_byname(char* file,StuInfo* s,int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d", &num);
    //stu_open(file, fp, s, num);
    int i = 0;
    //得到随机数
    i = rand() % num;
    printf("\n学号:  %d\n姓名:  %s\n", s[i].id, s[i].name);
}

//添加学生信息
void stu_add(char* file, StuInfo* s, int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d", &num);
    int i = 0;
    int j = 0;
    int m = 0;
    char str[20] = { 0 };
    printf("请输入添加学生的学号和姓名:>");
    scanf("%d  %s", &m, &str);

    //判断该学号是否已经存在
    for (i = 0; i < num; i++)
    {
        if (m == s[i].id)
        {
            printf("该学号已存在!\n");
            printf("添加失败!\n");
            break;
        }
    }

    //若不存在,则对该学生进行添加
    if (i == num)
    {
        num = num + 1;
        //重置文件指针到文件开头,并重新写入班级人数
        rewind(fp);
        fprintf(fp, "%d", num);
        //将文件指针移至文件末尾,写入新添加的学生
        fseek(fp, 0, SEEK_END);
        fprintf(fp, "\n%d %s", m, str);
        printf("添加成功\n");
    }
}

//删除菜单
void menu_del()
{
    printf("*********************************\n");
    printf("*********  1.按学号删除 *********\n");
    printf("*********  2.按姓名删除 *********\n");
    printf("*********   0.取消删除  *********\n");
    printf("*********************************\n");
}

//按学号删除
void stu_del_id(char* file, FILE* fp,StuInfo* s,int num)
{
    int m = 0;
    int i = 0;
    int j = 0;
    int k = 0;
    int flag = 0;
    
    printf("请输入要删除的学号:>");
    scanf("%d", &m);
    for (i = 0; i < num; i++)
    {
        if (m == s[i].id)
        {
            //确认是否删除
            printf("该学生信息为:\n");
            printf("学号:>%d    姓名:>%s\n", s[i].id, s[i].name);
            printf("您确定要删除这位学生的信息吗?(0/1):>");
            scanf("%d", &flag);
            switch (flag)
            {
            case 1:
                for (j = i; j < num; j++)
                {
                    s[j] = s[j + 1];
                }
                num--;
                //重置文件指针到文件开头,并重新写入班级人数
                rewind(fp);
                fprintf(fp, "%d\n", num);
                for (k = 0; k < num; k++)
                {
                    fprintf(fp, "%d %s", s[k].id, s[k].name);
                    if (k < num - 1)
                    {
                        fputc('\n', fp);
                    }
                }
                printf("删除成功!\n");
                break;
            case 0:
                printf("操作成功!取消删除,返回上级菜单!\n");
                break;
            default:
                printf("输入错误!请重新输入:>\n");
                break;
            }
            break;
        }
    }
    if (i == num)
    {
        printf("该学号不存在!\n");
        printf("删除失败!\n");
    }

}

//按姓名删除
void stu_del_name(char* file, FILE* fp,StuInfo* s,int num)
{
    int i = 0;
    int j = 0;
    int k = 0;
    int flag = 0;
    char str[20] = { 0 };
    //fscanf(fp, "%d\n", &num);
    //stu_open(file, fp, s, num);
    printf("请输入要删除的姓名:>");
    scanf("%s", &str);
    for (i = 0; i < num; i++)
    {
        if (strcmp(s[i].name, str) == 0)
        {
            //确认是否删除
            printf("该学生信息为:\n");
            printf("学号:>%d    姓名:>%s\n", s[i].id, s[i].name);
            printf("您确定要删除这位学生的信息吗?(0/1):>");
            scanf("%d", &flag);
            switch (flag)
            {
            case 1:
                for (j = i; j < num; j++)
                {
                    s[j] = s[j + 1];
                }
                num--;
                //重置文件指针到文件开头,并重新写入班级人数
                rewind(fp);
                fprintf(fp, "%d\n", num);
                for (k = 0; k < num; k++)
                {
                    fprintf(fp, "%d %s", s[k].id, s[k].name);
                    if (k < num - 1)
                    {
                        fputc('\n', fp);
                    }
                }
                printf("删除成功!\n");
                break;
            case 0:
                printf("操作成功!取消删除,返回上级菜单!\n");
                break;
            default:
                printf("输入错误!请重新输入:>\n");
                break;
            }
            break;
        }
    }
    if (i == num)
    {
        printf("该姓名不存在!\n");
        printf("删除失败!\n");
    }
}

//删除学生信息
void stu_del(char* file, StuInfo* s, int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d", &num);
    stu_close(file, fp);
    //关闭该文件,并重新以"w+"的方式打开该文件
    FILE* ffp = fopen(file, "w+");
    int input = 0;
    int k = 0;
    do
    {
        menu_del();
        printf("请输入删除方式:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            stu_del_id(file, fp,s,num);
            break;
        case 2:
            stu_del_name(file, fp,s,num);
            break;
        //由于是以"w+"的方式打开的文件,里面的内容会被清空,因此,若取消或退出删除,需要将结构体的内容再写入文件中
        case 0:
            fprintf(ffp, "%d\n", num);
            for (k = 0; k < num; k++)
            {
                fprintf(ffp, "%d %s", s[k].id, s[k].name);
                if (k < num - 1)
                {
                    fputc('\n', ffp);
                }
            }
            printf("退出删除!\n");
            break;
        default:
            rewind(ffp);
            fprintf(ffp, "%d\n", num);
            for (k = 0; k < num; k++)
            {
                fprintf(ffp, "%d %s", s[k].id, s[k].name);
                if (k < num - 1)
                {
                    fputc('\n', ffp);
                }
            }
            printf("输入错误!请重新输入!\n");
            break;
        }
        stu_close(file, ffp);
    } while (input);
}

//查询菜单
void menu_located()
{
    printf("--------------------------\n");
    printf("-------1.按学号查询-------\n");
    printf("-------2.按姓名查询-------\n");
    printf("-------0.退出查询---------\n");
    printf("--------------------------\n");
}

//按学号查询
void located_id(StuInfo* s, int num)
{
    int m = 0;
    int i = 0;
    printf("请输入要查询的学号:>");
    scanf("%d", &m);
    for (i = 0; i < num; i++)
    {
        if (m == s[i].id)
        {
            //查询成功,输出该学生信息
            printf("该学生信息为:\n");
            printf("学号:>%d    姓名:>%s\n", s[i].id, s[i].name);
            break;
        }
    }
    if (i == num)
    {
        printf("该学号不存在!\n");
    }
}

//按姓名查询
void located_name(StuInfo* s, int num)
{

    char s1[MAX];
    int i = 0;
    int j = 0;

    printf("请输入要查询的姓名:>");
    scanf("%s", &s1);
    for (i = 0; i < num; i++)
    {
        if (strcmp(s1, s[i].name) == 0)
        {
            printf("学号:>%d    姓名:>%s\n", s[i].id, s[i].name);
            break;
        }
    }
    if (i == num)
    {
        printf("该姓名不存在!\n");
    }
}

//查询信息
void stu_located(char* file, StuInfo* s, int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d", &num);
    int input = 0;
    do
    {
        menu_located();
        printf("请选择查询方式:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            located_id(s,num);
            break;
        case 2:
            located_name(s,num);
            break;
        case 0:
            break;
        default:
            printf("输入错误!请重新输入:>\n");
            break;
        }
    } while (input);
}

//修改菜单
void menu_multify()
{
    printf("*******************************\n");
    printf("*********  1.修改学号 *********\n");
    printf("*********  2.修改姓名 *********\n");
    printf("*********  0.取消修改 *********\n");
    printf("*******************************\n");
}

//输入学号进行修改
void multify_id(char* file, FILE* fp, StuInfo* s, int num)
{
    //fscanf(fp, "%d", &num);
    char s1[20] = { 0 };
    int i = 0;
    int j = 0;
    int k = 0;
    int m = 0;
    int n = 0;
    printf("请输入要修改学生的学号:>");
    scanf("%d", &m);
    for (i = 0; i < num; i++)
    {
        if (m == s[i].id)
        {
            printf("当前学生的学号为:>%d    姓名为:>%s\n", s[i].id, s[i].name);
            printf("请输入修改后的学号:>");
            scanf("%d", &n);

            //判断修改后的学号是否已存在
            for (k = 0; k < num; k++)
            {
                if (n == s[k].id)
                {
                    printf("该学号已存在!\n");
                    printf("该学号学生姓名为:>%s\n", s[k].name);
                    break;
                }
            }
            if (k == num)
            {
                s[i].id = n;
                printf("修改后该学生的学号为:>%d    姓名为:>%s\n", s[i].id, s[i].name);
                rewind(fp);
                fprintf(fp, "%d\n", num);
                for (j = 0; j < num; j++)
                {
                    fprintf(fp, "%d %s", s[j].id, s[j].name);
                    if (j < num - 1)
                    {
                        fputc('\n', fp);
                    }
                }
                printf("修改成功!\n");
                break;
            }
        }
    }
    if (i > num)
    {
        printf("该学号不存在!\n");
        printf("修改失败!\n");
    }
}

//输入姓名进行修改
void multify_name(char* file, FILE* fp, StuInfo* s, int num)
{
    //fscanf(fp, "%d", &num);
    char s1[20] = { 0 };
    char s2[20] = { 0 };
    int i = 0;
    int j = 0;
    int k = 0;
    int m = 0;
    printf("请输入要修改学生的姓名:>");
    scanf("%s", &s1);
    for (i = 0; i < num; i++)
    {
        if (strcmp(s1, s[i].name) == 0)
        {
            printf("当前学生的学号为:>%d    姓名为:>%s\n", s[i].id, s[i].name);
            printf("请输入修改后的姓名:>");
            scanf("%s", s1);
            strcpy(s[i].name, s1);
            printf("修改后该学生的学号为:>%d    姓名为:>%s\n", s[i].id, s[i].name);
            rewind(fp);
            fprintf(fp, "%d\n", num);
            for (j = 0; j < num; j++)
            {
                fprintf(fp, "%d %s", s[j].id, s[j].name);
                if (j < num - 1)
                {
                    fputc('\n', fp);
                }
            }
            printf("修改成功!\n");
            break;
        }
    }
    if (i > num)
    {
        printf("该姓名不存在!\n");
        printf("修改失败!\n");
    }
}

//修改学生信息
void stu_multify(char* file, StuInfo* s, int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d", &num);
    int input = 0;
    do
    {
        menu_multify();
        printf("请选择修改方式:>");
        scanf("%d", &input);
    switch (input)
        {
        case 1:
            multify_id(file, fp,s,num);
            break;
        case 2:
            multify_name(file, fp,s,num);
            break;
        case 0:
            break;
        default:
            printf("输入错误!请重新输入:>\n");
            break;
        }
    } while (input);

}

//展示学生信息
void stu_show(char* file, StuInfo* s, int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d\n", &num);
    int i = 0;
    printf("该班级学生信息为:\n");
    printf("学号    姓名\n");
    for (i = 0; i < num; i++)
    {
        printf("%d    %s\n", s[i].id, s[i].name);
    }
}

//排序菜单
void menu_sort()
{
    printf("***********************************\n");
    printf("********** 1.按学号排序 ***********\n");
    printf("********** 2.按姓名排序 ***********\n");
    printf("**********  0.取消排序  ***********\n");
    printf("***********************************\n");
}

qsort函数
//void qsort
// (
//    void* base,//待排序数组的首地址
//    size_t num,//待排序数组的元素个数
//    size_t width,//待排序数组每个元素的大小(以字节为单位)
//    int (*cmp)(const void* e1,const void* e2)//函数指针,比较两个元素时所用函数的地址(该函数要自己实现),里面
// )                                        //的两个参数为要比较的两个元素的地址

//按学号排序
int cmp_by_id(const void* e1, const void* e2)
{
    //e1、e2为void*类型,先将其强制性类型转换为结构体(StuInfo*)类型,再指向id进行比较
    return (((StuInfo*)e1)->id - ((StuInfo*)e2)->id);
}

//按姓名排序
int cmp_by_name(const void* e1, const void* e2)
{
    return strcmp(((StuInfo*)e1)->name, ((StuInfo*)e2)->name);
}

//排序学生信息
void stu_sort(char* file, StuInfo* s, int num)
{
    FILE* fp = fopen(file, "r+");
    fscanf(fp, "%d\n", &num);
    int i = 0;
    int input = 0;
    menu_sort();
    printf("请选择排序方式:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
        qsort(s, num, sizeof(s[0]), cmp_by_id);
        break;
    case 2:
        qsort(s, num, sizeof(s[0]), cmp_by_name);
        break;
    case 0:
        printf("取消排序!\n");
        break;
    default:
        printf("输入错误!请重新输入:>\n");
        break;
    }

    printf("排序完成!\n");
    rewind(fp);
    fprintf(fp, "%d\n", num);
    for (i = 0; i < num; i++)
    {
        fprintf(fp, "%d %s", s[i].id, s[i].name);
        if (i < num - 1)
        {
            fputc('\n', fp);
        }
    }
}

//关闭文件
void stu_close(char* file, FILE* fp)
{
    fclose(fp);
    fp = NULL;
}

3.test.c
(包含了主函数,以及前两份文件的代码)
#define _CRT_SECURE_NO_WARNINGS 1
#include "byname.h"

void menu()
{
    printf("*****************************************************\n");
    printf("*************    1.开始点名    2.增添   *************\n");
    printf("*************    3.删除        4.查找   *************\n");
    printf("*************    5.修改        6.显示   *************\n");
    printf("*************    7.排序        0.退出   *************\n");
    printf("*****************************************************\n");
}

void test()
{
    StuInfo s[MAX] = { 0 };//学生数组
    int num = 0;//班级人数
    char file[32];
    printf("请输入要打开的班级文件:>");
    scanf("%s", &file);
    FILE* fp;
    fp = fopen(file, "r+");

    //若打开失败,则打印“Open Failed!”,并显示打开失败的原因
    if (fp == NULL)
    {
        printf("Open Failed: % s\n", strerror(errno));
        return;
    }
    //将文件以"r+"的方式打开并将其内容写入结构体中,再关闭该文件,后面再以各功能需要的方式打开文件
    stu_open(file, fp, s, num);
    stu_close(file, fp);

    int input = 0;
    do
    {
        menu();
        printf("请输入您的选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            stu_byname(file,s,num);
            break;
        case 2:
            stu_add(file,s,num);
            break;
        case 3:
            stu_del(file,s,num);
            break;
        case 4:
            stu_located(file,s,num);
            break;
        case 5:
            stu_multify(file,s,num);
            break;
        case 6:
            stu_show(file,s,num);
            break;
        case 7:
            stu_sort(file,s,num);
            break;
        case 0:
            printf("即将退出!欢迎下次使用!\n");
            break;
        default:
            printf("输入错误!请重新输入:>\n");
            break;
        }
        stu_close(file, fp);
    } while (input);
}

int main()
{
    srand((unsigned int)time(NULL));
    test();
    return 0;
}


一是先输入学生信息再存文件吗?
二是怎么体现随机啊,没看出来