C++ 如果这个if-else-if程序更简单,代码冗余更少(C+;+;),您将如何着手使它变得更简单?

C++ 如果这个if-else-if程序更简单,代码冗余更少(C+;+;),您将如何着手使它变得更简单?,c++,C++,编写一个程序,询问三名跑步者的姓名以及他们各自花费的时间 他们中的一员完成了一场比赛。程序应该显示谁是第一名、第二名和第三名 第三名。 输入验证:只接受时间的正数 我的代码 #include <iostream> #include <string> using namespace std; int main() { string runner1, runner2, runner3; int time1, time2, time3; cout &

编写一个程序,询问三名跑步者的姓名以及他们各自花费的时间 他们中的一员完成了一场比赛。程序应该显示谁是第一名、第二名和第三名 第三名。 输入验证:只接受时间的正数

我的代码

#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;
}
#包括
#包括
使用名称空间std;
int main()
{
字符串runner1、runner2、runner3;
int time1,time2,time3;
cout runner1>>runner2>>runner3;

cout让跑步者按时间在数组中排序,迭代跑步者数组并输出(name+i+“place”)

我认为一个链表会非常好,但是如果跑步者不经常更换位置或者跑步者不多,它可能会输给一个原始数组

“将绘图代码与游戏逻辑分离”

你的绘图代码是cout calls。你的游戏逻辑是确定每个跑步者的位置。然后你根据你计算的状态绘图

您的方法是最直接和最快的方式来解决打印出亚军位置的问题

#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;
}
#包括“stdafx.h”
#包括
#包括
使用名称空间std;
结构转轮{
整数时间;
int-id;

It运算符

看起来你开始了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);
    }
}
预期产出:

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
我可能对理查德回答的复杂性感到惊讶

当然,他在组织代码方面提出了很好的观点

我最后发布了自己的评论和一个“更简单”的示例,因为我认为程序最重要的一面是功能性

在这种情况下,

  • 您需要错误处理(用户可能输入非法值)
  • 您需要检查输入(用户可以输入3个以上的名称,也可以输入相同的名称等)
  • 您需要正确地报告排名。如果两名跑步者同时跑步,您将按“任意”顺序对他们进行排名。您将希望将他们正确地评定为共享位置
我的代码

  • 与3名跑步者的联系较少(仅在阅读这三个名字时,因为这是示例所要求的)
  • 举例说明如何使用
    部分排序
    仅对前3个位置进行排序,这已不再可能,因为显示功能处理未知大小的集合,共享位置意味着可能有3个以上的排名跑步者

#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);
}
#包括
#包括
#包括
#包括
#包括
无效静态内联忽略\u行()的\u剩余\u{
std::cin.ignore(std::numeric_limits::max(),'\n');
}
结构运行程序{
std::字符串名;
整数时间=0;
布尔运算符name1>>name2>>name3&&unique()
打破

std::你展示的程序能工作吗?它能生成吗?它能运行吗?它能产生预期的结果吗?那么你想要的是代码审查,你应该在这里发布,而不是在这里发布。@OP我会从改进代码布局开始,这样它会读得更好。因为问题是按它的方式写的,对我来说听起来像是家庭作业。所以这里是一些提示:1.每个运行程序都有一个对应的时间,因此将它们捆绑到一个类或结构中是有意义的。2.通过比较它们的运行时间,可以对此类成员进行排序。3.通过将它们存储在STL容器中进行排序,并通过
std::Sort
(或类似方式)对它们进行排序4.通过遍历已排序的容器打印出谁有一个。如果您有问题,请尝试一下,然后返回这里。因此,没有代码编写服务。我投票关闭这个问题,因为它属于codereview.stackexchange.com。虽然这不是最好的问题,但它下面隐藏着一个好问题他的。这里的基本问题是有3!=6个分支,这显然不可伸缩。有趣的是,
sort\u container
实现的注释比代码多,后面返回,完美转发等等。我本来想在这个评论中发布一个竞争性的示例,但发现我添加了一些有用的东西,所以升级到一个答案。。。@两个人的想法总比一个人好。去做吧。我希望这里有像你这样的人来帮我写这个rpc库,而不是一个人写…谢谢你。我的答案是:)+1“从游戏逻辑中分离绘图”.这是一个很好的建议。我刚刚意识到我的
部分排序
在这里是不正确的,以防列表更大并且有许多共享位置(您可能需要打印3个以上的名称,并且它们都应该按顺序排列).已修复。您还记得我同意向您展示我为asio制作对象的方法吗?这里有一个快速演示:git@github.com:madmongo1/goblins.gitI do!我差点错过了这条评论。很快就从中克隆出来:)我认为值得注意的是,尽管Richard的答案显然更长,但并不十分复杂。乍一看,它看起来像e其McCabe圈复杂度(仅举一个例子)是2。虽然可以实现,但大多数人发现结果……最多有点奇怪。@JerryCoffin这都是相对的,而且,相对而言,对学生来说是主观的。但是,是的,我的答案并没有降低复杂性。但它确实提高了输入验证和逻辑:)这是我的观点。我本来打算展示一个精简版,但是然后我意识到这个问题被低估了(一如既往)
#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);
}