面向对象程序设计2020第二次作业

面向对象程序设计2020第一次作业

这个作业属于哪个课程 2020面向对象程序设计张栋班
这个作业要求在哪里 寒假作业2
这个作业的目标 完善代码、新建GitHub仓库并上传代码、制作编译脚本、进行单元测试并制作测试脚本、添加文件读取功能
作业正文 第二次作业
其它参考文献 git教程
shell教程
执行脚本的三种方式
C语言命令行参数的使用
C语言文件操作
git和GitHub教程

注: 系统是Mac OS


实践题

  • 创建SSH Key

  • 新建仓库

  • clone到本地

  • 其中仓库地址从这里复制

  • 创建.gitignore文件,配置后传到仓库(具体配置到gitignore模版找自己需要的,再复制组合到自己的.gitignore文件中)

  • 将代码放到该文件夹后传到仓库

  • push时如果出现问题,可参考下图


编程题

一、优化代码

  • 能够输入两位数三位数,如“二十”,“三十三”。具体实现在processStringToInt函数。
  • 分为几个函数,使含义更清晰,可读性提高
int convertToInt(char str[]);// 中文转为数字
char* convertToString(int n);// 数字转为中文
void error(void);//输出错误
void execute(void);// 执行
int processStringToInt(char number[]);// 在convertToInt函数的基础上,实现处理两位数和三位数中文
void printResult(int n); // 输出结果
  • 优化后完整代码
//main.h
#ifndef UNTITLED_MAIN_H
#define UNTITLED_MAIN_H

#include <stdio.h>
#include <string.h>
typedef struct variable
{
    char name[1000];
    int value;
} var;

int convertToInt(char str[]);// 中文转为数字
char* convertToString(int n);// 数字转为中文
void error(void);//输出错误
void execute(void);// 执行
int processStringToInt(char number[]);// 在convertToInt函数的基础上,实现处理两位数和三位数中文
void printResult(int n); // 输出结果

#endif //UNTITLED_MAIN_H



// main.c
#include "main.h"
int main()
{
    char integer[6];
    scanf("%s",integer);
    if(strcmp(integer,"整数")){ // 判断第一个词是否为“整数”
        error();
    }
    else{
        execute();//执行
    }
    return 0;
}

//error.c
#include "main.h"
void error()
{
    printf("格式错误\n");
}

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

//convertToString.c
char* convertToString(int n)
{
    if(n == 0)  return "零";
    else if(n == 1) return "一";
    else if(n == 2) return "二";
    else if(n == 3) return "三";
    else if(n == 4) return "四";
    else if(n == 5) return "五";
    else if(n == 6) return "六";
    else if(n == 7) return "七";
    else if(n == 8) return "八";
    else if(n == 9) return "九";
    else if(n == 10) return "十";
    else return "Error";
}

//execute.c
#include "main.h"
void execute()
{
    var a;
    char name[1000],operator[6],number[8];
    scanf("%s%s%s",a.name,operator,number);
    if(strcmp(operator,"等于")){
        error();
    }
    else{
        if(processStringToInt(number) == -1)    error();
        else {
            a.value = processStringToInt(number); //赋初始值
            scanf("%s", name);
            //循环执行到某行首个字符串不是变量名
            while (!strcmp(name, a.name)) {
                scanf("%s%s", operator, number);
                if (!strcmp(operator, "增加")) {
                    a.value += processStringToInt(number);
                } else if (!strcmp(operator, "减少")) {
                    a.value -= processStringToInt(number);
                } else {
                    error();
                    break;
                }
                scanf("%s", name);
            }
            if (!strcmp(name, "看看")) {
                scanf("%s", name);
                if (!strcmp(name, a.name))//“看看”后面输入的内容得和前面的变量名称相同
                {
                    printResult(a.value);
                } else {
                    printf("不存在此变量\n");
                }
            }
        }
    }
}

