“主C显”小组作品

该博客介绍了怀化学院计算机科学与工程学院1901班第十一小组“主C显”团队的课程设计项目——《学生限时答题评测系统》。团队完成了登录、预备工作、测试工作等功能,核心功能包括便捷输入题库、排除回车空格影响等。项目仍有从文件中读入题库、连接互联网等功能未完成。博客还记录了版本更新日志及每位成员的心得体会。
摘要由CSDN通过智能技术生成

团队介绍

在这里插入图片描述
单位名:怀化学院计算机科学与工程学院。
课程名称:高级程序语言设计。
班级 小组序号:1901班 第十一小组。
团队名称:“主C显”小组。
课程设计题目:《学生限时答题评测系统》

课程设计题目基本要求介绍

功能模块一:登录

		1,限制账号要以10位学号+姓名的方式登录,否则重新登录
		2,登录成功后将基本信息(如账户,IP地址等)发送给服务器
		3,登录成功后窗口标题应修改为该账户名

功能模块二:预备工作

		1,对答题者输入的用户名进行整理,可以允许答题者在输入学号前输入空格和回车,开始输入学号后可以允许输入空格。(程序不会被开始输入的回车及空格影响,并且会自动消除开始输入后的空格)
		
		2,进行答题时间的限制,练习版可以进行答题者自我规定。
		      
		3, 告知答题者答题时间限制和总题数限制,
		
		在答题者按任意键确认并开始答题。
		(进行一次暂停)
		       
		4, 进行倒计时,规定倒计时以秒为单位没过1秒提示一次。(进行一个延时输出的设置)

功能模块三:测试工作

		1,题库的输入和题目的输出
		        
		题库由出题者输入,按"...题目...","...答案...","...题目..."......;组成(注意" "     ,要用英文的);
		      
		 从题库中随机抽出一道题,抽题随机不重复。
		
		
		2,答案的处理
		      
		排除大小写的干扰。(将输入的答案中的英文字母全部小写化)
		      
		允许答题者在开始输入答案前可以输入回车和空格,并且在输入答案后可以允许在途中输入空格。(答案中的空格可以被消除,答案前的回车和空格不会影响答案)
		
		3,答案的判断
		      
		将答题者的答案与正确答案做对比。
		
		4,答题后的反馈
		        
		如果答题者回答正确,提示答案正确。(将答题者的正确答题数+1)
		         
		如果回答错误,提示答案错误,并告知正确答案。
		       
		 答题者总答题数+1
		        
		告知答题者本题用时和总用时,并提示至本题为止共回答多少题,回答正确多少题。
		
		5,进行模块三1-4的循环(在时间达到限定时间或总答题数达到总题数时进行循环停止)
		     
		  结束后会提示答题者总答题数,总正确题数,正确率,分数,所总时间。(定义评分标准)

模块四:进行成绩分类

		  根据答题者的得分显示一个对应的表格,进行等级划定,及语言提示。(设置等级划定的规划,并设置对应的语言提示,不同等级表格颜色要不同)
		 程序不会因为答题结束而关闭。(进行一个暂停设置)

模块五:客户端

		 可以自动建立一个文档将屏幕上的所以内容保存在文档中。(文档要txt文档)
		 将关键信息传输给服务端。(关键信息指答题者信息,总答题数,正确题数,答题正确率,总用时,总分数)

模块六:服务器

			可以接受客户端传输的内容,并进行保存,且可以不断接收客户端的连接,并且每个客户端发送的信息都可以保存在一起。

流程图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

核心功能讲解

1,便捷输入题库的功能

void comprehensive(char subject[TM][100],char answer[TM][100])//便捷输入题库(可按一题,一答案,的方式输入)
{
	int i , j ; 
	
	j = 0 ;
	for(i = 0 ; i < TM * 2 ;i += 2 )
	{
		strcpy ( subject[j] , subjct_and_answer[i]);
		strcpy ( answer[j] , subjct_and_answer[i + 1]);
		j += 1;
	}
}

便捷输入题库的功能如果加入文件导入二维数组可以进一步优化,此功能只需要时间便可以完成

2,排除回车空格对答案输入的影响

void eliminate(char * l)
{
	int j ;
	char g[100] , h[100];
	for( j = 0 ; j < 100 ; j++ )
	{
		scanf( "%c" ,&g[j]);
		if( g[j] != ' ' && g[j] > 13)
		{	
			g[0] = g [j];
			g[1] = '\0';
			break ;
		}
	}
	gets(h);
	fun (h);
	strcpy( l ,  strcat ( g , h )  );
}

**3,排除空格**
void fun(char *a)
{
	
	int i=0, j=0;
	for (i = 0; i < strlen(a); i++) 
	{
		if (a[i] != ' ') 
		{
			a[j++] = a[i];               
		}
		else if(a[i]==' ')
		{
			continue;
		}
	}
	a[j] = '\0';                          
}

在数组最后面加上字符串结束符’\0’
**3,**从文件中读入题目与答案,并且设置难易题目的比例
void ltemBankReading(int sumY ,int sumN )

