作業連結
評分要求
本次作業的github連結。
相同部分
1) 兩位合作者的學号和對應部落格首頁連結
趙暢 111500206 http://www.cnblogs.com/ZCplayground/
胡緒佩 031602114 http://www.cnblogs.com/heihuifei/
2) 描述實作設計思路
大的子產品分為,題目子產品,外部函數,主函數三個。下面對各個子產品進行詳細介紹。
題目子產品,主要實作在了Expression.h這個頭檔案中。其核心是表達式類: Expression類的類聲明和類方法定義。在這裡實作的功能是:随機生成表達式,并且求出這個随機式子的運算結果,以下是一些本子產品解決的技術細節問題:
- srand和rand實際上是“僞随機”,我們努力做到了與真正意義上的“随機”相近的效果。
- 實作了數字、操作符、表達式的格式完全是随機産生的,長度也是範圍内可變的。但有一個缺點就是括号裡目前隻有兩個數,且還沒實作括号裡還有括号的情況。
- 防止了出現“除以零”這種情況的産生。
- 防止出現“除不盡”這種情況的産生。
- 對數字“10”,進行了正确的處理。
- 顯示給使用者的是中綴表達式。通過轉換成逆波蘭式求出随機生成的表達式的值。
外部函數子產品,主要是ExtendFunction.h。其中實作了語言版本選擇、使用者輸入答案判定的功能。技術細節方面:
- 版本選擇、使用者自定題目數量,這兩項有做輸入檢測,防止意外的輸入錯誤導緻程式錯誤運作
主函數,main.cpp。實作了主體功能。除了調用其他檔案中的函數,還負責了最後結果統計的功能。
3) 你們訂立的編碼規範
整個代碼規範我也放到github上了,Coding Standards。詳細的可以clone下來看看。我們的做法是從網上尋找一份C++編碼規範,依照比較詳細的規範,從中選擇一些适合的部分,略作修改和整理,組成我們這個小程式的規範。
我挑幾個比較重要、在此次編碼中用得最多的來說說:
- 相對獨立的程式塊之間、變量說明之後必須加空行。
為了讓人知道這是互相獨立的功能子產品。增加代碼可讀性。
- 一行隻寫一條語句。
- if、for、do、while、case、switch、default等語句自占一行,且if、for、do、while等語句的執行語句部分無論多少都要加括号{}。
- 使用操作符對多個關鍵字、變量、常量進行操作時,要加入空格使得代碼更加清晰。
這三條也是為了可讀性。
- 程式必須具有一定的注釋,便于對程式的了解。注釋需要簡介明了準确,不然有可能起反作用。一定要邊寫代碼邊注釋。
- 辨別符命名原則。變量:采取小駝峰法,函數名、類名:采取大駝峰法,數組名:采取小駝峰法,并且用下劃線分隔單詞。
與個人單打獨鬥不同,這兩點在多人合作中十分重要。
4) 程式實作和結果測試的截圖
第一個截圖主要展現了中文界面。

