面向对象程序设计寒假作业3
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/2020OOP |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/2020OOP/homework/10288 |
这个作业的目标 | 1.继续完成作业二的编程题。 2.优化架构,思考代码的拓展性 3.或者扩大数字范围,支持负数 4.编译代码 5.测试代码 6.作业上传仓库 |
作业正文 | https://www.cnblogs.com/Sweetxinxin/p/12316634.html |
其他参考文献 | https://www.cnblogs.com/sddai/p/10249243.html https://www.cnblogs.com/hclw/p/9560442.html https://wenda.so.com/q/1365038777067506 |
仓库地址 | https://github.com/Sweetxinxin/winter-vocation-homework-3 |
Part 1 第二次作业完善
a.编译脚本
经过询问同学查找资料第二次作业得到了有效解决
关于编译脚本的路径问题,通过配置gcc环境及在控制面板中找到高级选项环境变量的path中添加gcc的路径
找到名为ComSpec的系统变量,查看是否是 :“%SystemRoot%\system32\cmd.exe”;然后找到名为PATH的变量,点击编辑:“;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Windows\SysWOW64”将其粘贴到PATH的后面保存后即配置完成。
将作业2的文件夹移入d盘中,编辑“编译脚本.txt”
重命名为“编译脚本.bat”,输入相关内容,运行结果如下:
b.单元测试
test1(10以内数的转换)的代码如下:
#include<bits/stdc++.h>
using namespace std;
int sum;
char num[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};
int transform(char z[]){
int i;
for(i=0;i<11;i++){
if(strcmp(z,num[i])==0) return i;
}
}
int main(){
int i;
char num2[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};
for(i=0;i<11;i++){
printf("%d\n",transform(num2[i]));
}
return 0;
}
test2(大于10小于100的数转换)代码如下:
#include<bits/stdc++.h>
using namespace std;
int sum;
char num[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};
int transform(char z[]){
int i;
for(i=0;i<11;i++){
if(strcmp(z,num[i])==0) return i;
}
}
char str1[20],str2[20];
int change(char d[]){
if(strlen(d)==2) return transform(d);
if(strlen(d)==4){
str1[0]=d[2];str1[1]=d[3];str1[2]='\0';
if(transform(str1)!=10) return transform(str1)+10;
else{
str1[0]=d[0];str1[1]=d[1];str1[2]='\0';
return 10*transform(str1);
}}
if(strlen(d)==6){
str1[0]=d[0];str1[1]=d[1];str1[2]='\0';str2[0]=d[4];str2[1]=d[5];str2[2]='\0';
return transform(str1)*10+transform(str2);
}}
int main(){
int i;
char m[100];
for(i=0;i<10;i++){
scanf("%s",m);
printf("%d",change(m));
}
return 0;
}
编辑单元测试的文本,文本内容如下:
将文件重命名为.bat,打开后测试结果为:
c.添加功能
在主函数中添加代码:
printf("输入文件名\n");
char f[10];
scanf("%s",f);
freopen(f,"r",stdin);
新建文本lang.txt,编辑文本lang.txt
通过命令行读取文件的操作:按win+R后在运行中打开cmd,如下图,步步寻找test.exe所在路径,运行lang.txt的内容,结果如下
Part 2 第三次作业
(1)拓展性
第三次作业提出的最值得思考的问题是编程题扩大数字范围及支持负数
思考:将数字范围扩大到1000以内应该怎样实现?支持负数应该用什么思路?
关于第三次作业中提高代码的拓展性,上网查阅资料了解到
可扩展性是指当需要为程序添加新的功能时,对其他模块的影响和添加的代价,可以从下面几个方面提高程序的可维护性和可扩展性
1.命名规范:命名要能传递出变量或者方法的含义
2.代码排版:留出合理的空白空间来区分不同的代码块
3.关键注释:仅为关键的代码添加注释
4.代码的层次性:不要试图在一个方法或者一个类中去全部实现,而要将它分成几个子逻辑,然后让每个子逻辑做自己的事情;当代码的层次性出来以后,就可以做到单一职责了
5.面向拓展编程:在写程序的过程中要时刻考虑到扩展
疑问和思考:那么什么是面向对象编程?与面向对象程序设计有何联系?
查阅网络资料,面向对象的概念简单的说就是 根据类创建除了对象 每个对象都有自己的属性和方法,而这些属性和方法都是围绕对象服务的,用到属性和方法都是对象.属性 对象.方法 实际上就是一个面向对象的过程。
思考:既考虑到拓展性又要使代码的可适用范围更加广泛应该怎么做?
考虑到第四方面的代码层次性,原代码中主函数关于输出的部分可以写作一个输出函数output
其次,想要在输出函数中让输出结果范围扩大到1000以内,我将输出函数做了如下修改,在输出函数中添加如下代码:
然后我做了以下测试,但是发现出现了下图结果
很显然“一百十”是不符合汉语习惯的,因此我又对输出函数做了修改:
但是在后来的思考过程中突然发现自己只考虑到了一百零几和一百一十几的情况,完全将几百零几、几百一十几的情况给忽略了,于是我又对代码进行了修改输出函数中范围为(100,1000)的部分如下:
if(sum>100&&sum<1000){
int c=sum/100;
if((sum%100)>19&&(sum%100)<=99){
printf("%s百",num[c]);
output(sum-c*100);
}
if((sum%100)>=10&&(sum%100)<=19){
printf("%d百一",c);
output(sum%100);
}
if((sum%100)>0&&(sum%100)<=9)
printf("%d百零%s",c,num[sum%100]);
}
思考:如果我要做负数的运算,即增加负多少或者减少负多少应该怎么做?
因此我考虑了两种思路,一种是将负多少转化为负数的数字形式进行运算,一种是将“负”字删除,符号另外考虑进行运算。我在先前作业中的change函数是通过比较单个字来转化的,如果不删除“负”字,change函数需要做很大改动,于是我决定采用第二种方法,不对change函数进行修改,直接在运算时先判断s字符串是否带有“负”字,然后再运算。
思考:怎么判断s字符串中有没有“负”字?
由于中文的习惯我们知道“负”字一定是白话文数字的第一个字,所以我将是第一个字赋给com字符串,(根据拓展性的第一方面命名规范,com的意思是compare即对比),然后对比“负”和com,若为零,为负数运算,若不为零则为正数的运算。
运算部分的代码如下:
for(;;){
scanf("%s",m);
if (strcmp("看看",m)==0) break;
scanf("%s",n);
scanf("%s",s);
com[0]=s[0]; com[1]=s[1]; com[2]='\0';
if (strcmp("负",com)==0){
for(k=2;s[k]!='\0';k++){
s1[p++]=s[k];
}
if (strcmp("增加",n)==0) sum-=change(s1);
if (strcmp("减少",n)==0) sum+=change(s1);
}
else{
if (strcmp("增加",n)==0) sum+=change(s);
if (strcmp("减少",n)==0) sum-=change(s);
}
}
思考:我要让output函数输出负数的形式要怎么做?
负数与正数输出的区别就在于一个负字,于是我觉得只要先打印一个“负”字,再用一层嵌套,即再调用一次output函数,其中参数用-sum即可,所以我的output函数完整代码如下:
int output(int sum){
if(sum>=0&&sum<=10) printf("%s",num[sum]);
if(sum>10&&sum<100){
int a;
a=sum/10;
if(a==1) printf("十");
else{
printf("%s",num[a]);
printf("十");
}
int b;
b=sum%10;
if(b!=0) printf("%s",num[b]);
}
if(sum%100==0) printf("%d百",sum/100);
if(sum>100&&sum<1000){
int c=sum/100;
if((sum%100)>19&&(sum%100)<=99){
printf("%s百",num[c]);
output(sum-c*100);
}
if((sum%100)>=10&&(sum%100)<=19){
printf("%d百一",c);
output(sum%100);
}
if((sum%100)>0&&(sum%100)<=9)
printf("%d百零%s",c,num[sum%100]);
}
if(sum<0){
printf("负");
output(-sum);
}
}
下面我随意输入测试了一下代码
正确结果不应该是“负十九”吗???于是我一步一步测试,看在哪一步运算出了错误
显然在第二次的计算中出了问题,那么后续的计算有没有出问题?
这样看来后来的计算是没有问题了,我又测试了其他样例
通过测试了多组类似的案例,我发现貌似第二次关于负数的运算总是错误的,期初我以为是删除“负”字后得到新字符串的部分有问题,于是我做了个测试,其他函数保留,主函数修改如下:
int main(){
char a[20],b[20],c[20],d[20];
scanf("%s %s %s %s",a,b,c,d);
char m[20],n[20],s[20],t[20],com[5],s1[20];
int p=0,k;
sum=change(d);getchar();
for(;;){
scanf("%s",m);
if(strcmp("看看",m)==0) break;
scanf("%s",n);
scanf("%s",s);
com[0]=s[0];com[1]=s[1];com[2]='\0';
if(strcmp("负",com)==0)
for(k=2;s[k]!='\0';k++){
s1[p++]=s[k];
}}
printf("%s",s1);
return 0;
}
测试输出删掉“负”字以后的字符串是否正确,测试结果如下
做了多组测试就不一一截图了,结果表明删除“负”字后的字符串均没有任何问题,所以问题不在此。这实在是太难受了,找bug找了几个小时都找不到,实在没有办法了...那我只能尽量把思考过程体现在博客里了.
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
int sum;
char num[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};//汉字列表
int transform(char z[]){
int i;
for(i=0;i<11;i++){
if(strcmp(z,num[i])==0) return i;//转换零到十
}
}
char str1[20],str2[20];
int change(char d[]){
if (strlen(d)==2) return transform(d);//十以内
if (strlen(d)==4){
str1[0]=d[2];str1[1]=d[3];str1[2]='\0'; //十几
if (transform(str1)!=10) return transform(str1)+10;
else{
str1[0]=d[0];str1[1]=d[1];str1[2]='\0';//几十
return 10*transform(str1);
}
}
if (strlen(d)==6){
str1[0]=d[0];str1[1]=d[1];str1[2]='\0';str2[0]=d[4];str2[1]=d[5];str2[2]='\0';//几十几
return transform(str1)*10+transform(str2);
}
}
int output(int sum){
if (sum>=0&&sum<=10) printf("%s",num[sum]);
if (sum>10&&sum<100){
int a;
a=sum/10;
if(a==1) printf("十");
else{
printf("%s",num[a]);
printf("十");
}
int b;
b=sum%10;
if(b!=0) printf("%s",num[b]);
}
if(sum%100==0) printf("%d百",sum/100);
if(sum>100&&sum<1000){
int c=sum/100;
if((sum%100)>19&&(sum%100)<=99){
printf("%s百",num[c]);
output(sum-c*100);
}
if((sum%100)>=10&&(sum%100)<=19){
printf("%d百一",c);
output(sum%100);
}
if((sum%100)>0&&(sum%100)<=9)
printf("%d百零%s",c,num[sum%100]);
}
if(sum<0){
printf("负");
output(-sum);
}
}
int main(){
char a[20],b[20],c[20],d[20];
scanf("%s %s %s %s",a,b,c,d);
char m[20],n[20],s[20],t[20],com[5],s1[20];
int p=0,k;
sum=change(d);
getchar();
for(;;){
scanf("%s",m);
if (strcmp("看看",m)==0) break;
scanf("%s",n);
scanf("%s",s);
com[0]=s[0]; com[1]=s[1]; com[2]='\0';
if (strcmp("负",com)==0){
for(k=2;s[k]!='\0';k++){
s1[p++]=s[k];
}
if (strcmp("增加",n)==0) sum-=change(s1);
if (strcmp("减少",n)==0) sum+=change(s1);
}
else{
if (strcmp("增加",n)==0) sum+=change(s);
if (strcmp("减少",n)==0) sum-=change(s);
}
}
scanf("%s",t);
output(sum);
return 0;
}
根据拓展性,我调整了以下代码里的注释长度(原先的注释太多太繁琐,我选择删繁就简),然后函数间分别空一行作为分隔,增添了一些空格让代码看起来更美观点。
(2)编译脚本
新建文本“编译.txt”,编辑文本内容,如图
重命名为.bat,运行如图
(3)单元测试
Test1代码:
#include<bits/stdc++.h>
using namespace std;
int sum;
char num[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};//数字列表
int transform(char z[]){
int i;
for(i=0;i<11;i++){
if(strcmp(z,num[i])==0) return i;
}
}
int main(){
int i;
char num2[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};
for(i=0;i<11;i++){
printf("%d\n",transform(num2[i]));
}
return 0;
}
Test2代码:
#include<bits/stdc++.h>
using namespace std;
int sum;
char num[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};
int transform(char z[]){
int i;
for(i=0;i<11;i++){
if(strcmp(z,num[i])==0) return i;
}
}
char str1[20],str2[20];
int change(char d[]){
if(strlen(d)==2) return transform(d);
if(strlen(d)==4){
str1[0]=d[2];str1[1]=d[3];str1[2]='\0';
if(transform(str1)!=10) return transform(str1)+10;
else{
str1[0]=d[0];str1[1]=d[1];str1[2]='\0';
return 10*transform(str1);
}}
if(strlen(d)==6){
str1[0]=d[0];str1[1]=d[1];str1[2]='\0';str2[0]=d[4];str2[1]=d[5];str2[2]='\0';
return transform(str1)*10+transform(str2);
}}
int main(){
int i;
char m[100];
for(i=0;i<10;i++){
scanf("%s",m);
printf("%d",change(m));
}
return 0;
}
Test3代码:
#include<bits/stdc++.h>
using namespace std;
int sum;
char num[15][5]={"零","一","二","三","四","五","六","七","八","九","十"};//汉字列表
int output(int sum){
if(sum>=0&&sum<=10) printf("%s",num[sum]);
if(sum>10&&sum<100){
int a;
a=sum/10;
if(a==1) printf("十");
else{
printf("%s",num[a]);
printf("十");
}
int b;
b=sum%10;
if(b!=0) printf("%s",num[b]);
}
if(sum%100==0) printf("%d百",sum/100);
if(sum>100&&sum<1000){
int c=sum/100;
if((sum%100)>19&&(sum%100)<=99){
printf("%s百",num[c]);
output(sum-c*100);
}
if((sum%100)>=10&&(sum%100)<=19){
printf("%d百一",c);
output(sum%100);
}
if((sum%100)>0&&(sum%100)<=9)
printf("%d百零%s",c,num[sum%100]);
}
if(sum<0){
printf("负");
output(-sum);
}
}
int main(){
int i;
for(i=0;i<10;i++){
scanf("%d",sum);
output(sum);
}
return 0;
}
单元测试脚本如下:
测试结果如下图:
transform函数和change函数都可以顺利测试而output函数的测试无法顺利进行,具体原因其实我也没搞明白。
(4)上传仓库
将所有文件上传仓库所在目录
打开githubdesktop,点击commit to master同步到远程仓库
打开网页版github检查仓库列表
作业已同步成功