简体   繁体   English

将结构传递给函数而不键入每个成员(C++ 无指针)

[英]Passing struct to function without typing every member (C++ no pointers)

So I think more of the inexperienced programmers will be roaming around with this question.所以我认为更多没有经验的程序员会带着这个问题四处游荡。 I can pass a struct to a function successfully like the snippet below:我可以像下面的代码片段一样成功地将结构传递给函数:

void printMonster(MonsterStats slime, MonsterStats spider, MonsterStats orc, MonsterStats ogre, MonsterStats dragon, int charLevel)

However you could imagine if the struct MonsterStats had 120 members which all needed to be passed to printMonster my code will become absolute spaghetti!但是你可以想象,如果 struct MonsterStats 有 120 个成员,所有成员都需要传递给 printMonster 我的代码将成为绝对的意大利面条!
So the question is, how can I pass this struct into my function without typing every single member into the function parameter?所以问题是,如何在不将每个成员都输入到函数参数中的情况下将这个结构传递到我的函数中?

For inquiries about how much I "should" know about c++ at this point, I have arrived at the learncpp.com chapter 4 comprehensive quiz .有关此时我“应该”了解多少 C++ 的问题,我已经到达了learncpp.com 第 4 章综合测验 I went a little out of scope of the assignment but I've done nothing I shouldn't be able to do by now.我有点超出了任务的范围,但我没有做任何我现在不应该做的事情。

full below (working but lengthy):完整如下(工作但冗长):

#include <iostream>


struct MonsterStats
{
    std::string type;
    std::string name;
    int health;
    int level;
};



void printMonster(MonsterStats slime, MonsterStats spider, MonsterStats orc, MonsterStats ogre, MonsterStats dragon, int charLevel)
{

    if(charLevel>=slime.level&&charLevel<spider.level)
        std::cout << "This " << slime.type << " is named " << slime.name << " and has " << slime.health << " health.\n";
    else if(charLevel>=spider.level&&charLevel<orc.level)
        std::cout << "This " << spider.type << " is named " << spider.name << " and has " << spider.health << " health.\n";
    else if(charLevel>=orc.level&&charLevel<ogre.level)
        std::cout << "This " << orc.type << " is named " << orc.name << " and has " << orc.health << " health.\n";
    else if(charLevel>=ogre.level&&charLevel<dragon.level)
        std::cout << "This " << ogre.type << " is named " << ogre.name << " and has " << ogre.health << " health.\n";
    else if(charLevel>=dragon.level)
        std::cout << "This " << dragon.type << " is named " << dragon.name << " and has " << dragon.health << " health.\n";
}

int main()
{
    using namespace std;

    MonsterStats ogre{"Ogre","Grumble",345, 16};            //Type, Name, Health, Level
    MonsterStats dragon{"Dragon","Spyro", 890, 21};         //Type, Name, Health, Level
    MonsterStats orc{"Orc","Rakanishu", 165, 11};           //Type, Name, Health, Level
    MonsterStats spider{"Giant Spider", "Arachnid", 80, 6}; //Type, Name, Health, Level
    MonsterStats slime{"Slime", "Blurp", 35, 1};            //Type, Name, Health, Level

    std::string getChoice="y";
    int charLevel;
    cout << "Please enter the level of your character to proceed to battle: ";
    cin >> charLevel;
    if(charLevel>0)
    {
        while(getChoice=="y")
        {
            printMonster(slime, spider, orc, ogre, dragon, charLevel);

            cout << "Do you want to fight the monster? (y/n)";
            cin >> getChoice;
            if(getChoice=="y")
            {
                cout << "You destroyed the monster and gained an experience level!\n\n";
                charLevel+=1;
            }
            else
                cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
        }
    }
    else
        cout << "Please create a character in order to play the game.";
    return 0;
}

Thanks in advance for the answers :)预先感谢您的回答:)

What you tend to call "members" (eg ogre , spider , etc...) are in fact instances of the MonsterStats structure.您倾向于称之为“成员”(例如ogrespider等...)实际上是MonsterStats结构的实例。 So variables.所以变数。

