2017-07-07 58 views
-4

編寫一個程序,詢問三位跑步者的名字以及每位參加比賽的每個 所花費的時間。該計劃應顯示第一名,第二名和第三名。 輸入驗證:只接受時間的正數。如果程序更簡單,代碼冗餘更少(C++),你會怎麼做呢?

我的代碼

#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string runner1, runner2, runner3; 
    int time1, time2, time3; 

    cout << "Please enter the names of three runners" << endl; 
    cin >> runner1 >> runner2 >> runner3; 
    cout << "How many minutes did it take " << runner1 << " to finish the race?" << endl; 
    cin >> time1; 
    cout << "How many minutes did it take " << runner2 << " to finish the race?" << endl; 
    cin >> time2; 
    cout << "How many minutes did it take " << runner3 << " to finish the race?" << endl; 
    cin >> time3; 

    if (time1 < time2 && time1 < time3) 
    { 
     cout << runner1 << " is 1st place!" << endl; 

     if (time2 < time3) 
     { 
      cout << runner2 << " is 2nd place!" << endl; 
      cout << runner3 << " is 3rd place!" << endl; 
     } 
     else if (time3 < time2) 
     { 
      cout << runner3 << " is 2nd place!" << endl; 
      cout << runner2 << " is 3rd place!" << endl; 
     } 
    } 
    else if (time2 < time1 && time2 < time3) 
    { 
     cout << runner2 << " is 1st place!" << endl; 

     if (time1 < time3) 
     { 
      cout << runner1 << " is 2nd place!" << endl; 
      cout << runner3 << " is 3rd place!" << endl; 
     } 
     else if (time3 < time1) 
     { 
      cout << runner3 << " is 2nd place!" << endl; 
      cout << runner2 << " is 3rd place!" << endl; 
     } 
    } 
    else if (time3 < time2 && time3 < time1) 
    { 
     cout << runner3 << " is 1st Place!" << endl; 

     if (time2 < time1) 
     { 
      cout << runner2 << " is 2nd place!" << endl; 
      cout << runner1 << " is 3rd place!" << endl; 
     } 
     else if (time1 < time2) 
     { 
      cout << runner1 << " is 2nd place!" << endl; 
      cout << runner2 << " is 3rd place!" << endl; 
     } 
    } 
    else 
    { 
     cout << "Error! Please restart the program and input a positive value" << endl; 
    } 
    return 0; 
} 
+6

您展示該方案,不是* *工作?它是否構建?它運行嗎?它會產生預期的結果嗎?那麼你想要的是*代碼審查*,你應該在http://codereview.stackexchange.com/而不是在這裏發佈。 –

+0

@OP我會從改進代碼佈局開始,所以它會更好。 –

+0

由於問題是以它的方式編寫的,所以它聽起來像是我的作業。所以這裏只是一些提示:1。每個跑步者都有相應的時間,所以將它們綁定到一個類或結構中是有意義的。來自「簡明英漢詞典」這個班級的成員可以通過比較他們的運行時間進行排序3.通過將它們存儲在STL容器中對它們進行排序,並通過'std :: sort'(或類似的東西)對它們進行排序。4.通過迭代排序後的容器來打印出誰有。試試看,如果你有問題,請回到這裏。 SO不是沒有代碼寫入服務。 – muXXmit2X

回答

2

請用自己的時間數組排序亞軍,遍歷選手陣列和輸出(姓名+ I +「地方」)

我想一個鏈接列表會非常好,但如果跑步者不經常更換位置或跑步者不多,則可能會失去原始數組。

你的繪圖代碼是COUT調用「從遊戲邏輯中分離出來的繪製代碼」。你的遊戲邏輯是確定每個參賽者的位置,然後根據你計算出的狀態進行抽籤。

你的方式是解決跑步者位置打印問題的最直接最快速的方法。

#include "stdafx.h" 
#include <iostream> 
#include <algorithm> 

using namespace std; 

struct Runner { 
    int time; 
    int id; 

    int operator<(Runner runner) { 
     return time < runner.time; 
    } 
}; 

char* pickSuffix(int place) { 
    switch (place) { 
    case 1: 
     return "st"; 
    case 2: 
     return "nd"; 
    case 3: 
     return "rd"; 
    default: 
     return "th"; 
    } 
} 

int main() { 

    //make my runners, read in my times, runner 1 first 
    Runner runners[3]; 
    for (int i = 0; i < 3; i++) { 
     cout << "Enter runner " << i+1 << "'s time: "; 
     cin >> runners[i].time; 
     cout << endl; 
     runners[i].id = i+1; //setup their id, used like a name 
    } 

    //figure out what place each runner came in 
    //must overload operator< for object to use sort 
    sort(runners, &runners[2]); 

    //the position of the runner in the array is the place they came in 
    //since it is sorted by their times 
    for (int i = 0; i < 3; i++) { 
     cout << "Runner #" << runners[i].id << " came in " << i+1 << pickSuffix(i+1) << " place!" << endl; 
     cout << runners[i].time << endl; 
    } 

    system("pause"); 

    return 0; 
} 