//processStringToInt.c
#include "main.h"
int processStringToInt(char number[])
{
    char str1[3],str2[3],str3[3];
    int sum = 0;
    strncpy(str1,number,2);
    str1[2] = '\0';
    sum = convertToInt(str1);
    if(strlen(number) == 4)//输入两位数中文
    {
        strncpy(str2,number+2,2);//从number字符串的第三个字符number[2]开始复制
        str2[2] = '\0'; //结尾要加\0,否则会出错
        if(convertToInt(str2) == 10)
            sum = convertToInt(str2) * convertToInt(str1);//大于10且为十的整数倍
        else if(convertToInt(str2) != -1)
            sum = convertToInt(str2) + convertToInt(str1); //十一到十九
        else
            sum = -1;
    }
    if(strlen(number) == 6)//输入三位数中文
    {
        strncpy(str3,number+4,2);
        str3[2] = '\0';
        sum = convertToInt(str1)*10 + convertToInt(str3);   // 二十一~九十九(不包括十的整数倍)
    }
    return sum;
}

//printResult.c
#include "main.h"
void printResult(int n)
{
    if(n <= 10)
    {
        printf("%s",convertToString(n));
    }
    else if(n % 10 == 0 && n < 100)
    {
        printf("%s十",convertToString(n/10));//十的整数倍输出为几十而不是几零
    }
    else if(n < 20)
    {
        n %= 10;
        printf("十%s",convertToString(n));//输出十几而不是一十几
    }
    else if(n < 100)
    {
        printf("%s十%s",convertToString(n/10),convertToString(n%10));
    }
  	else
    {
      	printf("变量数值超出范围");
		}
}

二、编译脚本

  • 代码如下,所使用脚本语言为shell
#!/bin/bash

fileName=$1 #注意不能有空格 #$0指此文件名 $1指运行此文件时的第一个参数名,也就是要编译的文件名

echo "开始编译......" 
gcc $fileName -o result.out # 使用一个定义过的变量,只要在变量名前面加美元符号$即可
if [ $? == 0 ]  # $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
then    #注意中括号周围的空格
    echo "编译成功......"
    echo "开始运行......"
    ./result.out
    if [ $? == 0 ]
    then
        echo "运行结束......"
    else
        echo "运行失败......"
    fi
else
    echo "编译失败......"
fi
  • 实现效果

三、 单元测试

  • 一开始理解错意思了,花了好长时间学了个单元测试工具CUnit,直到助教在群里说才知道是我想多了, 当场死亡

  • 首先测试三个转换函数(test.c作了修改,感谢分享)


//test.c
#include "main.h"

void assert_str_equals(const char *actual, const char *expected)
{
    if (!strcmp(actual, expected))
        printf("Pass\n");
    else
        printf("Failed. actual: %s, expected: %s\n", actual, expected);
    
}
void assert_int_equals(int actual, int expected)
{
    if (actual == expected)
        printf("Pass\n");
    else
        printf("Failed. actual: %d, expected: %d\n", actual, expected);
    
}

void test_convertToString()
{
    printf("test_convertToString 开始----------\n");
    assert_str_equals(convertToString(0),"零");
    assert_str_equals(convertToString(1),"一");
    assert_str_equals(convertToString(2),"二");
    assert_str_equals(convertToString(3),"三");
    assert_str_equals(convertToString(4),"四");
    assert_str_equals(convertToString(5),"五");
    assert_str_equals(convertToString(6),"六");
    assert_str_equals(convertToString(7),"七");
    assert_str_equals(convertToString(8),"八");
    assert_str_equals(convertToString(9),"九");
    assert_str_equals(convertToString(10),"十");
    assert_str_equals(convertToString(11),"Error");
    assert_str_equals(convertToString(21),"Error");
    printf("test_convertToString 结束----------\n");
}

void test_convertToInt()
{
    printf("test_convertToInt 开始----------\n");
    assert_int_equals(convertToInt("零"), 0);
    assert_int_equals(convertToInt("一"), 1);
    assert_int_equals(convertToInt("二"), 2);
    assert_int_equals(convertToInt("三"), 3);
    assert_int_equals(convertToInt("四"), 4);
    assert_int_equals(convertToInt("五"), 5);
    assert_int_equals(convertToInt("六"), 6);
    assert_int_equals(convertToInt("七"), 7);
    assert_int_equals(convertToInt("八"), 8);
    assert_int_equals(convertToInt("九"), 9);
    assert_int_equals(convertToInt("十"), 10);
    assert_int_equals(convertToInt("百"), -1);
    assert_int_equals(convertToInt("十一"), -1);
    printf("test_convertToInt 结束----------\n");
}