struct tiku
{
	char timu[50] ;
	char daan[20] ;
};
	int i ,j ;
	FILE * fp ;
	struct tiku arrayY[sumY] ,arrayN[sumN];
	if( ( fp = fopen( "tikuY.txt","r" ) ) == NULL  )//在stdio.h中已经定义NULL为0;
	{
		printf("cannot open this file\n");
		exit(0);//终止程序
	}
	for( i = 0 ; i < sumY ; i++ )
	{
		fscanf(fp,"%s",arraY[i].timu);
		fscanf(fp,"%s",arraY[i].daan);
	}
	fclose(fp);//关闭成功返回0,否则返回EOF(-1)

	if( ( fp = fopen( "tikuN.txt","r" ) ) == NULL  )//在stdio.h中已经定义NULL为0;
	{
		printf("cannot open this file\n");
		exit(0);//终止程序
	}

	for( i = 0 ; i < sumN ; i++ )
	{
		fscanf(fp,"%s",arraN[i].timu);
		fscanf(fp,"%s",arraN[i].daan);
	}
	fclose(fp);//关闭成功返回0,否则返回EOF(-1)
}

(2020.02.02对此进行补充)
4,将所要输出的文字输出并保存在文档

void showfile_and_savefile(FILE *fp,int c,const char *format,...)

{

    va_list args;
	switch(c)
	{
		case 1:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);
			break;
		case 2:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);
			break;
		case 3:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED);
			break;
		case 4:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_GREEN|FOREGROUND_RED);
			break;
	}	
 

    va_start(args,format);

	printf(format,args);
    vfprintf(fp,format,args);

    va_end(args);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);

}

知识引用于 https://blog.csdn.net/bribo/article/details/12973519
https://blog.csdn.net/u012349696/article/details/42398107

5,规定要10位学号加名字

