Conditionally Breaking A Long Sequence Of Inputs?

元气小坏坏 提交于 2019-12-13 04:33:35

问题


I have a personal project I've been working on. To work, it needs to accept a lot of data (relatively) from the user, in the form of four different kinds of data for 12 users. As such, I have quite a lengthy sequence of statements similar to this:

cout << '\n' << "Monster A's name is: ";
cin >> nameA;
cout << '\n' << "Monster A rolled: ";
cin >> rollM_A;
cout << '\n' << "Monster A's Dex is: ";
cin >> DexA;
cout << '\n' << "Monster A's Mod is: ";
cin >> ModA;
cout << '\n' << "Monster A's Level is: ";
cin >> LvlA;

etc.

Occasionally, however, there might only be a need to input data for less than 12 monsters, say, 5-6 or even 1-2. I'd like to be able to use a command to skip the input section to the rest of the code based on something like a keystroke. i.e. If the user has put in data for 5 monsters, and that's all they require, they could hit the backslash to skip the rest of the input sequence.

Does what I'm talking about make any sense/is there an STL command to do what I'm looking for? Currently, this process isn't looped, but would exiting it be easier if it was inside a loop? I did have a thought of trying something like this:

while(cin.get() != '\') {
   cout << '\n' << "Monster A's name is: ";
   cin >> nameA;
   //etc...
}

EDIT: The above attempt builds, but upon entering the desired keystroke, it quickly and endlessly prints the user prompts without accepting data. Any advice? All I want is for it to break and move on. Can I use a switch statement effectively?

Thanks!


回答1:


I just tested this set of code and it seems to work how you would like. Of course you will have to modify it to fit your original application.

std::string in;

while (true) {
    std::cout << "Enter a name\n";
    std::cin >> in;
    if (in == "#")
        break;
    std::cout << "\nMonster A's name is: " << in << "\n";
}

In order to incorporate the limit of the number of monsters, rather than having the true parameter passed into the while loop, simply add a counter to how many monsters are created and break on that condition:

int num_monsters = 0;
while (num_monsters <= 12) {
    ...
    num_monsters++;
}

Hope this helps.




回答2:


That could work. You can also use EOF, which is more general, than '\'. Then when you are done, hit Ctrl-D to send the EOF, and you are done. This takes care of the situation when some player enters '\' as the Monster's name.




回答3:


You can check if the name is \, it is not user friendly but it works.

string name;
while (name != "\\") {
    cout << '\n' << "Monster A's name is: ";
    cin >> name;
    cout << "Received " << name << '\n';
    if (name != "\\") {
        // do something with name ...
    }
}

If the loop still loops endlessly, refer to How do I flush the cin buffer? and try clearing stdin buffer.

[edit] I fixed an error in the loop




回答4:


Here's something I wrote.

struct Monster {
string name;
bool roll;
float dex;
float mod;
float level;
Monster(void) :
  name(),
  roll(false),
  dex(0),
  mod(0),
  level(0) { }
};


bool getMonsterInformationFromStdin(int index, Monster& monster) {
  string end_char = "\\";
  string name, roll, dex, mod, level;
  cout << '\n' << "Monster " << index << "'s name is: ";
  cin >> name;
  if (name.compare(end_char) == 0) return false;
  monster.name = name;
  cout << '\n' << "Monster " << index << " rolled: ";
  cin >> roll;
  if (roll.compare(end_char) == 0) return false;
  monster.roll = (roll[0] == 'y' || roll[0] == 'Y') ? true : false;
  cout << '\n' << "Monster " << index << "'s Dex is: ";
  cin >> dex;
  if (dex.compare(end_char) == 0) return false;
  monster.dex = atof(dex.c_str());
  cout << '\n' << "Monster " << index << "'s Mod is: ";
  cin >> mod;
  if (mod.compare(end_char) == 0) return false;
  monster.mod = atof(mod.c_str());
  cout << '\n' << "Monster " << index << "'s Level is: ";
  cin >> level;
  if (level.compare(end_char) == 0) return false;
  monster.level = atof(level.c_str());
  return true;
}


int main(int argc, char** argv) {
  int max_monsters = 10;
  for (int i = 0; i < max_monsters; i++) {
    Monster m;
    if( !getMonsterInformationFromStdin(i, m) ) break;
    string roll = m.roll ? "rolled" : "didn't roll";
    cout << m.name << " " << roll << " dex: " << m.dex << " mod: " << m.mod << " level: " << m.level << endl;
  }
  return 0;
}



回答5:


I think this is problem can be solved by using a sentinel Monster name, as u can see below.

const string SentinelName = "%^&";
while(true)
{
    cout << '\n' << "Monster A's name is(if u want to end, pls input %^&): ";
    cin >> nameA;
    if(strcmp(nameA, SentinelName.s_str())
        break;
    cout << '\n' << "Monster A rolled: ";
    cin >> rollM_A;
    cout << '\n' << "Monster A's Dex is: ";
    cin >> DexA;
    cout << '\n' << "Monster A's Mod is: ";
    cin >> ModA;
    cout << '\n' << "Monster A's Level is: ";
    cin >> LvlA;
}

Hope this can solve ur problem. Besides, A little advice for ur code, u can encapsulate the attributes of the monster, such as the name, mode level, etc into a class and this will make ur code look fancier.



来源:https://stackoverflow.com/questions/17118898/conditionally-breaking-a-long-sequence-of-inputs

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!