void test_pcocessStringToInt()
{
    printf("test_pcocessStringToInt开始----------\n");
    assert_int_equals(processStringToInt("零"), 0);
    assert_int_equals(processStringToInt("六"), 6);
    assert_int_equals(processStringToInt("十一"), 11);
    assert_int_equals(processStringToInt("二十"), 20);
    assert_int_equals(processStringToInt("七十"), 70);
    assert_int_equals(processStringToInt("四十二"), 42);
    assert_int_equals(processStringToInt("九十九"), 99);
    assert_int_equals(processStringToInt("六十六"), 66);
    assert_int_equals(processStringToInt("五十三"), 53);
    assert_int_equals(processStringToInt("一百"), -1);
    assert_int_equals(processStringToInt("三百"), -1);
    printf("test_pcocessStringToInt结束----------\n");
}

int main()
{
    test_convertToInt();
    test_convertToString();
    test_pcocessStringToInt();
}
  • 测试脚本
#!/bin/bash
echo "开始编译......"
gcc test.c excute.c convertToInt.c convertToString.c error.c printResult.c processStringToInt.c
if [ $? == 0 ]
then
  echo "编译成功......"
  echo "开始运行......"
  ./a.out
  if [ $? == 0 ]
  then
    echo "运行成功......"
  else
    echo "运行失败......"
  fi
else
  echo "编译失败"
fi
  • 运行结果
    • 运行方法:在终端cd进入文件夹,然后输入 bash filename.sh(filename指的是脚本的文件名)

  • 上面两个函数测试过了以后,其他几个函数由运行结果来验证


四、 添加以下功能

  • 通过命令行读取一个文件,然后运行这个文件。
  • 完成这题真是坎坷,一直理解错题目的意思。题目改完后才知道是要把1.txt 的内容作为输入
  • 首先要知道命令行参数的使用和文件的相关知识,main函数如下
//argc是参数的个数,argv[0]是执行的程序名,argv[1]是第一个参数(参考文章在开头有注明)
int main(int argc,char const* argv[])	
{
   FILE* fp = fopen(argv[1],"r"); //打开1.txt  “r”指的是只读
   if(fp) //fopen:如果文件顺利打开,返回指向该流的文件指针。如果文件打开失败则返回NULL
   {
       char integer[6];
       fscanf(fp,"%s", integer);	//与scanf的区别只是加了第一个参数,是文件指针 //如果要从文件中输入,就得用该方式,而不是普通的scanf
       if (strcmp(integer, "整数")) 
       { 
           error();
       } 
       else 
       {
           execute(fp);//该函数还要用到该文件,所以fp得传进该函数
       }
       fclose(fp);
   }
   else
   {
       printf("can't open the file\n");
   }
    return 0;
}
  • 运行
    • 首先cd进入文件夹,然后将程序编译成 lang
    • 然后如下图

  • 上图对应的1.txt是

整数 钱包 等于 零
钱包 增加 四
钱包 减少 三
看看 钱包

  • 如果将1.txt改为

整数 钱包 等于 十一
钱包 增加 二十六
钱包 减少 三
钱包 减少 二十
看看 钱包

  • 结果还是正确的


写在最后

  • 不得不说通过第二次作业学到的东西还是很多的,很多都是之前不会的,只能现学,关键是有时候题目都不知道什么意思,不但要弄懂概念还要学很多新知识(分分钟自闭
  • 顺便记录一下重定向(一开始以为第四部分的功能是这样做)
    • 在第一部分代码的情况下,在终端运行方式如下

文件重定向的定义:将原来**从标准输入读取数据**的文件操作重新定向为**从向其他文件读取数据**;将原来要输出到**标准输出**的内容,重新定向输出到**指定的其他文件**

<     // 标准输入重定向
>     // 标准输出重定向   清空原先的内容后添加新的内容 
>>    // 标准输出重定向   在原来内容换行下方添加新的内容
posted @ 2020-01-31 19:16  感官  阅读(662)  评论(5编辑  收藏  举报