• 面向对象程序设计寒假作业2编程题


    这个作业属于哪个课程 2020年面向对象程序设计 (福州大学 - 数学与计算机科学学院)
    这个作业要求在哪里 面向对象程序设计寒假作业2
    这个作业的目标 1.继续完成编程题。
    2.新建一个github仓库,并把作业推送到该仓库。
    3.发布博客。
    作业正文 面向对象程序设计寒假作业2实践题
    面向对象程序设计寒假作业2编程题
    Mac下Shell脚本使用学习笔记(一)
    Mac下Shell脚本使用学习笔记(二)
    其他参考文献 Macbook中使用Vim和GCC编译C程序
    c语言中所有文件操作函数详解
    C语言命令行参数详解
    freopen()函数的使用

    编程题

    1.题目要求:

    (1)继续完成作业一的编程题。
    (2)优化架构,一般要求每个函数长度不超过15行。
    (3)优化规范,尤其是命名规范。
    (4)制作一个编译脚本,运行该脚本可以编译你的代码,可选的脚本语言,python(2.7),windows批处理,powershell,shell。
    (5)进行单元测试,即测试每一个函数,并制作一个测试脚本,运行该脚本可以进行测试,并显示测试结果。
    (6)添加以下功能:通过命令行读取一个文件,然后运行这个文件。如我的程序叫lang,lang 1.txt代表我要运行1.txt这个文本中的代码

    2.分解需求:

    (1)对代码进行进一步优化:

    ①首先,我注意到在上次编程题的代码中,在一下这两个函数中,其功能存在重复赘余:

    int beginning(int wallet,char d[]){
        if(strcmp(d,"零")==0) return 0;
        else if(strcmp(d,"一")==0) return 1;
        else if(strcmp(d,"二")==0) return 2;
        else if(strcmp(d,"三")==0) return 3;
        else if(strcmp(d,"四")==0) return 4;
        else if(strcmp(d,"五")==0) return 5;
        else if(strcmp(d,"六")==0) return 6;
        else if(strcmp(d,"七")==0) return 7;
        else if(strcmp(d,"八")==0) return 8;
        else if(strcmp(d,"九")==0) return 9;
        else if(strcmp(d,"十")==0) return 10;
        else return -1;
    }
    
    int calculate(int wallet,char d[]){
          if(strcmp(d,"零")==0) return 0;
          else if(strcmp(d,"一")==0) return 1;
          else if(strcmp(d,"二")==0) return 2;
          else if(strcmp(d,"三")==0) return 3;
          else if(strcmp(d,"四")==0) return 4;
          else if(strcmp(d,"五")==0) return 5;
          else if(strcmp(d,"六")==0) return 6;
          else if(strcmp(d,"七")==0) return 7;
          else if(strcmp(d,"八")==0) return 8;
          else if(strcmp(d,"九")==0) return 9;
          else if(strcmp(d,"十")==0) return 10;
          else return -1;
    }
    

    作业一中之所以,将其分为两个函数是因为,第一个beginning函数其作用在于为变量“钱包”作初始化的作用,而第二个 calculate函数,是执行钱包总额增减的功能。但是,这两个函数在本质上起的是相同的作用,初始化函数也可以等同于对钱包的总额进行增减,故此我将这两个函数进行合并,并更名为change,其作用为对钱包总额的变化,代码如下:

    int change(int wallet,char d[]){
          if(strcmp(d,"零")==0) return 0;
          else if(strcmp(d,"一")==0) return 1;
          else if(strcmp(d,"二")==0) return 2;
          else if(strcmp(d,"三")==0) return 3;
          else if(strcmp(d,"四")==0) return 4;
          else if(strcmp(d,"五")==0) return 5;
          else if(strcmp(d,"六")==0) return 6;
          else if(strcmp(d,"七")==0) return 7;
          else if(strcmp(d,"八")==0) return 8;
          else if(strcmp(d,"九")==0) return 9;
          else if(strcmp(d,"十")==0) return 10;
          else return -1;
    }
    

    当然,相应的在主函数中,调用函数部分也会有相应的变化(代码见后)。
    ②然后,我在想,对于输出钱包总额时,我原先采用了三分支判断结构,是否可以进行修改使代码更简洁呢?
    原如下代码:

    void num(int i){
        if(i==0) printf("零");
        else if(i==1) printf("一");
        else if(i==2) printf("二");
        else if(i==3) printf("三");
        else if(i==4) printf("四");
        else if(i==5) printf("五");
        else if(i==6) printf("六");
        else if(i==7) printf("七");
        else if(i==8) printf("八");
        else if(i==9) printf("九");
        else if(i==10) printf("十");
    }
    void sum(int wallet){
        int a,b;
        if(wallet<=10){num(wallet);}
        else if(wallet<20){
            a=wallet%10;
            printf("十");
            num(a);
        }
        else{
            a=wallet/10;
            b=wallet%10;
            num(a);
            printf("十");
           if(b!=0) num(b);
        }
    }
    

    然后我尝试把后两个分支合并,代码如下:

    void num(int i){
        if(i==0) printf("零");
        else if(i==1) printf("一");
        else if(i==2) printf("二");
        else if(i==3) printf("三");
        else if(i==4) printf("四");
        else if(i==5) printf("五");
        else if(i==6) printf("六");
        else if(i==7) printf("七");
        else if(i==8) printf("八");
        else if(i==9) printf("九");
        else if(i==10) printf("十");
    }
    void sum(int wallet){
        int a,b;
        if(wallet<=10){num(wallet);}
        else{
            a=wallet/10;
            b=wallet%10;
            if(a!=0)num(a);//注意修改前的这一步
            printf("十");
           if(b!=0) num(b);
        }
    }
    

    我按照我修改后的代码尝试了三种情况,如下:



    前两种按照中文习惯是不存在任何问题的,但是第三种出现六问题,因为按照中文习惯,当钱包总额为17时,应该输出十七,而不是一十七。注意到,我在上一段代码作出的标记:

    if(a!=0)num(a);
    

    所以我改变了,这个判断语句a的条件,目的是为了当a=1时,其没有输出,故代码为:

    void num(int i){
        if(i==0) printf("零");
        else if(i==1) printf("一");
        else if(i==2) printf("二");
        else if(i==3) printf("三");
        else if(i==4) printf("四");
        else if(i==5) printf("五");
        else if(i==6) printf("六");
        else if(i==7) printf("七");
        else if(i==8) printf("八");
        else if(i==9) printf("九");
        else if(i==10) printf("十");
    }
    void sum(int wallet){
        int a,b;
        if(wallet<=10){num(wallet);}
        else{
            a=wallet/10;
            b=wallet%10;
            if(a!=1)num(a);//注意修改后的这一步
            printf("十");
           if(b!=0) num(b);
        }
    }
    

    验证结果(如下),发现答案正确:

    ③然后,我开始解决主函数的一些判断问题:
    原代码如下:

    int main() {
        char a[100],b[100],c[100],d[100];
        int wallet=0,i,flag=0;
        scanf("%s %s %s %s",a,b,c,d);
        if(strcmp(a,"整数")!=0||strcmp(c,"等于")!=0) flag=1;
        for(i=1;flag==0;i++){
            if(i==1) wallet=change(wallet,d);
            else {
                scanf("%s",a);
                if(strcmp(a,b)!=0&&strcmp(a,"看看")!=0) break;
                scanf("%s",c);
                if(strcmp(a,"看看")==0){
                    sum(wallet);
                    break;}
                scanf("%s",d);
             if(strcmp(c,"增加")==0) wallet+=change(wallet,d);
             if(strcmp(c,"减少")==0) wallet-=change(wallet,d);
            }
        }
       return 0;
    }
    

    当初,由于时间关系,我忽略了一个问题就是,如果我在第一次输入变量名为钱包后,在进行钱包总额的增减时,如果我输入的是其他变量名,那其总额仍会进行变化吗,于是我进行了测试:发现程序会结束,原来之前已经考虑过了这种情况,好吧,有点白费功夫了
    ④最后,优化规范,我对一些不规范对命名的调整,总代码如下:

    #include <stdio.h>
    #include <string.h>
    int change(int wallet,char d[]){
          if(strcmp(d,"零")==0) return 0;
          else if(strcmp(d,"一")==0) return 1;
          else if(strcmp(d,"二")==0) return 2;
          else if(strcmp(d,"三")==0) return 3;
          else if(strcmp(d,"四")==0) return 4;
          else if(strcmp(d,"五")==0) return 5;
          else if(strcmp(d,"六")==0) return 6;
          else if(strcmp(d,"七")==0) return 7;
          else if(strcmp(d,"八")==0) return 8;
          else if(strcmp(d,"九")==0) return 9;
          else if(strcmp(d,"十")==0) return 10;
          else return -1;
    }
    void num(int i){
        if(i==0) printf("零");
        else if(i==1) printf("一");
        else if(i==2) printf("二");
        else if(i==3) printf("三");
        else if(i==4) printf("四");
        else if(i==5) printf("五");
        else if(i==6) printf("六");
        else if(i==7) printf("七");
        else if(i==8) printf("八");
        else if(i==9) printf("九");
        else if(i==10) printf("十");
    }
    void printf_sum(int wallet){
        int a,b;
        if(wallet<=10) num(wallet);
        else{
            a=wallet/10;
            b=wallet%10;
            if(a!=1) num(a);
            printf("十");
            if(b!=0) num(b);
        }
    }
    int main() {
        char a[100],b[100],c[100],d[100];
        int wallet=0,i,flag=0;
        scanf("%s %s %s %s",a,b,c,d);
        if(strcmp(a,"整数")!=0||strcmp(c,"等于")!=0) flag=1;
        for(i=1;flag==0;i++){
            if(i==1) wallet=change(wallet,d);
            else {
                scanf("%s",a);
                if(strcmp(a,b)!=0&&strcmp(a,"看看")!=0) break;
                scanf("%s",c);
                if(strcmp(a,"看看")==0){
                    printf_sum(wallet);//这里重新命名函数,使代码更加易读
                    break;}
                scanf("%s",d);
             if(strcmp(c,"增加")==0) wallet+=change(wallet,d);
             if(strcmp(c,"减少")==0) wallet-=change(wallet,d);
            }
        }
       return 0;
    }
    

    待解诀问题:仍然只能进行零至十的赋值,将在下一阶段进行思考和改进。
    由于个人的力量是有限的,所以希望大家,可以对我的代码提出进一步对改进建议,或者你的看法。

    (2)制作一个编译脚本,运行该脚本编译代码(学习笔记已在链接标出):

    shell代码如下:

    #!/bin/bash
    
     echo -n "请输入需要编译的文件名:"
    read compile_file
     gcc $compile_file -o test1.out
     ./test1.out
    

    结果如下:

    之后,为了使一运行脚本便可编译代码,作出了修改,代码如下:

    #!/bin/bash
    
     gcc main.c -o test1.out
     ./test1.out
    

    结果如下:

    然后,我又参考了沈欢同学的作业,进行进一步完善了脚本,增加了一个判断,用于辨别是否成功编译。代码如下:

    #!/bin/bash
    
     gcc main.c -o test1.out
     if [ $? == 0 ]  # $?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
     then
         echo "编译成功"
         ./test1.out
         if [ $? == 0 ]
         then
             echo "运行结束"
         else
             echo "运行失败"
         fi
     else
         echo "编译失败"
     fi
    

    结果如下:

    需要注意的是,当我们在使用脚本编译代码的时候,需要将代码文件与脚本放在一个文件夹中,否则会出现以下情况:

    (3)进行单元测试,并制作一个测试脚本,运行并显示结果:

    这个地方,理解了半天,后面参考了提交的同学的博客和询问了同学,我才明白什么意思(非常感谢)
    注意到我的代码中总共有三个函数,而后面两个num函数与printf_sum函数皆为输出函数,负责直接输出结果,因此这两个函数的测试我们可以在结果中看到,因此这里只需测试chang函数:

    //main.h
    #include <stdio.h>
    #include <string.h>
    int change(char d[]){
          if(strcmp(d,"零")==0) return 0;
          else if(strcmp(d,"一")==0) return 1;
          else if(strcmp(d,"二")==0) return 2;
          else if(strcmp(d,"三")==0) return 3;
          else if(strcmp(d,"四")==0) return 4;
          else if(strcmp(d,"五")==0) return 5;
          else if(strcmp(d,"六")==0) return 6;
          else if(strcmp(d,"七")==0) return 7;
          else if(strcmp(d,"八")==0) return 8;
          else if(strcmp(d,"九")==0) return 9;
          else if(strcmp(d,"十")==0) return 10;
          else return -1;
    }
    

    测试部分代码:

    #include "main.h"
    void judge_change(int number_actual,int number_example){
        if(number_actual==number_example) printf("Pass
    ");
        else printf("Fail
    ");
    }
    void test_change(){
         printf("test_change begins
    ");
        judge_change(change("零"),0);
        judge_change(change("一"),1);
        judge_change(change("二"),2);
        judge_change(change("三"),3);
        judge_change(change("四"),4);
        judge_change(change("五"),5);
        judge_change(change("六"),6);
        judge_change(change("七"),7);
        judge_change(change("八"),8);
        judge_change(change("九"),9);
        judge_change(change("十"),10);
        judge_change(change("二十"),-1);
        printf("test_change is over
    ");
    }
    
    int main() {
        test_change();
       return 0;
    }
    

    按照(2)的步骤,我们建立相应的脚本文件,脚本代码如下:

    #!/bin/bash
    
     gcc main.c -o test2.out
     if [ $? == 0 ]
     then
         echo "编译成功"
         ./test2.out
         if [ $? == 0 ]
         then
             echo "运行结束"
         else
             echo "运行失败"
         fi
     else
         echo "编译失败"
     fi
    

    打开终端进行测试,结果如下:

    Change 函数测试过后,我们来通过结果查看其他两个函数的正误:


    以上就是测试部分的内容,感谢沈欢同学的帮助。

    (4)添加功能:过命令行读取一个文件,然后运行这个文件

    一看到题目疑惑不解,当学完shell后还以为就是Shell 文件包含重定向,后面发现并不是,这样,查了资料(链接已贴出)发现原来在我们c语言课本最后一章中有提到过对文件对操作(当初老师没教,而且考试也不考,就没看细看这一章,可是这次放假书放学校了,等回学校的时候再好好看看书)。以下是我的代码:

    //main.h
    #include <stdio.h>
    #include <string.h>
    int change(int wallet,char d[]){
          if(strcmp(d,"零")==0) return 0;
          else if(strcmp(d,"一")==0) return 1;
          else if(strcmp(d,"二")==0) return 2;
          else if(strcmp(d,"三")==0) return 3;
          else if(strcmp(d,"四")==0) return 4;
          else if(strcmp(d,"五")==0) return 5;
          else if(strcmp(d,"六")==0) return 6;
          else if(strcmp(d,"七")==0) return 7;
          else if(strcmp(d,"八")==0) return 8;
          else if(strcmp(d,"九")==0) return 9;
          else if(strcmp(d,"十")==0) return 10;
          else return -1;
    }
    void num(int i){
        if(i==0) printf("零");
        else if(i==1) printf("一");
        else if(i==2) printf("二");
        else if(i==3) printf("三");
        else if(i==4) printf("四");
        else if(i==5) printf("五");
        else if(i==6) printf("六");
        else if(i==7) printf("七");
        else if(i==8) printf("八");
        else if(i==9) printf("九");
        else if(i==10) printf("十");
    }
    void printf_sum(int wallet){
        int a,b;
        if(wallet<=10){num(wallet);}
        else{
            a=wallet/10;
            b=wallet%10;
            if(a!=1)num(a);
            printf("十");
           if(b!=0) num(b);
        }
    }
    void test(){  //注意把原代码的main函数改名,便于后续引用。
        char a[100],b[100],c[100],d[100];
        int  wallet=0,i,flag=0;
        scanf("%s %s %s %s",a,b,c,d);
        if(strcmp(a,"整数")!=0||strcmp(c,"等于")!=0) flag=1;
        for(i=1;flag==0;i++){
            if(i==1) wallet=change(wallet,d);
            else {
                scanf("%s",a);
                if(strcmp(a,b)!=0&&strcmp(a,"看看")!=0) break;
                scanf("%s",c);
                if(strcmp(a,"看看")==0){
                    printf_sum(wallet);
                    break;}
                scanf("%s",d);
             if(strcmp(c,"增加")==0) wallet+=change(wallet,d);
             if(strcmp(c,"减少")==0) wallet-=change(wallet,d);
            }
        }
        printf("
    ");
    }
    
    //main.c
    #include "main.h"
    //argc:命令行传入参数的总个数
    //argv:*argv[]是一个指针数组,里面存放的指针指向所有的命令行参数,argv[0]指向程序的全局路径,argv[1]指向在DOS命令行中执行程序名后的第一个字符串,argv[2]指向第二个。
    int main(int argc,char * argv[]) {
        if(argc>1){
        //当argc = 1的时候,表示只有一个程序名称;当argc>1时,说明文本的内容已经输入其中。
        freopen(argv[1],"r",stdin);
        //FILE *freopen(文件名,文件打开的模式,一个文件,通常使用标准流文件);
        //"r"代表"只读"
      //准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。
        test();
        }
        //把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区
        return 0;
    }
    

    然后通过终端将其编译为test,然后执行文本(注意在执行文本时需把文本与编译后的程序放在一个文件夹中):

    对应文本内容为:


    输出答案正确,添加功能成功。

    3.疑惑及解决

    * 本次作业将代码进行了进一步的优化,但仍存在一个问题待解决:对于钱包总额的变化仍然只能在*零至十*中进行,在下一阶段中将着重解决输入如“二十二”、“三十”的功能等实现 * 本次作业还学习了如何进行函数测试,了解了如何写脚本。对于单元测试,看到沈欢同学的博客中提到了*单元测试工具CUnit*,准备下一阶段中,进行学习。 * 本次作业还学习了github仓库的使用,将在下一阶段中借助作业EX进行深度学习。 * 本次作业还学习了如何通过c语言进行对文件的操作,以后也可将其进一步语言应用。有一个疑问:如果这一题我采用shell脚本中的文件包含重定向功能解决,应该也可以起到相似的功能,那么这两者有什么区别吗? * 将在下一阶段中学习c++,进一步了解课程。
  • 相关阅读:
    Linux安装和配置java
    动态代理:JDK动态代理和CGLIB代理的区别
    常用算法复习
    Linux重新学习
    oracle复杂查询是sql
    oracle触发器
    oracle存储过程
    oracle数据库操作
    java知识回顾
    Spring AOP简述
  • 原文地址:https://www.cnblogs.com/lvhang/p/12240361.html
Copyright © 2020-2023  润新知