2020面向对象程序设计寒假作业1题解
2020面向对象程序设计寒假作业1
这个作业属于哪个课程 | 2020面向对象程序设计 |
---|---|
这个作业要求在哪里 | 2020面向对象程序设计寒假作业1 |
这个作业的目标 | 1.问答题: (1)回答以下问题: 如果你不了解C++请回答以下问题:你认为C语言有什么缺陷(你觉得哪里用的不顺手)。 如果你已经了解C++请回答以下问题:你觉得C++和C语言比有什么优点。 (2)查阅相关资料,简述一下C语言/C++的编译过程。 2.实践题: 自己动手,完成以下任务: (1)查看自己的C++编译器版本。 (2)使用命令行编译一份C语言/C++代码。 3.编程题(请使用C语言或者C++完成以下题目): 编程要求 编写一个程序,输入满足以下语法要求的一段文字,输出运行后的结果。 变量定义:整数 钱包 等于 零 运算(加法):钱包 增加 四 运算(减法):钱包 减少 四 输出:看看 钱包 |
作业正文 | 问答题与实践题 编程题 |
其他参考文献 | C语言编译过程详解 静态链接与动态链接 |
1.问答题
(1)你认为C语言有什么缺陷(你觉得哪里用的不顺手)?
从本人近期C语言使用体验上来谈,我觉得首先C语言对于某些相对固定的功能没有进行概括封装成库函数,相对比较麻烦,例如C语言要实现排序,使用冒泡或者选择排序的话都要用双重循环来跑一遍,如果直接用库函数实现排序功能的话,可能会使代码来的更加简洁。还有就是感觉因为C语言灵活性强,自由度高,所以代码的可读性较差,对于我们初学者而言,如果码的太过随意,一不注意可能自己的代码就只有自己能看的懂了😂。
(2)简述一下C语言/C++的编译过程
c语言编译(从源代码到二进制行程序)共经过四个步骤:a.预处理 b.编译 c.汇编 d.链接
a.预处理
首先读取C语言源代码,将所有#include头文件以及宏定义替换成其所包含的实际文件,同时将注释去掉并进行条件编译。预处理过程实际上是在为编译做准备,将不需要的注释等文件删去,对C源码进行扩充和整理,方便在下一步转化为特定汇编代码。(通过查阅相关资料了解到在预处理后生成的文件仍为文本文件,但比预处理前的文件要大的多,由此可见头文件及宏定义,在某种意义上说,除了方便使用外还大大减少了C源代码的空间占用,节省了空间)
b.编译
这里的编译是指将经过预处理之后的程序转换成特定汇编代码的过程。该过程会进行语法的检查,如果语法出现问题,编译就无法进行,相应编译器就会报错。
c.汇编
汇编过程将上一步的汇编代码转换成机器码,产生目标文件,目标文件是二进制格式。机器码就是能够直接被计算机理解和接受的语言,但对于人来说不易理解。
d.链接
链接过程将多个目标文件以及所需的库文件链接成最终的可执行文件(及形成以.exe为拓展名的文件)。链接分为静态链接和动态链接两种,静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法,而动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息。
2.实践题
(1)查看自己的C++编译器版本。
a.查看Dev-C++所带gcc\g++编译器版本。
首先快捷键win+R打开运行,输入cmd打开命令提示符,然后可通过cd指令转换到编译器的绝对路径输入gcc -v进行查看。
或者直接将编译器的绝对路径加入到环境变量path中,再查看。(省去输入绝对路径的麻烦)
b.查看VS所带Microsoft C/C++编译器cl.exe版本。(可用VS自带命令行,已配置好环境变量可直接查看)
(2)使用命令行编译一份C语言/C++代码。
3.编程题
中国文化博大精深,从仓颉造字开始,汉字一直流传到了今天。我们在感叹汉字的源远流长时,也不禁感慨,为什么没有一门使用汉字编程的语言?
汉字真的不能编程吗?最近文言文编程火了一把,吾有一數。曰三。名之曰「甲」。这朴实无华的变量定义无疑不是几千年来中华文化的发展中一朵奇葩。
今天小王同学想,文言文能编程那白话文呢?他找到了你,让你帮帮他。
编程要求
编写一个程序,输入满足以下语法要求的一段文字,输出运行后的结果。
变量定义:整数 钱包 等于 零
运算(加法):钱包 增加 四
运算(减法):钱包 减少 四
输出:看看 钱包
样例
输入:
整数 钱包 等于 零
钱包 增加 四
钱包 减少 三
看看 钱包
输出:
一
注意事项
注意:
1.输入输出用例均为GBK编码,推荐使用vscode把文本切换为GBK编码。
2.数字只会出现以下 零一二三四五六七八九十 。
操作:
1.读题,提取出题目的要求。
2.分解需求,把需求分解为几个你觉得不太相关的模块。
3.思考每个模块怎么写,可以从简单的模块开始写。
4.对于不会的问题进行查阅资料。
5.对于每一个模块设计测试用例。
(1)题目要求
实现汉字为变量的0~99之间的数值存储及查询。
题目要求分为三个部分:
a.实现以输入“整数”为起始条件的变量定义;
b.实现0~99内数值运算;
c.实现以输入“看看”为条件的数值查询功能。
(2)需求分析与模块分类
首先,依题目及样例可知,输入均为汉字,而GBK编码中汉字占两个字节且零到十在对应编码上并没有明显可用的关系,所以首先需要将输入的汉字转化为数字再进行数值计算,汉字数字识别与转化可以作为一个相对独立的模块来实现。其次,就是初始化后的数值运算,根据相应指令中的加减乘除的命令,对转化为数字的数值进行运算,也可以作为一个模块来实现。之后,由于输出的也是汉字数字,所以需要将计算处理后的数字转换为汉字后再输出,这部分也可以作为一个模块。最后,由于题目在格式以及数值大小上有限定,所以需要考虑出错的情况,主要是在定义以及运算的时候出现,这也可以作为一个融汇于以上模块的特殊模块进行考虑。
总结一下就是:
a.汉字识别转换模块
b.条件识别及运算模块
c.数值转化输出模块
d.错误分析模块(特殊)
(3)模块实现
a.汉字识别转换模块
首先对汉字对应数字类型进行分析,发现共有四种汉字表达类型分别是:零一二等单个汉字表达的数字;十一、十二等以十开头的两个汉字表达的数字;二十、三十等以十结尾的数字;以及“几十几”类型的数字。因此需要设计分别对应于这四种情况的转换,代码如下:
char list[11][5]={"零","一","二","三","四","五","六","七","八","九","十"}; //运用数组下标和汉字对应关系进行查表更方便
int swap(char a[]){
int i;
for(i=0;i<11;i++){
if(strcmp(list[i],a)==0){
return i;
}
}
}
int num(char a[]){
char b[10],c[10];
if(strlen(a)==2){
return swap(a); //对应零一二等单个汉字表达的数字
}
else if(strlen(a)==4){
b[0]=a[2];
b[1]=a[3];
b[2]='\0';
if(swap(b)!=10) return 10+swap(b);//对应十一、十二等以十开头的两个汉字表达的数字
else{
b[0]=a[0];
b[1]=a[1];
b[2]='\0';
return 10*swap(b);//对应二十、三十等以十结尾的数字
}
}
else if(strlen(a)==6){
b[0]=a[4];
b[1]=a[5];
b[2]='\0';
c[0]=a[0];
c[1]=a[1];
c[2]='\0';
return swap(b)+swap(c)*10;//对应“几十几”类型的数字
}
}
b.条件识别及运算模块
分别对应识别“增加”、“减少”、“除以”、“乘以”等指令并进行运算。
int judge(int n,char a[],char b[]){
int sum1;
sum1=num(b);
if(strcmp(a,"增加")==0) return n+sum1;
else if(strcmp(a,"减少")==0) return n-sum1;
else if(strcmp(a,"乘以")==0) return n*sum1;
else if(strcmp(a,"除以")==0) return n/sum1;
}
c.数值转化输出模块
该模块同a模块需要对应识别四种情况并输出。
if(sum>=0&&sum<=10){
printf("%s\n",list[sum]);
}
else {
if(sum%10==0){
printf("%s十\n",list[sum/10]);
}
else if(sum<=19){
printf("十%s\n",list[sum%10]);
}
else {
printf("%s十%s\n",list[sum/10],list[sum%10]);
}
}
d.错误分析模块(特殊)
主要在主函数中出现,见完整代码
(4)完整代码
#include<stdio.h>
#include<string.h>
char list[11][5]={"零","一","二","三","四","五","六","七","八","九","十"}; //运用数组下标和汉字对应关系进行查表更方便
int swap(char a[]){
int i;
for(i=0;i<11;i++){
if(strcmp(list[i],a)==0){
return i;
}
}
}
int num(char a[]){
char b[10],c[10];
if(strlen(a)==2){
return swap(a); //对应零一二等单个汉字表达的数字
}
else if(strlen(a)==4){
b[0]=a[2];
b[1]=a[3];
b[2]='\0';
if(swap(b)!=10) return 10+swap(b);//对应十一、十二等以十开头的两个汉字表达的数字
else{
b[0]=a[0];
b[1]=a[1];
b[2]='\0';
return 10*swap(b);//对应二十、三十等以十结尾的数字
}
}
else if(strlen(a)==6){
b[0]=a[4];
b[1]=a[5];
b[2]='\0';
c[0]=a[0];
c[1]=a[1];
c[2]='\0';
return swap(b)+swap(c)*10;//对应“几十几”类型的数字
}
}
int judge(int n,char a[],char b[]){
int sum1;
sum1=num(b);
if(strcmp(a,"增加")==0) return n+sum1;
else if(strcmp(a,"减少")==0) return n-sum1;
else if(strcmp(a,"乘与")==0) return n*sum1;
else if(strcmp(a,"除以")==0) return n/sum1;
}
int main(){
int i,sum;
char a[100],b[100],c[100],d[100];
scanf("%s",a);
if(!strcmp(a,"整数")){
scanf("%s %s %s",a,b,c);
}
else{
printf("输入格式错误\n");
return 0;
}
sum=num(c);//测试点:printf("%d\n",sum);
while(scanf("%s %s",d,b)!=EOF){
if(strcmp(d,"看看")){ //可在运算过程中重复运用查看功能
scanf("%s",c);
if(!strcmp(a,d)){
sum=judge(sum,b,c);//测试点:printf("%d\n",sum);
if(sum>=99||sum<=0){
printf("超出可容纳范围\n");
return 0;
}
}
else {printf("变量不匹配\n");
return 0;
}
}
else{
if(sum>=0&&sum<=10){
printf("%s\n",list[sum]);
}
else {
if(sum%10==0){
printf("%s十\n",list[sum/10]);
}
else if(sum<=19){
printf("十%s\n",list[sum%10]);
}
else {
printf("%s十%s\n",list[sum/10],list[sum%10]);
}
}
}
}
return 0;
}
(5)测试用例
a.基本功能测试
b.运用测试点进行测试(测试点见完整代码注释)
由此可知输入格式正确的情况下输出基本无误
c.错误分析测试
(6)存在问题及总结
在输入自己拟定的测试样例时,还是找出了不少bug,例如判断条件||打成了&&等等,自我感觉在错误分析上还不够完善,应该还存在一些其他可能出错的地方,代码还有可以提升的空间。通过这道题学到了一些关于汉字编码方面的知识,同时也加深了对于字符运用方面的理解,例如strcmp函数的运用,以及汉字如何存储。
本人水平有限,如果有发现问题或有更好的建议欢迎大家向我提出😄