问题
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