本博客爲完成結對項目所需的先導知識,題目不難,請認真對待 :)html
歡迎來到軟件工程 :)java
注:本次實驗爲附加做業,不作不扣分,作了有附加分c++
阿超家裏的孩子上小學一年級了,這個暑假老師給家長們佈置了一個做業:家長天天要給孩子出一些合理的,但要有些難度的四則運算題目,而且家長要對孩子的做業打分記錄。git
做爲程序員的阿超心想,既然天天都須要出題,那何不作一個能夠自動生成小學四則運算題目與解決題目的命令行 「軟件」呢。他把老師的話翻譯一下,就造成了這個軟件的需求:程序員
n
道加減乘除(分別使用符號+-*/
來表示)練習題,每一個數字在 0
和 100
之間,運算符在 2
個 到 3
個之間。3÷5+2=2.6
這樣的算式。n
道練習題及其對應的正確答案輸出到一個文件 subject.txt
中。當程序接收的參數爲4時,如下爲一個輸出文件示例。github
13+17-1=29 11*15-5=160 3+10+4-16=1 15÷5+3-2=4
此次阿超選擇使用他最拿手的 C++
語言來完成這樣的需求,工欲善其事必先利其器,第一步就須要先安裝一個好用的 IDE ,在這裏咱們推薦使用 Visual Studio 2017
。算法
Visual Studio 2017 有着宇宙最強 IDE 的美稱,它對 C++ 的支持也很好,在本教程中,爲簡化學員的開發難度,咱們選擇使用 VS2017 社區版(社區版(Community)指的是可免費提供給單個開發人員,給予初學者及大部分程序員支持,能夠無任何經濟負擔、合法地使用的版本。)編程
下面提供三種安裝方法:瀏覽器
下載迅雷,輸入如下ed2k連接:服務器
ed2k://|file|mu_visual_studio_community_2017_version_15.3_x86_x64_11100062.exe|1069960|5984B3CD547F9F213DE21EFE5887F08D|/
百度網盤:連接: https://pan.baidu.com/s/1jJXyRMA 密碼: ub6c
下載的文件只是一個引導安裝程序,下載完成後,雙擊運行,若是出現下面的 Visual Studio 提示:
則須要首先自行安裝版本較高的 .Net Framework
( .NET Framework 4.6 能夠在這裏下載到)若是沒有出現該提示,請忽略。
在點擊開 exe
文件後,一路繼續,能夠看到以下的選擇界面。因爲咱們只須要 C++
庫,因此只須要勾選 【使用 C++
的桌面開發】便可。因爲 VS
自己體積較大,推薦修改存儲位置,將其安裝在非系統盤目錄。
若是順利的話,過一大段時間 VS2017 就會下載好相應文件,此時會提示要求重啓,此時按照指示重啓便可。
安裝成功後,首次使用 VS 2017 還須要對其進行簡單的配置,包括開發環境的主題風格。若是要求登陸的話,可使用你的outlook帳號登陸,或者能夠選擇忽略。
這裏開發設置選擇 C++便可,主題推薦深色主題。
阿超的項目放在了當下最流行的源代碼管理平臺 Github
上,倉庫地址。那麼,咱們如何在阿超項目的基礎上進行開發呢?
成功登陸後,輸入阿超倉庫的網址 https://github.com/ChildishChange/Calculator ,點擊右上角的 Fork
,將阿超的四則運算庫拷貝到本身的同名倉庫中,以下圖所示:
拷貝成功後,能夠看到本身已經擁有了一個同名倉庫。這裏咱們登陸的是 buaase 的帳號:
在本身的電腦上安裝 Git 軟件,Git 的安裝教程在這裏。在本身拷貝項目的主頁的綠色按鈕處能夠找到一個可克隆的項目地址,下面是一個示例:
在 個人電腦 中任意找一個目錄,打開 Git 命令行軟件(Windows上可在空白處右鍵打開 Git Bash ),輸入 git clone <clone url>
,其中 <clone url>
即咱們剛剛複製的項目地址。一個動W態演示圖以下所示(這裏 https://github.com/buaase/Calculator.git 就是咱們 Fork 後倉庫的地址):
在完成上述操做後,可在當前目錄下看到一個與倉庫同名的文件夾Calculator
,這就是克隆到本地的項目。注意,默認克隆的分支是 java,請使用 git checkout cplusplus 命令切換到 C++
項目。 進入項目文件夾,新建一個文件夾,重命名爲你的 Github
帳號名。
以 Github 帳號命名的文件夾做爲項目目錄,打開 VS2017,點擊左上角的 文件
-> 新建
-> 項目
,以下圖所示,選擇 Visual C++
中的 控制檯應用程序
。注意更改 位置
參數到剛剛新建的文件夾所在的路徑。好比個人帳戶名爲 buaase
,剛剛新建的文件夾路徑爲D:\Calculator\buaase
,解決方案的名稱也能夠是 Calculator
,自定義便可。
新建項目後會出現一些默認的 stdafx.cpp
與 .h
爲後綴的頭文件。找到與解決方案同名的 cpp
文件,好比解決方案爲 ConsoleApplication1
,那麼會有一個名叫 ConsoleApplication1.cpp
的文件。將 src
目錄下 Calculator.cpp
文件的內容拷貝到該文件中。右鍵點擊 頭文件
,新建一個頭文件,修更名稱爲 Calculator.h
,並將 src
目錄下 Calculator.h
文件的內容拷貝到新的頭文件中。此時,右鍵點擊解決方案,選擇 編譯解決方案
,成功後點擊 本地Windows調試器
便可運行,示意圖以下:
接下來接連使用 git add,git commit -m "Message"
(Message是你要寫的內容)便可利用 Git 記錄下全部的改動。若是是初次使用 Git,請在使用上述兩條命令前使用以下兩條命令配置本身的我的郵箱與 Commit 時的用戶名,這裏的郵箱和用戶名最好與 Github 帳號保持一致。
$ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com
下面是一些常見的Git操做,可留做備忘
$ git clone [url] 下載一個項目以及它全部的版本歷史 $ git add [file] 將文件進行快照處理用於版本控制 $ git commit -m"[descriptive message]" 將文件快照永久地記錄在版本歷史中 $ git push 上傳當前本地分支commit到GitHub上 $ git pull 下載服務器上最新的本部併合並更改到本地 $ git reset [commit hash] 撤銷全部[commit hash]後的的commit,在本地保存更改 $ git log 列出當前分支的版本歷史
對於Github平臺有疑問的,能夠在 http://github.com/help 找到解決方案。
要想在 VS2017 裏對 C++ 項目進行單元測試,首先要新建一個測試項目。右鍵單擊解決方案,能夠添加一個新建項目,在類型裏選擇 單元測試
,咱們這裏新建了一個名爲 CalculatorUnitTest
的單元測試項目。
在項目建立成功後,爲單元測試項目 CalculatorUnitTest
增長對原項目的引用,以實現調用原項目函數接口的功能。
光設置引用還不夠,接下來讓咱們手動設置一下測試項目的附加依賴項。選中單元測試項目,右鍵點擊選擇 屬性
在打開的左側菜單欄中選擇 配置屬性
-> 連接器
-> 輸入
,在 附加依賴項
的下拉選擇框中選擇 <編輯...>
,將被測試項目產生的全部 obj 文件路徑(注意:並不是每次單元測試都固定寫 Calculator.obj ,它決定於 C++源文件的名字)寫到附加依賴項中,以下圖所示:
這兩個obj 文件能夠在以下圖文件夾(Project/Debug/)中找到:
在完成單元測試的項目配置後,下面咱們就能夠開始寫單元測試代碼了。首先看向新建立的單元測試項目,裏面應該會有一個默認的 unittest1.cpp
文件,打開該文件,應該是長這樣的:
#include "stdafx.h" #include "CppUnitTest.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace CalculatorUnitTest { TEST_CLASS(UnitTest1) { public: TEST_METHOD(TestMethod1) { //請輸入測試代碼 } }; }
爲了能順利引用剛剛寫好的接口,咱們須要引入Calculator工程的接口定義頭文件,即 calculator.h。在頭文件部分插入一行
#include "../Calculator/calculator.h"
而後咱們就能夠順利引用相關接口了。經過閱讀方法 Solve 的註釋與代碼,咱們不難發現,它的參數是字符串形式的四則運算表達式,返回的應該是該表達式的答案。如今咱們來填充第一個測試用例,TEST_METHOD 其實就是一個宏,後面跟着的 TestMethod1 纔是單元測試真正的名字。在該方法中插入以下代碼塊:
Calculator* calc = new Calculator(); string ret = calc->Solve("11+22"); Assert::AreEqual(ret, (string)"11+22=33");
這裏咱們用到了 Assert(斷言)。編寫單元測試時,咱們老是會作出一些假設,好比咱們指望一個函數在接受預期的輸入後就返回預期的輸出,斷言就是用於在代碼中捕捉這些假設。通常來講,單元測試中都會有斷言的存在,沒有斷言存在的單元測試實際上是「假大空」的,沒有任何對程序輸入輸出的假設約束。
下面咱們來運行一下這個單元測試,看 Solve 函數是否符合咱們的指望。找到菜單欄中的 測試
,運行全部測試便可,以下圖所示
在單元測試運行完畢後,VS 的左側會彈出一個測試結果窗口。綠色表明經過,紅色表明失敗。從本次的結果來看,咱們經過了這個單元測試。
那麼也就是說,當 solve 函數的輸入爲 "11+22"
時,其實際的輸出就是 "11+22=33"
,與預期現象溫和。固然,咱們這裏只是經過了一個簡單的測試用例,不能說這個函數就是必定正確的。因此咱們須要加一些單元測試,以驗證在怎樣的狀況下這個函數可能會出錯,如今請你幫助阿超補充一些針對 solve 方法的單元測試用例吧。
上面咱們學習瞭如何使用 IDE 進行單元測試,也測試出了 solve 方法的確有些問題。那麼該如何定位問題所在呢?這就要用到 IDE 的調試功能了。下面咱們就來介紹一下 Visual Studio 的調試方法。
斷點
調試程序首先要會設置斷點和單步運行。在 VS 中設置斷點很是簡單,在要設置斷點的行號旁用鼠標單擊一下就好了(注意要點到與右側編輯器顏色明顯不一樣的區域),以下圖所示,咱們在第 31 行設了個斷點:
單步運行
在設置好斷點後,咱們就能夠啓動 Debug 模式。咱們這裏因爲默認啓動項目是 Calculator ,因此直接點擊以下所示的 本地 Windows 調試器
按鈕便可開始調試。
若是一個解決方案中有多個Cpp項目,要首先指定啓動項目。
啓動調試後,這時能夠看到程序已經運行到剛剛打的斷點處前。下方的自動窗口能夠看到各個變量的值。
與其餘 IDE 相似,咱們也能夠經過手動設置監視一些感興趣的變量。點擊選項卡到 監視 1
中,按照下圖所示方式添加監視,可在界面中只顯示監控變量的值。
此時咱們的第31行代碼並無執行,下面咱們利用單步運行的方法執行該語句。單步運行有兩種:Step Into(逐語句,快捷捷F11) 和 Step Over(逐過程,快捷捷F10),分別對應這兩個圖標。(這些圖標都在剛纔啓動本地調試器按鈕的旁邊)
這兩種單步運行功能在運行語句時沒有區別,在執行方法調用語句時,Step Into 會跳入方法實現,Step Over 會直接執行完方法,實際使用中咱們優先使用 Step Over,只有方法執行出錯了,說明程序問題在被調用方法中,這時再回來經過 Step Into 進入方法進行調試。咱們單擊一下 Step Over 圖標(或 F10 ),程序停在了第 33 行(向右的小黃箭頭指示目前執行到第幾行,也可使用這個圖標表明的按鈕 )
這時咱們能夠看到執行了 31 行代碼後 formulaChar 目前的值。
條件斷點
有些狀況下咱們只但願斷點在某些條件下才成立,該如何作呢?其實很是簡單,右鍵單擊紅色的斷點符號,便可彈出條件選項。
在這裏咱們能夠輸入 Condition,設定爲只有某些前置變量的值知足條件時咱們纔會觸發斷點,幫助咱們高效率測試。好比咱們這裏設定 Condition 爲 j == 0
:
從下圖中咱們能夠看到當斷點生效時,j 的值爲 0。
咱們如今的程序中暗藏了兩個BUG,一個是不符合題目的需求,另外一個是實現上有一個小問題。如今請你利用剛學習到的單元測試與 Debug 的相關知識,找出程序的 Bug 吧!
單元測試不只僅用來保證當前代碼的正確性,更重要的是用來保證代碼修復、改進或重構以後的正確性。也就是說,在每次修改完 Bug 以後,咱們其實都須要運行一遍來看看是否是知足以前全部的單元測試樣例。因此,在每次由於現有的 failed test 而修復原有代碼後,最好都所有運行一遍單元測試,保證之前 passed test 仍然是能夠經過的。
一樣地,Git 的使用也是講究勤提交,提交的粒度最好是細到每一個小功能的完成。一個小功能能夠是一處小 Bug 的修復,也能夠是一個簡單函數的實現。因此,在咱們本次的編程訓練任務中,Git 至少會提交 2 次或以上。
爲了測試並改進程序生成四則運算算式的效率,咱們須要使用效能分析工具。效能分析工具並不能幫助咱們直接改進算法的效率,但它能夠幫咱們分析找到代碼中執行效率最差,也就是所謂 效能瓶頸
的部分。這以後咱們就能夠把精力花費在改進瓶頸上,從而高效快速地提高程序性能。
Visual Studio 內置了很是棒的效能工具,學名叫作 性能探查器
。點擊 IDE 頂部菜單欄中的 分析
,便可看到 性能探查器
。
咱們這裏關注在程序的執行效率方面,因此咱們選擇測試 CPU 使用率
便可。若是想探查內存泄露問題,也能夠選擇使用其餘選項。
先別急着開始探查。咱們的代碼目前只產生 1 個四則運算算式,不存在性能問題。咱們首先來給代碼多加幾百萬個循環,讓它運行 足夠長
時間,才能準確測出代碼的效能問題。增長循環體後的 main 函數體以下所示
int main() { for (int i = 0; i < 10000000; i++) { Calculator* calc = new Calculator(); string question = calc->MakeFormula(); cout << question << endl; string ret = calc->Solve("11+22"); cout << ret << endl; } }
好了,如今讓咱們開始效能分析。即便程序沒有執行完成,效能分析也是能夠強行結束的。讓程序跑幾十秒以後,就能夠結束。點擊效能分析工具界面左上角的 中止收集
便可中止收集數據。
下圖就是一份完整的效能分析報告。
從圖中咱們能夠看到,Solve 方法在總 CPU 耗時中佔了約 30% 左右,但若是想得到更詳細的信息(好比具體到哪一行佔了這麼久,詳細報告閱讀起來更易懂),咱們須要點擊上圖中的 建立詳細的報告...
,建立完成後會自動打開一個後綴爲 .vspx
的文件,以下圖所示:
咱們點進 Calculator::Solve 看看,能夠看到很是清晰的每行代碼佔用 CPU 的時間比例,以下圖左側所示。而後咱們就能夠着手改進代碼的效率,好比結合場景用更高效的數據結構,優化一些沒有用的代碼等等。
在完成 Debug
與 單元測試
以後,咱們如今來學習一下如何提交代碼到 Github 上,並利用 Github 進行團隊協做。以前咱們已經介紹過了 git add
與 git commit
命令,但這兩條命令只會對本地的倉庫進行修改,也就是說以前的全部操做都是離線的。咱們要想讓 Github 上也跟蹤到最新的改變,就須要使用 git push
命令。
在使用該命令前,請確保全部本地的改動都已經 add
並 commit
了。能夠用 git status
來檢查:
出現如圖所示的 nothing to commit
即說明已經能夠 push 了。使用 push 命令後,會彈出一個窗口要求登陸 Github,此時輸入 Github 的 用戶名或郵箱
與 密碼
便可成功 push。
成功的提示以下所示,其中 master 部分應該是 java / cplusplus。
在完成 push 後,咱們就能夠開始向源倉庫(即阿超的倉庫)發起 Pull Request(簡稱 PR ,指發起請求給倉庫貢獻代碼)。打開你 Fork 後的項目主頁,如圖所示,點擊按鈕 New pull request
若是你按照教程的節奏一步步走下來了,那麼在點擊 New Pull Request後,應該出現以下所示界面。若是不是,請聯繫羣內的助教/老師,或者在本博客下留言補充錯誤截圖。
此時點擊 Create pull request
便可發起請求。等待倉庫主人阿超經過審覈後,你的代碼就能夠成功合併進阿超的倉庫。至此就完成了整個教程,恭喜!