這裏是我描述的方式編寫的代碼示例。我認爲,對於大多數目的,你不想排序數組中的跑步者,你可以添加一個成員變量place,並且只存儲他們的計算位置。

+1

+1「遊戲邏輯分離繪圖」。這是可靠的建議。 – sehe

2

看起來你正在開始你的C++程序設計之旅。歡迎。

我會尋求下把問題分解成它的組成部分,這樣我們就可以結束了表達解決方案的意圖在一個易於理解的形式:

int solve(std::istream& is, std::ostream& os) { 

    Runners runners; 
    collect_runners(os, is, runners); 
    sort_by_time(runners); 
    print_first_3(os, runners); 

    return 0; 
} 

請注意,我有不將解決方案與任何特定輸入或輸出流綁定。這樣我可以在以後輕鬆測試。

既然我們已經清楚地表達瞭解決方案的意圖,我們填寫空白處(我已經使用了各種'高級'技術,我希望你會發現有意思的和有趣的)。

我已經使用C++ 11。

評論內嵌。

#include <string> 
#include <vector> 
#include <algorithm> 
#include <type_traits> 
#include <iostream> 
#include <sstream> 

/** The concept of coupling a runner's name with the time it took to run the race 
* 
*/ 
struct Runner { 
    std::string name; 
    int time; 
}; 

/** A collection of runners and their corresponding time. 
* 
*/ 
using Runners = std::vector<Runner>; 

/** Sort a container with a predicate. Return a reference to the container 
* 
* @tparam Container 
* @tparam Pred 
* @param c 
* @param pred 
* @return 
*/ 
template<class Container, class Pred> 
auto sort_container(Container &c, Pred &&pred) -> Container & { 
    std::sort(std::begin(c), std::end(c), std::forward<Pred>(pred)); 
    return c; 
} 

/** Sort a Runners array by ascending time 
* 
* @param vec 
* @return 
* */ 
Runners &sort_by_time(Runners &vec) { 
    auto by_increasing_time = [](Runner const& l, Runner const& r) { 
     return l.time < r.time; 
    }; 

    sort_container(vec, by_increasing_time); 
    return vec; 
} 

/** Print the first 3 runnes in an array of runners to an ostream 
* 
* @param os 
* @param vec 
*/ 
void print_first_3(std::ostream& os, Runners const &vec) { 
    static const char *nth[] = { 
      "first", 
      "second", 
      "third" 
    }; 

    auto limit = std::extent<decltype(nth)>::value; 
    limit = std::min(limit, vec.size()); 
    for (std::size_t i = 0; i < limit; ++i) { 
     auto const &runner = vec[i]; 
     os << runner.name << " is in " << nth[i] << " place with a time of " << runner.time << "\n"; 
    } 
} 

/** Ask a question on the console if the answer is to come from stdin 
* 
* @param is 
* @param q 
*/ 
template<class Target> 
void question(std::istream& is, Target& target, std::string const& q) 
{ 
    if (std::addressof(is) == static_cast<std::istream*>(std::addressof(std::cin))) 
    { 
     std::cout << q << std::endl; 
    } 
    is >> target; 
} 

/** Build a runner using the supplied input and output streams 
* 
* @param os 
* @param is 
* @return 
*/ 
Runner collect_runner(std::ostream& os, std::istream& is) 
{ 
    Runner runner {}; 
    question(is, runner.name, "runner's name?"); 
    question(is, runner.time, "runner's time?"); 
    return runner; 
} 

/** Populate a Runners array using input and output streams 
* 
* @param os 
* @param is 
* @param runners 
* @return 
*/ 
Runners& collect_runners(std::ostream& os, std::istream& is, Runners& runners) 
{ 
    int nrunners = 0; 
    question(is, nrunners, "how many runners?"); 

    while (nrunners-- > 0) { 
     runners.push_back(collect_runner(os, is)); 
    } 
    return runners; 
} 

/** Solve the problem at hand 
* 
* @param is 
* @param os 
* @return 
*/ 
int solve(std::istream& is, std::ostream& os) { 

    Runners runners; 
    collect_runners(os, is, runners); 
    sort_by_time(runners); 
    print_first_3(os, runners); 

    return 0; 
} 