第二個截圖主要展現了輸入檢測子產品和英文界面。
5) github的送出連結和送出日志截圖
6) 兩位同學的分工和協作證據截圖
分工方面,我負責了main.cpp、Expression.h、stack.h三個檔案的代碼編寫工作。緒佩負責了ExtendFunction.h的大部分代碼,我負責少許潤色修改工作。代碼規範的doc檔案大部分由緒佩編輯而成,我負責檢查、修改。
截圖我就上傳一張特别有意思的。可以看到我們那天通過分享桌面一起工作到了半夜三點。那天的午夜12點我解決了一個bug,想分享給胡同學看,誰知在那會又找到了一個更大的bug,是以我們又開始一起debug。沒想到一開始debug就直接工作到了淩晨三點,才攻克了那個難關,完成了算法的主體部分,我們兩個人都很高興。第二天早上,就釋出了Preview version,預覽版本。
差異部分:
1)合作過程
在于胡同學接觸之後,了解到他有些知識儲備還不夠。是以一開始大概一周時間,我先自己思考問題的分解子產品、技術細節,同時給緒佩布置了任務。首先,讓他讀了一份代碼規範,學到了不少知識;接下來,我陸陸續續地安排了他去學習了switch、随機數、棧、string類、逆波蘭算法的用法,相信他有不少收獲吧。
在胡同學有了一定知識儲備之後,他也可以開始寫一些函數了,我們開始共同編碼。我們每天保持聯系,溝通各自進度,咨詢困惑。每天,我們遠端分享桌面或者語音通話的時間都在一小時以上。
在實作了一些小函數、胡同學有了一些知識儲備之後,2月7日,我在github上建立了dev分支,并開始了C++形式的編碼。13日,釋出了預覽版。15日下午,在master分支上釋出了最終版。
2)合作體會
1. 選擇搭檔
因為我是多有一年的學習經曆,是以有很大可能我會在兩個人的小隊中當“主心骨”(除非說我的隊友高中參加過競賽)。
我在尋找我的搭檔時,我不在意,他的水準要多高,或者打過什麼代碼,參加過什麼競賽之類的(在這次作業中,我自己也有很多地方是一邊打,發現了問題,再去學習的)。我的搭檔,他需要真正參與進來,而不是隻懷着一種“抱大腿”的思想。他要願意花時間學習,真正參與進我們兩個的團體中來。他要有積極的态度,面對困難不逃避。如果能做到這些,那麼就沒有問題。聞道有先後,我隻不過是比我的搭檔提早學了一些知識而已。我的搭檔隻要願意去學習,那麼我們兩個人一定能共同寫出來一款很不錯的軟體,實作1+1>2。這些,我覺得胡同學做的特别好。
2. 問題子產品化
不像是在OJ上面打題目,這次考慮的問題的規模就有點大了。問題一大,思考分子產品處理時要十分小心。我們都知道解決一個比較大的問題時要把問題拆分,就像寫一個大程式最好分塊成幾個函數。關于這裡我有一點體會就是拆分的程度要深一點,要到足夠具體的細節上。
假設一個問題可以分為A和B,B又能分為C和D。如果你在AB的層次上考慮這個問題而不是以ACD來考慮的話,那有可能在C和D上就會出毛病。如果在程式體量很龐大的情況下出現了這種失誤,牽一發動全身,十分麻煩。
下面是親身體會:原本有一個成員函數,叫RandomPart,會随機生成一個part并附加在expression後面。但在解決除号後面不能是零的問題時我又犯了難。是以我就把原本的RandomPart分解為RandomPart和AddPart兩個函數。并寫了新的PartValue。
3. 編碼習慣的改變
這樣的作業,我十分想寫出“高品質”的代碼,讓别人都看得懂的代碼——命名風格統一、語句書寫清晰、編碼習慣良好、注釋準确到位,等等。
我覺得,我算初步實作了這一願望。
自已寫代碼、自己在OJ上打題,和與他人共同編碼是完全不一樣的。自己寫代碼時,AC了就行,随便int abcde,全局變量随便開,函數接口想怎麼寫怎麼寫,不想寫函數也行,全丢main裡就好。但實際上這一切是不好的。變量名、全局變量、注釋等編碼習慣,條件判斷、循環、封裝等手段,不能像以前一樣AC了就行,而且要讓人看得懂,代碼是給人看的,這樣才有可維護性。
剛剛說到函數接口,這次共同編碼中發現,一個函數的傳回值類型和接受參數清單特别重要。假設有兩個函數做的工作大緻相似,但傳回值類型不同、參數清單不同,這兩點也足以讓編碼時,面對函數時的思維有很大的不同。最好在對問題有深刻了解的基礎上,經過雙方讨論商定後,确定函數原型,再對函數進行編碼。
說點别的
不足
1. STL
如果細心的朋友可以發現,我用的是自己寫的棧,而不是用标準模闆庫的棧。我是有打算用的,但是STL比較進階,有很多的預防性措施,而我了解的程度也不夠深,導緻使用了STL後,debug較為麻煩,是以就放棄了使用STL。但是以也學到了一些知識,可以看下面的參考連結。
2. git的共同協作功能
兩個人都是新手,是以有的地方操作的不是那麼的專業。在dev分支上開發時,我push上去的代碼是儲存在一個新檔案裡的,這樣的話,就沒有很好的運用github的compare(比較)功能。這是一個很棒的功能,能夠顯示你修改了哪些部分。如果push了一個新檔案,會顯示全都是“新增”。
3. “使用C++,展現面向對象的更佳”
這是一條作業加分項要求。C++用倒是用了,但個人感覺我的作業是沒達到“展現面向對象”那樣精髓的層面的。下面貼一個之前學C++時儲存的一段筆記:
使用對象不能保證你的程式就是面向對象,初學者或者很蹩腳的程式員很可能以面向對象之虛而行面向過程之實,這樣設計出來的所謂面向對象的程式很難有良好的可移植性和可擴充性。
以前不知道什麼意思,寫了程式才知道什麼意思。紙上得來終覺淺,絕知此事要躬行!
參考連結
學習過程中對自己幫助頗大的幾個網址,供大家參考!
- Expression:Deque iterator not dereferencable
- stack報錯 deque iterator not dereferencable
- c++ 報錯 deque iterator not incrementable
- 知乎:git 分支?
- git 建立分支送出遠端分支
- 将表達式轉換成逆波蘭式
- STL中的stack的pop函數為什麼不傳回值?
- c++中string類的詳解
順帶一提,本次作業使用程式設計環境是Microsoft Visual Studio 2015
鳴謝:Ladit
有任何意見和問題歡迎大家交流,有任何錯誤歡迎提出批評!