int islogin(char*a)
{
	int i,count=0;
	for( i = 0 ; i <= 9 ; i++)
	{
		if( a[i] <= '9' && a[i] >= '0')
		{
			count++;
		}
	}
	if(count == 10)
	{
		if( a[0]=='1' && a[1] >= '6' 
			&& a[1] <= '9' && a[2] == '0' 
			&& a[3] == '0' && a[4] == '1' 
			&& a[5] == '3' && a[6] == '0'
			&& a[10] != '\0')
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
	else
	{
		return 1;
	}
}

6,服务器

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

#pragma comment(lib , "ws2_32.lib")


#define DEFAULT_BUFFER 4096 /*缓冲区大小*/
#define PORT 0
#define IP 1
char getparameter[2][64];
//FILE * fpRead;
FILE * fp;
//FILE * fp = fopen( "答题信息汇总.txt" , "w" );
/*与客户机通信的线程函数*/
DWORD WINAPI ClientThread(LPVOID lpParam)
{
	 
	FILE * fp = fopen( "答题信息汇总.txt" , "a" );
    SOCKET sock = (SOCKET)lpParam;
    char Buffer[DEFAULT_BUFFER];
    int ret , nLeft , idx;
    while (1) {
        /*接收来自客户机的消息*/
        ret = recv(sock , Buffer , DEFAULT_BUFFER , 0);
        if (ret == 0)
            break;
        else if (ret == SOCKET_ERROR) {
            printf("recv() 失败: %d\n" , WSAGetLastError());
            break;
        }
        Buffer[ret] = '\0';
        printf("已接收来自%s字符: %s\n" , getparameter[IP] ,Buffer);    //打印接收到的消息
		fprintf( fp , "已接收来自%s字符: %s\n" , getparameter[IP] ,Buffer);
			fclose(fp);
        nLeft = ret;
        idx = 0;
        while (nLeft > 0) {
            /*向客户机发送回应消息*/
            ret = send(sock , &Buffer[idx] , nLeft , 0);
            if (ret == 0)
                break;
            else if (ret == SOCKET_ERROR) {
                printf("send() 失败: %d\n" , WSAGetLastError());
                break;
            }
            nLeft -= ret;
            idx += ret;
        }
    }
    return 0;
}
int main( )
{
	FILE * fp = fopen( "答题信息汇总.txt" , "w" );
    WSADATA        wsd;
    HANDLE        hThread;
    DWORD        dwThread;
    SOCKET        sListen , sClient;
    int            AddrSize;
    unsigned short port;
    struct sockaddr_in local , client;

	printf("请输入服务器端口号:");
	gets(getparameter[PORT]);
    /*加载Winsock DLL*/
    if (WSAStartup(MAKEWORD(2 , 2) , &wsd) != 0) {
        printf("WinSock 初始化失败!\n");
        return 1;
    }
    /*创建Socket*/
    sListen = socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
    if (sListen == SOCKET_ERROR) {
        printf("socket() 失败: %d\n" , WSAGetLastError());
        return 1;
    }
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = htonl(INADDR_ANY);
    port = atoi(getparameter[PORT]);    //获取端口值
    local.sin_port = htons(port);
    /*绑定Socket*/
    if (bind(sListen ,
        (struct sockaddr*)&local ,
        sizeof(local)) == SOCKET_ERROR) {
        printf("bind() 失败: %d\n" , WSAGetLastError());
        return 1;
    }
    /*打开监听*/
    listen(sListen , 8);
    /*在端口进行监听,一旦有客户机发起连接请示
    就建立与客户机进行通信的线程*/
    while (1) {
        AddrSize = sizeof(client);
        /*监听是否有连接请求*/
        sClient = accept(sListen ,
                         (struct sockaddr*)&client ,
                         &AddrSize);
        if (sClient == INVALID_SOCKET) {
            printf("accept() 失败: %d\n" , WSAGetLastError());
            break;
        }
		strcpy(getparameter[IP],inet_ntoa(client.sin_addr));
        printf("接受客户端连接: %s:%d\n" ,
               inet_ntoa(client.sin_addr) ,
               ntohs(client.sin_port));

        //创建一个线程去处理
        hThread = CreateThread(NULL , 0 , ClientThread ,
                               (LPVOID)sClient , 0 , &dwThread);
        if (hThread == NULL) {
            printf("CreateThread() 失败: %d\n" , GetLastError());
            break;
        }
        //处理完后关闭
        CloseHandle(hThread);
    }
    closesocket(sListen);
    WSACleanup();    //用完了要清理
    return 0;
}

7,倒计时程序

void timeback(int r)
{
	
	while(r>0)
	{
		printf( "************************倒计时%d*****************************\n" , r );
		Sleep(1000);
		r--;
	}
	
}

本设置适应本次项目需要

项目未完成的功能

1,未完成从文件中读入题库(只是时间问题)
2,未完成连接互网络的内容(暂时尚未掌握足够能力)

版本更新日志

测验小程序PATCH修正说明:
V服务器完美版(2019-11-24)
1,可以接受客户端传送来的信息并保存。

V2.0.0(2019-11-23)
客户端版成功,可以自动将答题信息存档保存。

V1.2.0(2019-11-21):
1,进行函数的优化,将部分功能函数化。
2,解决输入学号时在输入前输入回车和输入过程中有空格的问题。

V1.1.0(2019-11-19):
1,程序自动生成一个txt文档,并实现将所有屏幕上的内容保存在txt文档中。
2,当答题者输入完成学号和姓名后,窗口自动改为学号加姓名。

V1.0.1(2019-11-19) :
1, 修改和完善排除空格回车干扰的功能。(欧阳有澳)
2,实现最终的绘制表格有颜色区分。(欧阳有澳)

V1.0.0(2019-11-17):
1,提示答题者输入学号和姓名。在这里插入代码片
2,如果输入学号错误或者有空格,提示输入错误,重新输入。(唐新坤)
3,支持答题时大小写字母均可正确。
4,答案不受空格和回车影响。(段文杰)!(经测试有错误)
5,回答错误和回答正确会有不同样色的字符提示。(欧阳有澳)
6,回答完一题会告知本题用时,和总用时,及答题个数和正确题数。
7,可以进行5秒倒计时提示。(欧阳有澳)
8,可以进行答题时间的限制。(段文杰)
9,可以打出表格对成绩进行分类和评价,并且字体颜色不同。(欧阳有澳)(1.0.0是未实现)
10,可以告知答题者正确率。
在这里插入图片描述

相关文档地址

  • https://pan.baidu.com/s/1HySs1Kv5TTzTgCOV4dfORg

每位成员的过程心得

组长 欧阳有澳 个人心得:
这是本人第一次进行项目领导,本人感受到领导的重要性,团队的带领需要领导者考虑到每个人的性格和能力来分配任务,
还得根据工作量和限定的项目时间时间来合理分任务,(此次本人因个人原因导致程序最后的进程拖延了),本人还意识到了团
队管理对于一个团队的重要性;
编程收获:
本次项目编程让我之前学的许多知识得到巩固和加深,还然我学到了怎样面向百度编程,还培养了自己的学习能力;并且学到了
于他人讨论遇到的各种问题;本人还认识到程序优化的重要性,尽量封装自定义函数是主函数简化。

组员 段文杰 个人心得:
我在这一次的课程设计,也是第一次课程设计中发现了许多问题,也收获了许多。
首先,一个大的课程设计在规定时间内,并不是一个人可以完成的,而是由多个人一同努力才
可以做到,这就要求,小组内每个组员有良好的沟通和配合以及分工,这是对组员的要求,更是对组长的要求。
然后在一个小组内,有时组员之间可能在不同方面有着不同的方法,可以有效的取长补短。
然后说一下,我所遇到的问题
第一,对于一些任务的时间安排有些冲突,导致自己的时间过于紧凑。
第二,在函数的难易程度上的判断不精确,没能很好的完成所有代码。
对于这一次的编程,整体来说,我还是对我,以及我们小组的表现很满意,如果可能,
希望在下一次的课程设计中在一起努力

组员 唐新坤 个人心得:
通过这次团队合作,我深刻的意识到了团队的重要性,当我遇到难题时,组长和另一个组员都给我提供了很多支持,这才使我顺利的完成了任务,当组长或其他组员遇到困难时我也会从旁协助,尽力完成我们共同的任务,能完成这个任务是大家一起努力的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值