In C++, the "members" are the variables or functions that are in the structure (eg name , health , level , etc...).在 C++ 中,“成员”是结构中的变量或函数(例如namehealthlevel等...)。

Of course, using many instances like in your snippet, and retype a lot of time the same things would be a nightmare.当然,在您的代码片段中使用许多实例,并多次重新输入相同的内容将是一场噩梦。 Fortunately, in chapter 5 you'll see the loops and in chapter 6 you'll learn about arrays and vectors to handle a bundle of instances.幸运的是,在第 5 章中您将看到循环,而在第 6 章中您将学习处理一组实例的数组和向量。

This would look like:这看起来像:

#include <iostream>
#include <string>
#include <vector>

struct MonsterStats
{
   ...
};
...
int main()
{
    using namespace std;

    vector<MonsterStats> monsters { 
                            {"Ogre","Grumble",345, 16}, 
                            {"Dragon","Spyro", 890, 21}, 
                            {"Orc","Rakanishu", 165, 11}, 
                            {"Giant Spider", "Arachnid", 80, 6}, 
                            {"Slime", "Blurp", 35, 1} }; 

    ... 
    printMonster(monsters, charlevel); 
    ...
}

And you would then access to the i -th item with monsters[i] .然后您将使用monsters[i]访问第i个项目。

Once you start using a standard library container you could make use of the standard library to sort and search:一旦您开始使用标准库容器,您就可以使用标准库进行排序和搜索:

void printMonster(std::vector<MonsterStats>& monsters, int charLevel)
{
    MonsterStats mystats{"","",0,charLevel};
    auto comp = [](const auto& i, const auto& j) {return i.level <= j.level; };
    std::sort(monsters.begin(), monsters.end(), comp);
    auto monster_iterator = std::lower_bound(monsters.begin(), monsters.end(), mystats, comp);
    auto monster = *(monster_iterator - 1);
    std::cout << "You have level " << charLevel << '\n';
    std::cout << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
}

Here is the full program :这是完整的程序

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

struct MonsterStats
{
    std::string type;
    std::string name;
    int health;
    int level;
};

void printMonster(std::vector<MonsterStats>& monsters, int charLevel)
{
    MonsterStats mystats{"","",0,charLevel};
    auto comp = [](const auto& i, const auto& j) {return i.level <= j.level; };
    std::sort(monsters.begin(), monsters.end(), comp);
    auto monster_iterator = std::lower_bound(monsters.begin(), monsters.end(), mystats, comp);
    auto monster = *(monster_iterator - 1);
    std::cout << "You have level " << charLevel << '\n';
    std::cout << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
}

int main()
{
    std::vector<MonsterStats> monsters{
        {"Ogre","Grumble",345, 16},            //Type, Name, Health, Level
        {"Dragon","Spyro", 890, 21},           //Type, Name, Health, Level
        {"Orc","Rakanishu", 165, 11},          //Type, Name, Health, Level
        {"Giant Spider", "Arachnid", 80, 6},   //Type, Name, Health, Level
        {"Slime", "Blurp", 35, 1}};            //Type, Name, Health, Level

    std::string getChoice = "y";
    int charLevel;
    std::cout << "Please enter the level of your character to proceed to battle: ";
    std::cin >> charLevel;
    if(charLevel>0)
    {
        while(getChoice == "y")
        {
            printMonster(monsters, charLevel);

            std::cout << "Do you want to fight the monster? (y/n)";
            std::cin >> getChoice;
            if(getChoice == "y")
            {
                std::cout << "You destroyed the monster and gained an experience level!\n\n";
                charLevel += 1;
            }
            else
                std::cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
        }
    }
    else
        std::cout << "Please create a character in order to play the game.";
    return 0;
}

A cleaner program might be with a multiset (sorted container) using a custom comparator.更干净的程序可能是使用自定义比较器的多集(排序容器)。

The comparator could have this form:比较器可以具有以下形式:

struct myComp {
    bool operator()(const MonsterStats& i, const MonsterStats& j) {
        return i.level < j.level;
    }
};

And the multiset could use it:并且多重集可以使用它:

using myMultiset = std::multiset<MonsterStats, myComp>;

