系统软件程序设计报告linux下C语言程序课程设计报告.docx
《系统软件程序设计报告linux下C语言程序课程设计报告.docx》由会员分享,可在线阅读,更多相关《系统软件程序设计报告linux下C语言程序课程设计报告.docx(21页珍藏版)》请在冰点文库上搜索。
系统软件程序设计报告linux下C语言程序课程设计报告
一、引言(简要说明设计题目的目的、意义、内容、主要任务等)
1.1设计目的
本次系统软件课程设计的主要目的有两个:
一方面是分析设计linux源代码,另一方面是进行系统级的程序设计。
1.2题目与要求
我计划编写的题目是:
⑴小学算术运算测试程序。
制作一个可供小学数学运算的程序:
10以内加减法,能根据输入题数出题,判断题是否正确,最后计算分数。
并用make工程管理器编译,编写makefile文件。
⑵简单聊天程序。
在linux下用C语言编写一个简单的网络聊天程序。
实现网络传输功能。
1.3内容及主要任务
⑴小学算术运算测试程序:
要求完成10以内的加减运算。
能根据用户输入的想要练习的题目数自行出题。
用户输入答案后可以判断正误,并能给出算对及算错的题目数,最后计算出分数。
同时,对于用户算错的题目会发出报警声,提示用户注意,同时给出正确结果。
做完一次测试后用户可决定是否继续进行下一次测试。
⑵简单聊天程序:
本课题是建立聊天通信模型,设计一个聊天室软件,包括服务器端和客户端,主要功能为:
Ⅰ、服务器端功能:
①初始化socket创建服务器端。
②维护一个链表,保存所有用户的IP地址、端口信息。
③接受用户传送来的聊天信息,然后向链表中的所用用户转发。
④接受用户传送来的连接判断命令,并向用户发出响应命令。
Ⅱ、客户端功能:
客户端界面上的两个文本框,一个用于显示接受的聊天信息,一个用来接受用户输入的聊天信息。
当按下“发送”按钮时将信息发送给服务器。
1.4题目设计意义
⑴通过本课题的毕业设计,熟悉了关于linux下C语言的系统软件程序设计,可以比较深入的了解和掌握WINSOCK控件基本属性、方法和事件,理解网络聊天通信的概念,输控制协议(TCP)进行数据交流,初步掌握网络聊天通信程序的设计方法。
并能巩固和扩展大学期间的学习内容,进行项目的设计开发训练,更好的适应社会的需求。
⑵随着计算机网络技术的快速发展,人们的交流方式越来越多,传统的通信方式在速度和可靠性方面已经很难满足人们的需要,即时通信系统已成为人们的新宠。
同时,即时通信系统对现代企业也有着重大意义,它为诸企业开拓了网络应用的新领域。
自从它诞生以来,以实时交互、资费低廉等优点,受到广大个人用户的喜爱,已经成为网络生活中不可或缺的一部分。
本着学以致用的原则,本人开发了这套多点聊天系统,以满足网络用户的通讯需求。
该系统具有操作简单、界面友好、功能专一等特点。
⑶本报告就系统的开发过程做了详细的介绍,并对系统的原理、总体设计等方面做了深入细致的讨论。
二、正文(课程设计的主要内容,包括实验与观测方法和结果、仪器设备、计算方法、编程原理、数据处理、设计说明与依据、加工整理和图表、形成的论点和导出的结论等。
正文内容必须实事求是、客观真切、准确完备、合乎逻辑、层次分明、语言流畅、结构严谨,符合各学科、专业的有关要求。
)
任务一:
小学数学运算程序
2.1.1主要内容
本程序共分为五个模块:
出题模块、答题模块、检查计分模块、评分模块和评价模块;下面分别对这五个模块的算法做一下介绍。
⑴出题模块:
一个答题系统自然而然首先就是要有题目且能够根据条件出题;在本模块中,首先设了一个含有15个指针的指针数组,指针数组里的每个指针都指向了相应题号的选择题,这样就实现了对题目的储存;然后用scanf函数来实现从键盘上输入题号,用if语句控制输题的范围;题号不在1--15的范围内就提示选题出错;在输入题号的过程中输入相同题号是在所难免的;但是在答题系统中输入相同题号显然没有意义,所以另外设了一个静态一维数组来储存已输过的题号;且数组的第一个元素初始化为0,然后每输入一个题号就赋给这个数组,同时用for语句来使当前的题号一一与储存在一维数组中已输过的题号进行比较,如题号有相同,就提示重答,重答的功能是通过对出题模块函数的递归调用来实现的,如题号没有相同,就通过输入的题号借助指针数组里的指针找到与题号对应的选择题,用puts函数来实现对选择题的输出;最后用return语句将其他模块返回来每道题的小分数返回到主函数中(在主函数中调用出题模块函数)。
⑵答题模块:
出完题后自然是从键盘上输入答案了,在本模块中,提示输入答案后,用scanf函数来实现使从键盘上输入的一个答案选项(A、B、C、D)赋给一个用来记录答案的字符变量;用return语句将这个变量返回到出题模块中。
⑶检查计分模块:
输入答案选项后,就要判断答案的正确性和计分了,在本模块中,要设一个字符数组来储存每道题的正确答案;用if语句来控制在答题模块中输入的答案是否为A、B、C、D中的某一个;若不是,就提示选的答案不在答案范围内,若是,根据在出题模块中输的题号使在答题模块中输入的答案选项与储存正确答案数组中的相应答案选项相比较,若相同,就提示答案正确,与此同时用变量记录下这道题所得的小分,否则,就提示答案错误并给出当前题目的正确答案,不计分;用return语句将得分返回到出题系统中(在出题模块函数中调用检查计分模块函数)。
⑷评分模块:
做完题后,就要根据做题的对错个数来评分;在本模块中,首先就要提示题目全做完,用switch语句根据总小分来选择性地选出11个不同的分数中的一个分数,并且打印出该分数(在主函数中调用评分模块函数)。
⑸评价模块:
最后一步就是要根据不同的总得分段来给出不同的评语,在本模块中用if语句根据不同的总分数段来打印出不同的评语(在主函数中调用评价模块函数)。
主函数将这五个模块直接地或间接地联系在一起,使它们构成本程序,现在就来介绍主函数的算法。
主函数对出题模块函数、评价模块函数进行了调用;首先提示开始答题,为了要答10次题,就要设一个for语句来控制对出题模块函数调用的次数,即需要答一定次数的题,与此同时用一个变量来累加由出题模块函数返回来每道题的小分数;接下来分别对评分模块函数和评价模块函数进行调用。
以上就是对本程序算法的介绍。
2.1.2程序结构及主要过程
⑴本程序共包含了顺序结构、选择结构、循环结构三种在C程序中的主要结构,其中穿插了数组(一维数组、字符数组)、指针(指针数组)、函数调用(递归调用)等知识,该程序覆盖了本学期所学的除结构体外的大部分知识。
⑵本程序结构和过程思路如下:
为了要答题,首先要有题目,设一个指针数组来实现;把相应的题目调出,应用指针的功能实现;调出题目后,就要给用户答题了,用一个输入函数实现;再经过系统的判断,用一个字符数组储存正确答案结合判断语句实现;最后累加计分,用循环结构实现。
⑶总之,该程序的总体结构和过程很好的体现了现在所提倡的对一个程序结构模块化的思想。
2.1.3程序模块功能说明
本程序一共有五个模块,它们分别是:
出题模块(question_out()),答题模块(answer()),检查计分模块(check()),评分模块(count()),评价模块(assessment()),现在就来分别介绍这五个模块的功能。
⑴出题模块(question_out()):
这一模块主要负责对题目的储存和调出这两个功能。
⑵答题模块(answer()):
这一模块主要负责将用户端的答案通过键盘输入到系统。
⑶检查计分模块(check()):
这一模块主要负责检查判断用户所提供的答案是否正确并根据它来记录每题所的总分。
⑷评分模块(count()):
这一模块主要负责统计总得分并打印。
⑸评价模块(assessment()):
这一模块主要负责根据给出的总得分打印相应的评语。
总之这五个模块都有着各自的功能且互相联系,五者在程序中缺一不可。
2.1.4makefile介绍
⑴Makefile文件介绍
Makefile一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
⑵makefile主要功能
Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。
而makefile文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。
makefile文件是许多编译器--包括WindowsNT下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改makefile文件而已。
⑶自动化编译
Makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:
Delphi的make,VisualC++的nmake,Linux下GNU的make。
可见,makefile都成为了一种在工程方面的编译方法。
2.1.5makefile规则
makefile中的规则是这样的:
TARGET…:
DEPENDENCIES…
COMMAND
…
目标(TARGET)程序产生的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。
依赖(DEPENDENCIES)是用来产生目标的输入文件,一个目标通常依赖于多个文件。
命令(COMMAND)是make执行的动作,一个可以有多个命令,每个占一行。
注意:
每个命令行的起始字符必须为TAB字符!
有依赖关系规则中的命令通常在依赖文件变化时负责产生target文件,make执行这些命令更新或产生target。
规则可以没有依赖关系,如包含target“clean”的规则。
规则解释如何和何时重做该规则中的文件,make根据依赖关系执行产生或更新目标;规则也说明如何和何时执行动作。
有的规则看起来很复杂,但都符合上述模式。
makefile中的规则描述如何生成特定的文件,即规则的目标。
规则列出了目标的依赖文件,指定生成或更新目标的命令。
规则的次序是不重要的,除非是确定缺省目标:
缺省目标是第一个makefile中的第一个规则;如果第一个规则有多个目标,第一个目标是缺省的。
有两个例外:
以’.’开头的目标不是缺省目标;模式规则对缺省目标没有影响。
通常我们所写的地一个规则是编译整个或makefile中指定的所有程序。
2.1.6Makefile文件
main:
main.oinput.ochuti.o
gccmain.oinput.ochuti.o-omain
main.o:
main.cmyhead.h
gcc-cmain.c
input.o:
main.c
gcc-cinput.c
chuti.o:
main.c
gcc-cchuti.c
2.1.7源程序
#include
#include
voidfunction(){
intindex,itest_total,N=200;
intiflag,num1,num2,itotal,iarrsum[200],iarranswer[200],iarrop[4];
itotal=0;
printf("请输入题数:
\n");
scanf("%d",&itest_total);
for(index=0;index{
iflag=rand()%4+1;
switch(iflag)
{
case1:
num1=rand()%10;
num2=rand()%10;
iarrsum[index]=num1+num2;
printf("%d+%d=\n",num1,num2);
break;
case2:
num1=rand()%10;
num2=rand()%10;
iarrsum[index]=num1-num2;
printf("%d-%d=\n",num1,num2);
break;
case3:
num1=rand()%10;
num2=rand()%10;
iarrsum[index]=num1*num2;
printf("%d*%d=\n",num1,num2);
break;
case4:
num1=rand()%10;
num2=rand()%10;
iarrsum[index]=num1/num2;
printf("%d/%d=\n",num1,num2);
break;
default:
break;
}
}
printf("依次输入每题的答案:
\n");
for(index=0;index{
scanf("%d",&iarranswer[index]);
getchar();
if(iarranswer[index]==iarrsum[index])
itotal++;
}
}
printf("正确率:
%f%%\n",100.0*((itotal*1.0)/itest_total));
}
intmain()
{
charflag;//开始有一轮测试,以后根据用户的输入开始新一轮测试或结束测试;
do{
function();
printf("请输入'Y'表示开始新一轮测试,其他字母表示结束测试:
\n");
scanf("%c",&flag);
}while(flag!
='Y');
return0;}
2.1.8试验过程及结果
⑴输入题数5
⑵得到计算式
⑶输入每题答案
⑷运行结果
输入y重新开始,输入其他字母结束。
2.1.6结果分析
这是一个小学数学运算测试程序,要求完成10以内的加减运算。
能根据用户输入的想要练习的题目数自行出题。
用户输入答案后可以判断正误,并能给出算对及算错的题目数,最后计算出分数。
同时,对于用户算错的题目会发出报警声,提示用户注意,同时给出正确结果。
做完一次测试后用户可决定是否继续进行下一次测试。
该程序基本实现了以上功能,且计算结果合理正确,满足实验要求。
任务二:
linux下C语言设计简单聊天程序
2.2.1实验题目
熟悉linux操作系统下最简单实用的通信程序socket.最好能全部完成,否则按照完成情况打分。
2.2.2实验目的
通过对socket的编写,可以了解linux下最简单实用的进程通信方法,为后续信号灯、消息队列等学习奠定基础。
2.2.3实验设备及环境
⑴硬件设备:
PC机一台
⑵软件环境:
安装Linux操作系统,并安装相关的程序开发环境,如C\C++\tsh\bsh等编程语言环境。
2.2.4实验内容及要求
⑴内容:
本课题是建立聊天通信模型:
设计一个聊天室软件。
包括服务器端和客户端。
主要功能为:
Ⅰ、服务器端功能:
①初始化socket,创建服务器端。
②维护一个链表,保存所有用户的IP地址、端口信息。
③接受用户传送来的聊天信息,然后向链表中的所用用户转发。
④接受用户传送来的连接判断命令,并向用户发出响应命令。
Ⅱ、客户端功能:
客户端界面上的两个文本框,一个用于显示接受的聊天信息,一个用来接受用户输入的聊天信息。
当按下“发送”按钮时将信息发送给服务器。
⑵要求:
①用C语言编程实现linux简单的聊天室功能。
②用户程序命名为client.c;服务器程序命名为server.c。
③绑定端口等信息见实验方法内容,要求client可以通过socket连接server。
④在client,提示输入服务器ip。
⑤若连接server的socket建立成功,返回提示信息。
⑥Client输入的聊天内容在client端(多个client端)和server端同时显示。
⑦多个client可同时接入server,进入聊天室,最多支持20个client。
⑧Client端输入quit退出连接,server端提示client退出。
⑨可选择使用多线程实现多客户端。
2.2.5实验方法内容
⑴主要的常量变量
①客户端:
#defineTRUE1
#definePORT5000
intquit=0;//quit表示是否用户确定退出
②服务器端:
#defineMAXLINE1000//在一条消息中最大的输出字符数
#defineLISTENQ20//最大监听队列
#definePORT5000//监听端口
#defineMAXFD20//最大的在线用户数量
void*get_client(void*);
inti,maxi=-1;//maxi表示当前client数组中最大的用户的i值
intclient[MAXFD];
⑵主要模块
①客户端:
intmain(void)
void*get_server(void*sockfd)
//get_server函数,用于接受服务器转发的消息
②服务器端:
intmain()
void*get_client(void*sockfd)//运行get_client函数,处理用户请求
2.2.6代码
⑴客户端代码
#ifdefHAVE_CONFIG_H
#include
#endif
#include"client.h"
intmain(intargc,char*argv[])
{
intcstcp,csudp,ccudp;
intserver_port=8000;//c-stcpport
intCC_port=5000;//c-cudpport
structhostent*hostPtr=NULL;
structsockaddr_inCS_link={0};
structsockaddr_inCC_link={0};
charhostname[80]="";
charbuf[bufsize+1]="";
char*msg;
char*S_addr=NULL;
intrecvn;
intchildPid;
if(2!
=argc)
{
fprintf(stderr,"Usage:
%s\n",argv[0]);
exit
(1);
}
S_addr=argv[1];
cstcp=tcpSocket();
GetHostName(hostname,sizeof(hostname));//getlocalhost
CreateSockAddr(S_addr,&CS_link,server_port);//C-S
Connect(cstcp,(structsockaddr*)&CS_link);
msg="ClientOPC0.0.1\n";
Send(cstcp,msg);
Recv(cstcp,buf);
printf("%s",buf);
printf("Connecttoserversuccessfully,pleaseinputyournickname\n");
Fgets(buf);
Send(cstcp,buf);//sendusername
bzero(buf,bufsize);
Recv(cstcp,buf);
while(strncmp(buf,":
x",2)==0)
{
printf("%s","Thenamehasbeenused,pleasechangeyourname:
\n");
Fgets(buf);
Send(cstcp,buf);//sendusername
bzero(buf,bufsize);
Recv(cstcp,buf);
}
printf("%s",buf);
Send(cstcp,":
l");//sendcomtogetuserlistformserver
printf("OnLineUsers:
\n");
bzero(buf,bufsize);
Recv(cstcp,buf);//getuserlistfromserver
printf("%s",buf);
childPid=fork();
switch(childPid)
{
case-1:
//ERROR
perror("fork()");
exit
(1);
case0:
//childprocess
while
(1)
{
bzero(buf,bufsize);
if(Recv(cstcp,buf)>0)
if(strncmp(buf,":
q",2)==0)
exit(0);//getuserlistfromserver
printf("%s",buf);
}
⑵服务器端代码
#include
inttcpSocket()
{intn;
if((n=socket(PF_INET,SOCK_STREAM,0))==-1)
{
perror("TCPSocketerror");
exit
(1);
}
return(n);
}
voidSetsockopt(ints)
{inton=1;
structlingerlinger={0};
linger.l_onoff=1;
linger.l_linger=30;
if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(constchar*)&on,sizeof(on))==-1)
{perror("Setsockopt(...,SO_REUSEADDR,...)");
exit
(1);}
if(setsockopt(s,SOL_SOCKET,SO_LINGER,(constchar*)&linger,sizeof(linger))==-1)
{
perror("Setsockopt(...,SO_LINGER,...)");
exit
(1);
}
}
intBind(intsockfd,conststructsockaddr*my_addr,socklen_taddrlen)
{
returnbind(sockfd,my_addr,addrlen);
}
voidListen(ints)
{
voidGetHostName(char*buffer,intlength)
{
structutsnamesysname={0};
intstatus=0;
status=uname(&sysname);
if(-1!
=status)
{
strncpy(buffer,sysname.nodename,length);
}
else
{
perror("GetHostName()");
exi