2013-04-27 239 views
3

首先做一簡單介紹:2 while循環VS如果else語句在1 while循環

我是一個新手C++程序員(我是新來的節目)寫了一點乘法表練習計劃。這個項目起初是一個小程序,教給自己編程的基礎知識,隨着我越來越多地學習編程,我不斷添加新的功能。起初它只是基本的要求輸入,循環和if-else語句。但現在它使用的載體,讀取和寫入文件,創建一個目錄等

你可以看到這裏的代碼:Project on Bitbucket

我的程序現在將有兩種模式:練習一次乘法表的用戶可以選擇自己或練習所有混合的乘法表。現在兩種模式在內部都有很大不同。我開發了混合模式作爲一個單獨的程序,這樣可以簡化開發過程,我可以專注於編寫代碼本身,而不是打擾如何將它集成到現有代碼中。

低於當前獨立混合模式程序的代碼:

#include <iostream> 
#include <sstream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <time.h> 

using namespace std; 
using std::string; 

int newquestion(vector<int> remaining_multiplication_tables, vector<int> multiplication_tables, int table_selecter){ 
    cout << remaining_multiplication_tables[table_selecter] << " * " << multiplication_tables[remaining_multiplication_tables[table_selecter]-1]<< " =" << "\n"; 
    return remaining_multiplication_tables[table_selecter] * multiplication_tables[remaining_multiplication_tables[table_selecter]-1]; 
} 

int main(){ 
    int usersanswer_int; 
    int cpu_answer; 
    int table_selecter; 
    string usersanswer; 
    vector<int> remaining_multiplication_tables = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
    vector<int> multiplication_tables(10, 1);//fill vector with 10 elements that contain the value '1'. This vector will store the "progress" of each multiplication_table. 
    srand(time(0)); 

    table_selecter = rand() % remaining_multiplication_tables.size(); 
    cpu_answer = newquestion(remaining_multiplication_tables, multiplication_tables, table_selecter); 
    while(remaining_multiplication_tables.size() != 0){ 
    getline(cin, usersanswer); 
    stringstream usersanswer_stream(usersanswer); 
    usersanswer_stream >> usersanswer_int; 
    if(usersanswer_int == cpu_answer){ 
     cout << "Your answer is correct! :)" << "\n"; 
     if(multiplication_tables[remaining_multiplication_tables[table_selecter]-1] == 10){ 
     remaining_multiplication_tables.erase(remaining_multiplication_tables.begin() + table_selecter); 
     } 
     else{ 
    multiplication_tables[remaining_multiplication_tables[table_selecter]-1] +=1; 
     } 
     if (remaining_multiplication_tables.size() != 0){ 
    table_selecter = rand() % remaining_multiplication_tables.size(); 
    cpu_answer = newquestion(remaining_multiplication_tables, multiplication_tables, table_selecter); 
     } 
    } 
    else{ 
     cout << "Unfortunately your answer isn't correct! :(" << "\n"; 
    } 
    } 
    return 0; 
} 

正如你可以看到newquestion功能的混合模式是完全不同的。 while循環還包括其他混合模式特定的代碼。

現在,如果我想將混合乘法表模式集成到現有的主程序中,我有兩個選擇: -I可以用if-else語句來處理while循環,以檢查每次循環運行時是否使用mode == 10(單乘法表模式)或模式== 100(混合乘法表模式)。還可以在newquestion()函數中放置一個if-else語句來檢查模式== 10或模式== 100 -I可以讓程序檢查啓動時用戶是選擇單乘法表還是混合乘法表模式並創建2 while循環和2個newquestion()函數。這看起來像這樣:

int newquestion_mixed(){ 
//newquestion function for mixed mode 
} 
int newquestion_single(){ 
//newquestion function for single mode 
} 

//initialization 
if mode == 10 
//create necessary variables for single mode 
while(){ 
    //single mode loop 
} 
else{ 
//create necessary variables for mixed mode 
while(){ 
    //mixed mode loop 
} 
} 

現在爲什麼我會打擾創建2個獨立的循環和函數?如果程序檢查每次循環運行時(每次向用戶提出新問題,例如:'5 * 3 ='),用戶選擇了哪種模式,那麼效率不是很低?我很擔心這個選項的表現。現在我聽到了你的想法:但是爲什麼你會因爲今天功能非常強大的處理器和大量的RAM而對這樣一個簡單的,非性能不重要的應用程序的性能感到困擾?那麼,正如我早些時候說的那樣,這個程序主要是教我自己一個很好的編碼風格和學習如何編程等。所以我想從一開始就教好自己的好習慣。

2 while while循環和函數選項更有效率將使用更少的CPU,但更多的空間幷包括重複的代碼。我不知道這是否是一種很好的風格。

所以基本上我問專家最好的風格/方式來處理這種事情。另外,如果你發現我的代碼/不好的風格有問題,請告訴我,我非常樂於反饋,因爲我仍然是一名新手。 ;)

回答

5

首先,編程的一個基本規則是「不要過早地優化代碼」 - 也就是說,在代碼正常工作之前,不要少擺弄一些細節,並編寫代碼儘可能清楚地表達你想做的事情。這是很好的編碼風格。爲了瞭解「哪個更快」的細節(在花費大部分時間等待用戶輸入一些數字的循環中)並不是很好的編碼風格。

正確運行後,分析代碼花費時間(假設性能是首要考慮的主要因素)(例如使用Profiler工具)。一旦你找到了主要的「熱點」,然後嘗試在某種程度上做得更好 - 你如何去做,這很大程度上取決於特定的熱點代碼的功能。

至於哪一個執行得最好將高度依賴於代碼和編譯器的細節(以及哪個編譯器優化被選擇)。很有可能在while循環中運行if會運行得更慢,但現代編譯器相當聰明,而且我確實看到了編譯器將這樣的選擇提升出循環的情況,在條件不成立的情況下更改。有兩個while循環對於編譯器來說「變得更好」更困難,因爲它很可能不會看到你在兩個循環中都做了同樣的事情[因爲編譯器從分析樹的底部開始工作,它會首先優化while循環的內部,然後出去if-else,然後在每個循環內部發生什麼事情的時候,它會「失去蹤跡」。

哪一個更清楚,有一個if while循環,或者if有兩個while循環,這是另一個好問題。

當然,面向對象的解決方案是有兩個類 - 一個用於混合,另一個用於單個 - 只運行一個循環,調用基於if-else創建的對象的相關(虛擬)成員函數循環之前的語句。

+0

我再次閱讀了我的代碼,但如果我不想創建2個循環,那麼我將不得不創建比我想象的更多的if-else。我認爲我的代碼會變得更不可讀。所以我想我會把更多的代碼放入函數中,並創建2個循環。這將大大簡化事情。 – Superpelican 2013-04-27 13:43:35

+0

我最終創建了2個循環和2個獨立的函數。結果是比用if-else語句混淆了代碼更可讀。結果可以在這裏看到:https://bitbucket.org/Superpelican/clamshell_cli/src/c4dc989c1500f6a29981a966404c8cd92d4bc648/clamshell.cpp?at=default – Superpelican 2013-04-28 10:43:40

1

現代CPU分支預測器非常好,如果在循環期間條件不會改變,它可能會像每個分支中有兩個while循環一樣快。