1. 程式人生 > >[0415] C++簡單程序設計-4 類和對象2

[0415] C++簡單程序設計-4 類和對象2

compare gets draw 描述 try 處理 圖形 編譯 ios

南京信息工程大學實驗報告

實驗名稱 類和對象2 實驗日期 2018-4-17 得分 指導教師 耿學華 計軟院 專業 計嵌+軟嵌 年級 2017 級 班次 (1) 姓名 施昊陽 學號 20161334026

一、實驗目的


  1. 掌握類的設計、定義、實現和測試
  2. 深度理解面向對象編程思維與結構化編程思維的不同

二、實驗準備


實驗前,請圍繞以下內容復習/學習指定內容

  1. C++程序以項目文件方式組織的多文件結構
    學習教材「5.6.1 節 C++程序的一般組織結構」
  2. 編譯預處理指令
    學習教材「5.6.4 節 編譯預處理指令」
  3. 類和對象的定義和使用
    復習第 4 章相關內容

三、實驗內容


  1. 練習將 C++ 程序以項目文件組織的多文件結構方式編寫

    將實驗 3 中的 4-20 以多文件結構方式重寫

  2. 基於已有信息,補足並擴充程序,體會面向對象編程與結構化編程思維的不同。 在 graph 文件夾裏提供有三個文件
    基於已有信息,補足並擴充程序,體會面向對象編程與結構化編程思維的不同。
    在 graph 文件夾裏提供有三個文件

文件 文件內容說明
graph.h 類 Graph 的聲明
graph.cpp 類 Graph 的實現
main.cpp 類 Graph 的測試:定義 Graph 類的對象,調用 public 接口繪制圖形

要求如下:

  • 新建一個項目,添加以上三個文件到項目中。

  • 補足 graph.cpp 中類的成員函數 draw()的實現,使得在 main()中對類的測試能夠實現以下顯示效果:

代碼 效果
技術分享圖片 技術分享圖片
技術分享圖片 技術分享圖片
  • 擴展類 Graph 的功能(選做)
    • 支持重新設置顯示的字符、尺寸,每次重新設置後,自動重繪圖形;
    • 支持圖形的前景色、背景色設置和調整;
    • 支持通過方向鍵控制圖形水平移動或垂直移動,等等。
  1. 基於需求描述設計、定義並實現類 Fraction,並編寫代碼完成測試。
    具體要求描述如下:
    設計一個類 Fraction 描述分數(兩個整數的比值)
    技術分享圖片
    類 Fraction 的數據成員包括兩個 int 型變量 top 和 bottom,分別代表分子和分母。
    技術分享圖片
    經過分析後,通過設計和實現接口(即成員函數)實現如下要求:
  • 類 Fraction 的基本功能列表
    • 定義 Fraction 類對象時,支持如下形式:
      技術分享圖片
      提示:通過編寫構造函數實現,並且,基於不同情形,編寫重載構造函數。
    • Faction 類對象能夠進行如下操作:
      • 加、減、乘、除運算
      • 對兩個分數值進行比較運算,返回其大小關系
      • 分數的輸入、輸出
    • 通過定義成員函數來實現。設計每一個成員函數時,從以下幾個方面考慮:
      • 成員函數的功能;
      • 是否需要形參和返回值,如果需要,需要幾個參數,參數的類型是什麽,返回值的類型是什麽
  • 類 Fraction 的擴展功能(選做)
    • 對分數進行規範化處理,確保分數在形式上,只有分子為負數,並且,分數值是約簡形式。
      即:
      2/-3 經過規範化處理後,轉換為-2/3
      15/21 經過規範化處理後,轉換為 5/7
      -2/-6 經過規範化處理後,轉換為 1/3
    • 實現分數到十進制之間的轉換
      例如:3/4 會轉換為 0.75 輸出
  • 設計並實現好 Fracton 類後,在 main()中測試時,要測試到各種情形,以確保你所設計和實現的類的各項功能都能正常運行。

  • 以項目文件組織的多文件結構方式編寫(fraction.h, fraction.cpp, main.cpp)

四、實驗結論


