面向對象程序設計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改為

整數 錢包 等於 十一
錢包 增加 二十六
錢包 減少 三
錢包 減少 二十
看看 錢包

  • 結果還是正確的


寫在最后

  • 不得不說通過第二次作業學到的東西還是很多的,很多都是之前不會的,只能現學,關鍵是有時候題目都不知道什么意思,不但要弄懂概念還要學很多新知識(分分鍾自閉
  • 順便記錄一下重定向(一開始以為第四部分的功能是這樣做)
    • 在第一部分代碼的情況下,在終端運行方式如下

文件重定向的定義:將原來**從標准輸入讀取數據**的文件操作重新定向為**從向其他文件讀取數據**;將原來要輸出到**標准輸出**的內容,重新定向輸出到**指定的其他文件**

<     // 標准輸入重定向
>     // 標准輸出重定向   清空原先的內容后添加新的內容 
>>    // 標准輸出重定向   在原來內容換行下方添加新的內容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM