C语言不重复随机点名提问且保存之前记录

C语言不重复随机点名提问且保存之前记录

继续之前一篇 C语言读取文件方式实现不重复的随机点名程序,在 方式2 的实现上更新点内容,增加文件中空行处理;基于读写文件方式,保存之前点名记录,下一次点名排除掉之前名单,继续不重复随机点名,使得可以公平公正的点到每一位学生,满足每个学生的课堂参与感。

增加部分代码

    printf("请输入之前记录的已点过txt学生名单文件: "); // 注意:文件名不支持中文,且文件内容一行一名字
    scanf("%s", rfile);                        // usedStudentsNames.txt
    lines = getFileLines(file, arrName);
    printf("名单总人数:%d\n", lines);
    rlines = getFileLines(rfile, usedArrName);
    printf("之前已经点过的名单人数:%d\n", rlines);

    // 更新之前已点的人数以及对应名单里行号
    for(int m=0; m<rlines; m++)
    {
        for(int n=0; n<lines; n++)
        {
            if(strcmp(usedArrName[m],arrName[n])==0)
            {
                // printf("---names[%d]:%s", n,usedArrName[m]);
                index[i] = n;
                i++;
            }
        }
    }

完整代码示例:

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

// 读取文件返回文件行数,即总人数,同时将行号对应名字存放到二维数组中
int getFileLines(char *filePath, char arrName[][20])
{
    FILE *fp = NULL;
    int count = 0;
    char StrLine[20] = {0}; // 每行最大读取的字符数 20,

    if ((fp = fopen(filePath, "r")) == NULL)
    {
        fprintf(stderr, "open file error! %s\n", strerror(errno));
    }

    while (!feof(fp))
    {
        strcpy(StrLine, "");
        fgets(StrLine, 20, fp); // 读取一行,并定位到下一行

        if (strcmp(StrLine, "\n") != 0 && strcmp(StrLine, "") != 0)
        {
            strcpy(arrName[count], StrLine);
            // printf("names[%d]:%s", count,arrName[count]);
            count++;
        }
    }
    // puts("\n");
    fclose(fp);
    return count;
}

// 判断某个数是否在数组中重复
bool isContainsNum(int num, int *nums, int numsSize)
{
    if (numsSize <= 0)
        return false;
    for (int i = 0; i < numsSize; i++)
    {
        if (num == nums[i])
            return true;
    }
    return false;
}

int main(int argc, char *argv[])
{
    FILE *wfp = NULL;
    char file[50] = {0}, rfile[50] = {0};
    int lines = 0, rlines = 0;
    int rand_num, nums = 0;
    char usedArrName[1000][20] = {0}; // 初始化二维数组,记录已经点过的名单
    char arrName[1000][20] = {0};     // 初始化二维数组,存放名字,限制最多点名人数
    int i = 0, index[1000] = {0};     // i:记录已点人数;index:记录不重复行号,限制最多点名人数

    printf("请输入之前记录的已点过txt学生名单文件: "); // 注意:文件名不支持中文,且文件内容一行一名字
    scanf("%s", rfile);                                // usedStudentsNames.txt
    printf("请输入txt学生名单文件: ");                 // 注意:文件名不支持中文,且文件内容一行一名字
    scanf("%s", file);                                 // studentsNames.txt
    printf("请输入要点的人数:");
    scanf("%d", &nums);

    lines = getFileLines(file, arrName);
    printf("名单总人数:%d\n", lines);
    rlines = getFileLines(rfile, usedArrName);
    printf("之前已经点过的名单人数:%d\n", rlines);
    if (nums > lines)
    {
        printf("点名人数大于总人数,请重试!");
        return -1;
    }

    // 更新之前已点的人数以及对应名单里行号
    for (int m = 0; m < rlines; m++)
    {
        for (int n = 0; n < lines; n++)
        {
            if (strcmp(usedArrName[m], arrName[n]) == 0)
            {
                // printf("---names[%d]:%s", n,usedArrName[m]);
                index[i] = n;
                i++;
            }
        }
    }
    srand((unsigned)time(NULL)); // 随机数种子

    while (true)
    {
        rand_num = rand() % lines; //[0,lines) => [0,lines-1]
        // printf("%d ",n);

        if (!isContainsNum(rand_num, index, i))
        { // 没有重复出现则添加到记录中
            index[i] = rand_num;
            i++;
        }

        if (i == lines) // 名单已点完一轮
            break;
        if (i - rlines == nums) // 点的人数够了
            break;
    }

    if ((wfp = fopen(rfile, "a+")) == NULL)
    {
        fprintf(stderr, "open file error! %s\n", strerror(errno));
    }
    // for (int l = 0; l < i; l++)
    // {
    //     printf("%d,", index[l]);
    // }
    puts("\n随机点中的名单:");
    for (int l = rlines; l < i; l++)
    {
        // printf("arrName[%d]=%s",index[i],arrName[index[i]]);
        printf("%s", arrName[index[l]]);
        fputs(arrName[index[l]], wfp); // 按行追加写入记录文件中
    }
    if (i == lines)
    {
        printf("\n学生名单已点完一轮,这次还要重新点%d人,请清空文件继续点", nums - (i - rlines));
    }
    fclose(wfp);
    return 0;
}

执行示例:

在这里插入图片描述

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的随机点名程序示例,包含超过300行代码。请注意,这只是示例代码,您可以根据自己的需求进行修改和扩展。 ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAX_NAME_LEN 20 // 最大姓名长度 #define MAX_STUDENTS 100 // 最大学生数 typedef struct { char name[MAX_NAME_LEN]; // 姓名 int id; // 学号 } Student; // 初始化学生信息 void init_students(Student students[], int num_students) { char names[MAX_STUDENTS][MAX_NAME_LEN] = { "张三", "李四", "王五", "赵六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十", "刘一", "陈二", "杨三", "黄四", "吕五", "张六", "孙七", "周八", "吴九", "郑十" }; for (int i = 0; i < num_students; i++) { // 随机生成学号 int id = rand() % 100000; // 随机选取一个姓名 int name_index = rand() % MAX_STUDENTS; // 将姓名和学号赋值给学生信息 sprintf(students[i].name, "%s", names[name_index]); students[i].id = id; } } // 打印学生信息 void print_students(Student students[], int num_students) { for (int i = 0; i < num_students; i++) { printf("%s\t%d\n", students[i].name, students[i].id); } } // 随机选择一个学生 void random_pick(Student students[], int num_students) { // 生成随机数 int index = rand() % num_students; // 打印被选中的学生信息 printf("本次被点名的学生是:%s,学号:%d\n", students[index].name, students[index].id); } int main() { srand((unsigned)time(NULL)); // 初始化随机数生成器 Student students[MAX_STUDENTS]; // 学生信息数组 int num_students = 50; // 学生数目 init_students(students, num_students); // 初始化学生信息 printf("初始化后的学生信息:\n"); print_students(students, num_students); // 打印学生信息 printf("\n"); for (int i = 0; i < 10; i++) { printf("第%d次随机点名:\n", i + 1); random_pick(students, num_students); // 随机选择一个学生 printf("\n"); } return 0; } ``` 这个程序随机生成一些学生信息,然后进行随机点名。您可以根据需要进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值