0. 實驗內容 1

  • 如何在 Dev-Cpp 中創建多文件結構工程
    • 文件-新建-項目
    • Project.h, Project.cpp, Main.cpp 添加到項目
    • GIF演示
      技術分享圖片
  • C++ Code: 見上文
  • Java Code:

    Complex.java
    package ex1;
    public class Complex {
    private double real;
    private double imaginary;
    
    public Complex(double r0,double i0){
        real = r0;
        imaginary = i0;
    }
    
    public Complex(double r0){
        real = r0;
        imaginary = 0;
    }
    public Complex(Complex c0){
        real = c0.real;
        imaginary = c0.imaginary;
    }
    public void add(Complex c0) {
        real += c0.real;
        imaginary += c0.imaginary;
    }
    public void show() {
        if (imaginary > 0) System.out.println(real + "+" + imaginary + "i");
        else if(imaginary < 0) System.out.println(real + "-" + imaginary + "i");
        else System.out.println(real);
    }
    }
  • console:
    技術分享圖片

1. 實驗內容 2

  • 基於Graph graph1(‘*‘,5);的圖像分析 draw() 算法:
    每一行輸出的符號數為 2X行號+1 ,輸出的空格數為 2X總行號+1 - 每行輸出的符號數。
  • 實驗環境:Dev C++ 5.11
  • C++ Code:
    • Graph.cpp:

      #define rap(a,b) for(int a=1;a<=b;++a)
      #include<iostream>
      #include"Graph.h"
      using namespace std;
      Graph::Graph(char s,int l){
      sign=s;
      line=l;
      }
      void Graph::draw(){
      rap(i,line){
      int tmp=line-i;
      //cout<<tmp<<endl;
      rap(j,tmp) cout<<" ";
      rap(j,2*i-1)cout<<sign;
      rap(j,tmp) cout<<" ";
      cout<<endl;
      }
      return ;
      }
    • Graph.h:

      class Graph{
      protected:
      char sign;
      int line;       
      public:
      Graph(char s,int l);
      void draw();
      };
    • main.cpp:

      #include "Graph.h"
      int main(){
      Graph graph1('*',5);
      graph1.draw();
      Graph graph2('$',7);
      graph2.draw();
      return 0;
      }
  • Java Code:
    • Graph.java:

      public class Graph {
      private static char sign;
      private static int line;
      public Graph(char s, int l) {
      sign = s;
      line = l;
      }
      public void draw() {
      for(int i = 1; i <= line; ++ i) {
          int tmp = line - i;
          for(int j = 1; j <= tmp; ++j) System.out.print(" ");
          for(int j = 1; j <= 2*i-1; ++j) System.out.print(sign);
          for(int j = 1; j <= tmp; ++j) System.out.print(" ");
          System.out.print("\n");
      }
      }
      public void renew(char s, int l) {
      sign = s;
      line = l;
      draw();
      }
      }
    • Main.java:

      public static void main(String[] args) {
      // TODO 自動生成的方法存根
      Graph graph1=new Graph('*', 5);
      graph1.draw();
      Graph graph2=new Graph('$', 7);
      graph2.draw();
      graph2.renew('%', 8);
      }
  • console:
    技術分享圖片

  • 選做部分:
    • 重新設置顯示的字符、尺寸:
      • Code(Graph.h):void rewrite(char s,int l);
      • Code(Graph.cpp):

        void Graph::rewrite(char s,int l){
        sign=s;
        line=l;
        draw();
        } 
      • Code(Main.cpp):graph2.rewrite(‘%‘,8);
      • 演示:
        技術分享圖片

    • 支持圖形的前景色、背景色設置和調整;
      • 設置console輸出的顏色:

        HANDLE consolehwnd=GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(consolehwnd,Color);
        其中color為8位二進制數,高位存放前景色,低位存放背景色。
      • 顏色編號
      • Code(Graph.h):

        protected unsigned int forecolor,backcolor;
        int str2color(string a);
      • Code(Graph.cpp):

        int Graph::str2color(string a)
        {
        if (strcasecmp(a.c_str(), "black") == 0)return 0;
        if (strcasecmp(a.c_str(), "blue") == 0)return 1;
        if (strcasecmp(a.c_str(), "green") == 0)return 2;
        if (strcasecmp(a.c_str(), "lackblue") == 0)return 3;
        if (strcasecmp(a.c_str(), "red") == 0)return 4;
        if (strcasecmp(a.c_str(), "purple") == 0)return 5;
        if (strcasecmp(a.c_str(), "yellow") == 0)return 6;
        if (strcasecmp(a.c_str(), "white") == 0)return 7;
        if (strcasecmp(a.c_str(), "grey") == 0)return 8;
        return 0;
        }
        void Graph::setcolor(string fore, string back){
        forecolor=str2color(fore);
        backcolor=str2color(back);
        }
        void Graph::draw(){
        HANDLE consolehwnd=GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(consolehwnd,(forecolor<<4)+backcolor);
        }
      • Code(Main.cpp):

        #include "Graph.h"
        int main(){
        Graph graph1('*',5);
        graph1.setcolor("white","red");
        graph1.draw();
        Graph graph2('$',7);
        graph2.setcolor("blue","yello");
        graph2.draw();
        graph2.setcolor("grey","green");
        graph2.rewrite('%',8);
        return 0;
        }
      • console:
        技術分享圖片

    • 方向鍵控制圖形移動:
      • Code(Main.cpp):

        while(1){
        int ch=getch();
        switch(ch){
        case 72:if(offsety>0)offsety--;break;
        case 75:if(offsetx>0)offsetx--;break;
        case 77:offsetx++;break;
        case 80:offsety++;break;
        }
        system("cls"); 
        graph2.redraw(offsetx,offsety);
        }
      • Code(Graph.h):void redraw(int x,int y);
      • Code(Graph.cpp):

        void Graph::redraw(int x,int y){
        rap(j,y)cout<<endl;
        rap(i,line){
        int tmp=line-i;
        rap(j,x)cout<<" ";
        rap(j,tmp) cout<<" ";
        rap(j,2*i-1)cout<<sign;
        rap(j,tmp) cout<<" ";
        cout<<endl;
        }
        }
      • 演示GIF:
        技術分享圖片