Then, searching can be simpler as the set is already sorted:然后,搜索可以更简单,因为集合已经排序:

auto& monster = *--monsters.upper_bound(mystats);

Printing could use the << operator:打印可以使用<<操作符:

std::ostream& operator<<(std::ostream& os, const MonsterStats& monster)
{
     std::cout 
         << "Monster has level: " << monster.level << '\n' 
         << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
     return os;
}

Full program:完整程序:

#include <iostream>
#include <string>
#include <set>

struct MonsterStats
{
    std::string type;
    std::string name;
    int health;
    int level;
};

struct myComp {
    bool operator()(const MonsterStats& i, const MonsterStats& j) {
        return i.level < j.level;
    }
};

using myMultiset = std::multiset<MonsterStats, myComp>;

std::ostream& operator<<(std::ostream& os, const MonsterStats& monster)
{
     std::cout 
         << "Monster has level: " << monster.level << '\n' 
         << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
     return os;
}

int main()
{
    myMultiset monsters{
        {{"Ogre","Grumble",345, 16},            //Type, Name, Health, Level
        {"Dragon","Spyro", 890, 21},           //Type, Name, Health, Level
        {"Orc","Rakanishu", 165, 11},          //Type, Name, Health, Level
        {"Giant Spider", "Arachnid", 80, 6},   //Type, Name, Health, Level
        {"Slime", "Blurp", 35, 1}}};            //Type, Name, Health, Level

    std::string getChoice = "y";
    std::cout << "Please enter the level of your character to proceed to battle: ";
    MonsterStats mystats{};
    std::cin >> mystats.level;
    if(mystats.level>0)
    {
        while(getChoice == "y")
        {
            auto& monster = *--monsters.upper_bound(mystats);
            std::cout 
                << "You have level " << mystats.level << '\n' 
                << monster
                << "Do you want to fight the monster? (y/n)";
            std::cin >> getChoice;
            if(getChoice == "y")
            {
                std::cout << "You destroyed the monster and gained an experience level!\n\n";
                ++mystats.level;
            }
            else
                std::cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
        }
    }
    else
        std::cout << "Please create a character in order to play the game.";
    return 0;
}

Or, if you include the operator< in the struct then you can simplify even further:或者,如果您在结构中包含operator<那么您可以进一步简化:

#include <iostream>
#include <string>
#include <set>

struct MonsterStats
{
    std::string type;
    std::string name;
    int health;
    int level;

    bool operator<(const MonsterStats& rhs) const {
        return level < rhs.level;
    }
};

using myMultiset = std::multiset<MonsterStats>;

std::ostream& operator<<(std::ostream& os, const MonsterStats& monster)
{
    std::cout
        << "Monster has level: " << monster.level << '\n'
        << "This " << monster.type << " is named " << monster.name << " and has " << monster.health << " health.\n";
    return os;
}

int main()
{
    myMultiset monsters{
        {{"Ogre","Grumble",345, 16},            //Type, Name, Health, Level
        {"Dragon","Spyro", 890, 21},           //Type, Name, Health, Level
        {"Orc","Rakanishu", 165, 11},          //Type, Name, Health, Level
        {"Giant Spider", "Arachnid", 80, 6},   //Type, Name, Health, Level
        {"Slime", "Blurp", 35, 1}}};            //Type, Name, Health, Level

    std::string getChoice = "y";
    std::cout << "Please enter the level of your character to proceed to battle: ";
    MonsterStats mystats{};
    std::cin >> mystats.level;
    if(mystats.level>0)
    {
        while(getChoice == "y")
        {
            auto& monster = *--monsters.upper_bound(mystats);
            std::cout
                << "You have level " << mystats.level << '\n'
                << monster
                << "Do you want to fight the monster? (y/n)";
            std::cin >> getChoice;
            if(getChoice == "y")
            {
                std::cout << "You destroyed the monster and gained an experience level!\n\n";
                ++mystats.level;
            }
            else
                std::cout << "You ran like Forest Gump and got out of the fight safely!\n\n";
        }
    }
    else
        std::cout << "Please create a character in order to play the game.";
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM