实验一、命令解释程序的编写实验
一、 实验目的
(1)掌握命令解释程序的原理;
(2)*掌握简单的DOS调用方法;
(3)掌握C语言编程初步。
二、 实验内容和要求
根据教师指定的实验课题,完成设计、编码、测试工作。
三、 实验方法、步骤及结果测试
- 1. 源程序名:MiniOS1.0.cpp
可执行程序名:MiniOS1.0..exe
- 2. 原理分析及流程图
存储结构:结构体数组
原理分析:根据实验要求,该程序需要显示一个类似window系统dos窗口的界面,用户输入命令后在存储的命令信息中寻找是否存在相应的命令,并进行相关的处理或提示相应的信息。
实验流程:阅读实验要求à规划程序结构à把程序分为多个部分à完善各个部分à把各个程序段结合起来à调试
程序运行流程:显示版本信息à读取命令信息的文件cmd.txt到结构体数组中à等待用户输入命令à在结构体数组中寻找是否存在该命令à(存在,则进行相应的处理货提示该命令的作用/不存在,则提示该命令不存在)à回到等待用户输入命令的操作。
- 3. 主要程序段及其解释:
结构体:
struct Ordersave
{
char order[10];//储存命令
char type[3];//命令类型
char mean[50];//命令作用
};
主函数:
int n;//记录读入命令信息的条
Ordersave dos[MAX];
char msg[50];
//从本地文件读取全部命令信息
printf("Microsoft Window [版本 6.1.7016] 版权所有 <c> 2009 Microsoft Corporation。保留所有权利。 ");
n=readMsg(dos);
while(1)
{
//读取用户输入的命令
inputMsg(msg);
//写日志,记录输入的命令和输入的时间
writeLog(msg);
//处理用户输入的命令
dealMsg(dos,msg,n);
}
readMsg函数:
功能:从文件cmd.txt中读取命令信息
while(!feof(fp))
{
j=0;
k=0;
//按行读取
fgets(s,800,fp);
s[strlen(s)]=' ';
if(s[strlen(s)-1]==10) //去掉回车键
s[strlen(s)-1]=' ';
if(s[k]!=' ')
{
while(s[k]!=' ')
{
dos[i].order[j]=s[k];
j++;
k++;
}
dos[i].order[j]=' ';
k++;
while(s[k]!=' ')
{
if(s[k]=='0')
strcpy(dos[i].type,"外");
else
strcpy(dos[i].type,"内");
k++;
}
k++;
j=0;
while(s[k]!=' ')
{
dos[i].mean[j]=s[k];
k++;
j++;
}
dos[i].mean[j]=' ';
}
i++;
}
inputMsg函数:
功能:显示输入的提示
printf(" C:\User\Administrator>");
gets(msg);
dealMsg函数:
功能:寻找是否存在命令并进行相应的处理货提示
if(strcmp(msg,dos[i].order)==0)
{
if(strcmp(msg,"cls")==0)
{
//清屏
system("cls");
}
else if(strcmp(msg,"help")==0)
{
//输出全部命令
int j=0;
while(j<n)
{
printf("%s %s部命令 %s ",dos[j].order,dos[j].type,dos[j].mean);
j++;
}
}
else if(strcmp(msg,"time")==0)
{
time_t t;//定义一个时间变量
struct tm *at;//定义为结构体的数据类型方便阅读
char now[80];//定义一个字符串用来保存获取到的日期和时间
time(&t);//获取当前时间(以秒数表示)
at=localtime(&t);//获取当前时间和日期并转换为本地时间
strftime(now,79,"当前时间: %H:%M:%S",at);//根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串
puts(now);
printf("输入新时间:");
char temp[20];
gets(temp);
}
else if(strcmp(msg,"date")==0){
time_t t;//定义一个时间变量
struct tm *at;//定义为结构体的数据类型方便阅读
char now[80];//定义一个字符串用来保存获取到的日期和时间
char week[]={"日一二三四五六"};
char weekNum[2];
time(&t);//获取当前时间(以秒数表示)
at=localtime(&t);//获取当前时间和日期并转换为本地时间
strftime(weekNum,79,"%w",at);
strftime(now,79,"当前日期: %Y/%m/%d ",at);//根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串
printf("%s星期%c%c ",now,week[(weekNum[0]-48)*2],week[(weekNum[0]-48)*2+1]);
printf("输入新日期: <年月日> ");
char temp[20];
gets(temp);
}
//判断是否选择退出
else if(strcmp(msg,"exit")==0){
exit(0);
}
else
{
printf("'%s' ",dos[i].order);
printf("%s部命令输入正确! ",dos[i].type);
printf("该命令的作用是:%s ",dos[i].mean);
}
canfine = true;
break;
}
writeLog函数:
功能:记录用户输入的命令到log.txt中,没有该文件则创建一个再储存
if((fp = fopen("log.txt","a"))==NULL)
{
fp=fopen("log.txt","w");
}
fputs(msg,fp);
fputs(now,fp);//now为储存格式化系统时间后的数组
fclose(fp);
cmd.txt中储存的数据为:
dir 1 显示一个目录中的文件和子目录
cd 1 显示当前目录的名称或将其更改
md 1 创建一个目录
rd 1 删除目录
cls 1 清除屏幕
date 1 显示或设置日期
time 1 内部命令显示或设置系统时间
ren 1 重新命名文件
copy 1 将至少一个文件复制到另一个位置
help 0 提供Window命令的帮助信息
exit 0 退出命令解释程序
源代码地址 https://github.com/helloyoucan/MiniOS
- 4. 运行结果及分析
运行结果:
实验结果符合预料的结果。
四、 实验总结
难点1:在读取命令信息时,不能正确地读取并储存到结构体中。
解决办法:分行读取,一行储存着命令,命令类型及作用,需要分三个不同的位置读取,用制表符作为读取位置的区分。
难点2:储存命令类型的方法是用0和1区别的,但实际要求输出的是字符串类型。
解决办法:在读取时,根据读取到的0或1,用strcpy的方法储存“外”或“内”到结构体数组中。
难点3:未曾试过用C语言读取系统时间并输出。
解决办法:翻书寻找和在网络上寻找,最终在网络上找到一个大致符合自身要求的方式,加以修改后为自己所用。
难点:4:用户输入date时,需要输出中文的星期几,但在读取时读取到的只有英文的星期几或0到6的数字。
解决办法:用一个字符串数组储存日“一二三四五六”,再利用读取到的0到6之间的数字作为数组下标,但又遇到一个问题,汉字占的位置为2个字符,输出一个字需要同时输出储存着两个半个汉字的字符才能输出一个汉字,所以用读取到的数字乘2和读取到的数字乘2加一作为数组下标,同时输出两个字符,即输出“日一二三四五六”中的一个汉字。
心得体会:在看到实验要求时,根本不知道如何才能做出如实验结果截图显示的程序,在开始实验时,我并不是一味一行一行写代码,而是先构建好程序的结构,写好程序大致需要哪些功能,再把每一个功能分为一个函数,然后再完善每一个函数。在写每一个程序时,首先需要的不是马上写出代码,而是先把程序的结构功能细致分清,分开为很多的一小部分,再一部分一部分地写好,再结合为一个整体。