实验14
完善课堂随机点名实验,要求:1.用文件存放学生名单;2.输出学号+姓名;3.用函数实现这一功能。
c语言
私我发你文件,一步步教你
代码如下,可一直循环点名,直到全部学生点名完毕,可重置。
如有帮助,望采纳!
#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;
}
一是先输入学生信息再存文件吗?
二是怎么体现随机啊,没看出来
来