/** Solve the problem using either std input/output or test input 
* 
* @param argc 
* @param argv 
* @note If argc == 2 and argv[1] == "test" then run solve using test input. 
*  We do this so that we can test our code without playing around with external files or 
*  the console each time we want to test it 
* @return 
*/ 
int main(int argc, char **argv) { 
    if (argc == 2 && argv[1] == std::string("test")) { 
     static const char test_data[] = R"__(
5 
bob 40 
bill 20 
sue 30 
peter 25 
zool 29 
)__"; 
     std::istringstream test_stream{test_data}; 

     return solve(test_stream, std::cout); 

    } else { 

     return solve(std::cin, std::cout); 
    } 
} 

測試與控制檯上:

$ ./a.out test 

預期輸出:

bill is in first place with a time of 20 
peter is in second place with a time of 25 
zool is in third place with a time of 29 
+0

有趣的是,'sort_container'實現比代碼更多的評論,尾隨返回,完美轉發等。我將在此評論中發佈競爭示例,但發現我添加了一些有用的東西,因此升級到答案... – sehe

+0

@兩個人的頭腦比一個人好。去吧。我希望我有一個像你這樣的人來幫助我寫這個rpc庫,而不必一個人去做...... –

+0

謝謝。我的答案是:) – sehe

2

我可以在理查德的答案的複雜性有laughed a little

當然,他在組織代碼方面表現出色。

我最終發佈了自己的評論和一個「更簡單」的示例,因爲我認爲程序最重要的一面是功能

在這種情況下,

  • 你需要錯誤處理(用戶可以輸入非法值)
  • 你需要檢查輸入(用戶可以輸入3名以上的名字,可以輸入相同的名稱等)
  • 您需要正確報告排名。如果兩名選手同時參加比賽,您將按照「任意」順序排名。您需要將它們正確評分爲共享位置。

我的代碼

  • 較少依賴於3個亞軍(僅讀出三個名字的時候,因爲這是需要什麼樣)
  • 例證使用 partial_sort得到公正的前3排序的位置 由於顯示功能處理未知大小的集合,並且共享位置意味着可能有超過3個排名的跑步者,因此不再可能。

Live On Coliru

#include <iostream> 
#include <algorithm> 
#include <string> 
#include <vector> 
#include <set> 

void static inline ignore_rest_of_line() { 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
} 

struct Runner { 
    std::string name; 
    int time = 0; 

    bool operator<(Runner const& o) const { return time < o.time; } 
}; 

std::vector<Runner> read_three() { 
    std::string name1, name2, name3; 
    auto unique = [&] { return std::set<std::string>{ name1, name2, name3 }.size() == 3; }; 

    std::cout << "Please enter the names of three runners\n"; 

    while (std::cin) { 
     if (std::cin >> name1 >> name2 >> name3 && unique()) 
      break; 
     std::cout << "Enter 3 unique names\n"; 
     ignore_rest_of_line(); 
    } 

    ignore_rest_of_line(); 
    return { { name1, 0 }, { name2, 0 }, { name3, 0 } }; 
} 

void read_time(Runner& runner) { 
    while (std::cin) { 
     std::cout << "How many minutes did it take " << runner.name << " to finish the race?\n"; 
     if ((std::cin >> runner.time) && runner.time > 0) 
      break; 
     std::cout << "Enter a valid time\n"; 
     std::cin.clear(); 
     ignore_rest_of_line(); 
    } 

    ignore_rest_of_line(); 
} 

template <typename List> 
void display_winners(List runners) { 
    std::sort(std::begin(runners), std::end(runners)); 

    std::string ranks[] = { "1st", "2nd", "3rd" }; 

    auto prev = runners.begin(); 
    auto rank = std::begin(ranks); 

    for (auto& runner : runners) { 
     if (runner.time != prev->time) 
      ++rank; 
     if (rank == std::end(ranks)) 
      break; 
     std::cout << runner.name << " is " << *rank << " place\n"; 
    } 
} 

int main() { 
    std::cin.exceptions(std::ios::eofbit); 
    auto runners = read_three(); 

    for (auto& runner : runners) { 
     read_time(runner); 
    } 

    display_winners(runners); 
} 

樣品運行顯示

請輸入三個亞軍
A A B
輸入3個獨特的名字名210 a b c
需要多少分鐘才​​能完成比賽?

需要多少分鐘才​​能完成比賽?
無效時間7
輸入有效時間
需要多少分鐘才​​能完成比賽?

需要多少分鐘才​​能完成比賽?

c是第一名
b爲第一名
一個是第二名

+0

我剛剛意識到我的'partial_sort'在這裏是不正確的,因爲列表較大並且有很多共享位置(您可能需要打印多於3個名稱,並且它們都應該按順序排列)。固定。 – sehe

+0

你記得我同意我會告訴你我爲asio做對象的方式嗎?快速演示在這裏:[email protected]:madmongo1/goblins.git –

+0

我做到了!我幾乎錯過了這個評論。快速克隆地獄:) – sehe