2017-07-07 57 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