2. 實驗內容 3

  • UML類圖:
    技術分享圖片
  • Code:
    • Fraction.java

      package ex3;
      import java.util.Scanner;
      public class Fraction {
      private int top;
      private int bottom;
      private int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a%b);
      }
      private int abs(int a) {
      return a > 0 ? a : -a;
      }
      public Fraction(int t, int b) {
      top = t;
      bottom = b;
      }
      public Fraction(int t) {
      top = t;
      bottom = 1;
      }
      public Fraction() {
      top = 0;
      bottom = 1;
      }
      public void simplify() {
      if(bottom < 0) { 
          top = - top;
          bottom = - bottom;
      }
      int g = gcd(abs(top),abs(bottom));
      top /= g;
      bottom /= g;
      }
      public void add(Fraction c0) {
      bottom = bottom * c0.bottom;
      top = top * c0.bottom + c0.top * bottom;
      simplify();
      }
      public void subtract(Fraction c0) {
      bottom = bottom * c0.bottom;
      top = top * c0.bottom - c0.top * bottom;
      if(bottom < 0) { 
          top = - top;
          bottom = - bottom;
      }
      simplify();
      }
      public void multiple(Fraction c0) {
      top *= c0.top;
      bottom *= c0.bottom;
      simplify();
      }
      public void divde(Fraction c0) {
      if(c0.top == 0) {
          System.out.println("Error: Zero can't be divided.");
          return ;
      }
      top *= c0.bottom;
      bottom *= c0.top;
      simplify();
      }
      public boolean compare(Fraction c0) {
      return top * gcd(bottom, c0.bottom) - c0.top 
              * gcd(bottom, c0.bottom) > 0 ? true : false;
      }
      @SuppressWarnings("resource")
      public void readln() {
      Scanner sc=new Scanner(System.in);
      System.out.println("Plz input the Numerator and Denominator");
      top = sc.nextInt();
      int tmp = sc.nextInt();
      while (tmp == 0) {
          System.out.println("Zero can't be the Denominator, plz try again!");
          tmp = sc.nextInt();
      }
      bottom = tmp;
      }
      public void writeln() {
      if(bottom != 1) System.out.println(top + "/" + bottom);
      else System.out.println(top);
      }
      public double todecimal() {
      return (double)top/bottom;
      }
      }
    • Main.java

      package ex3;
      public class Main {
      public static void main(String[] args) {
      // TODO 自動生成的方法存根
      Fraction c1 = new Fraction (11,22);
      Fraction c2 = new Fraction (4);
      Fraction c3 = new Fraction ();
      c1.add(c2);
      c1.writeln();
      c1.subtract(c2);
      c1.writeln();
      c1.multiple(c2);
      System.out.println(c1.todecimal());
      c1.writeln();
      c1.divde(c2);
      c1.writeln();
      }
      }
    • Fraction.h

      #include<iostream>
      #include<cmath>
      using namespace std;
      class Fraction
      {
      protected:
      int top, bottom;
      int gcd(int a, int b);
      public:
      Fraction(int t, int b);
      Fraction(int t);
      Fraction();
      void simplify();
      void add(Fraction c0);
      void subtract(Fraction c0);
      void multiple(Fraction c0);
      void divde(Fraction c0);
      bool compare(Fraction c0);
      void readln();
      void writeln();
      double todecimal();
      };
    • Fraction.cpp

      int Fraction::gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a%b);
      }
      Fraction::Fraction(int t, int b) {
      top = t;
      bottom = b;
      }
      Fraction::Fraction(int t) {
      top = t;
      bottom = 1;
      }
      Fraction::Fraction() {
      top = 0;
      bottom = 1;
      }
      void Fraction::simplify() {
      if(bottom < 0) {
      top = - top;
      bottom = - bottom;
      }
      int g = gcd(abs(top),abs(bottom));
      top /= g;
      bottom /= g;
      }
      void Fraction::add(Fraction c0) {
      bottom = bottom * c0.bottom;
      top = top * c0.bottom + c0.top * bottom;
      simplify();
      }
      void Fraction::subtract(Fraction c0) {
      bottom = bottom * c0.bottom;
      top = top * c0.bottom - c0.top * bottom;
      if(bottom < 0) {
      top = - top;
      bottom = - bottom;
      }
      simplify();
      }
      void Fraction::multiple(Fraction c0) {
      top *= c0.top;
      bottom *= c0.bottom;
      simplify();
      }
      void Fraction::divde(Fraction c0) {
      if(c0.top == 0) {
      cout << "Error: Zero can't be divided.\n";
      return ;
      }
      top *= c0.bottom;
      bottom *= c0.top;
      simplify();
      }
      bool Fraction::compare(Fraction c0) {
      return top * gcd(bottom, c0.bottom) - c0.top* gcd(bottom, c0.bottom) > 0 ? true : false;
      }
      void Fraction::readln() {
      cout << "Plz input the Numerator and Denominator" << endl;
      cin >> top;
      int tmp;
      cin >> tmp;
      while (tmp == 0) {
      cout << "Zero can't be the Denominator, plz try again!" << endl;
      cin >> tmp;
      }
      bottom = tmp;
      }
      void Fraction::writeln() {
      if(bottom != 1) cout << top << "/" << bottom << endl;
      else cout << top <<endl;
      }
      double Fraction::todecimal() {
      return (double)top / bottom;
      }
    • Main.cpp

      #include "Fraction.h"
      #include <iomanip>
      int main() {
      Fraction c1 (11,-22);
      Fraction c2 (4);
      Fraction c3 ;
      c1.writeln();
      c1.add(c2);
      c1.writeln();
      cout << fixed<< setprecision(2) << c1.todecimal() << endl;
      c1.subtract(c2);
      c1.writeln();
      c1.multiple(c2);
      c1.writeln();
      c1.divde(c2);
      c1.writeln();
      return 0;
      }
  • console:
    技術分享圖片
  • 選做部分:
    • 規劃化處理:

      void Fraction:: simplify() {
      if(bottom < 0) {
      top = - top;
      bottom = - bottom;
      }
      int g = gcd(abs(top),abs(bottom));
      top /= g;
      bottom /= g;
      }
    • 轉換為十進制:

      double Fraction:: todecimal() {
      return (double)top / bottom;
      }

五、實驗總結與體會


  • 多文件結構式的項目在日後實際開發中更容易進行多人合作。
  • 作為從C++衍生出來的Java,所有東西都必須置入一個類,沒有類聲明,只有類定義。
  • My pleasure to participate in the design of this experiment~
    技術分享圖片

[0415] C++簡單程序設計-4 類和對象2