ne555 wrote: |
---|
Instead of asking for messages to show, you should throw exceptions and let the program to resolve them. |
I think that's an overkill.
There's a good reason why I use getline instead of the >> operator. In general, it's not good practice to use both of them. That's because getline doesn't leave the delimitation character (usually being '\n') in the buffer, while the >> operator does. And since getline is what I want to use to get strings, I use it to get numbers as well. Using both (getline and operator >>) allows situations like this to arise:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
int n;
cout << "enter your age: ";
cin >> n;
cout << "enter your name: ";
getline(cin,str);
cout << "hello, " << str << endl;
cout << "you are " << n << " years old" << endl;
cin.get();
return 0;
}
|
You'll notice that the above piece of code doesn't work as expected. It's because
cin >> n;
leaves a '\n' in the buffer.
getline(cin,str)
then "sees" that '\n' and assumes that you've entered a blank line. Thus str is set to "". Furthermore, if the user enters something like "23asdf" when asked for his age, n is set to 23 and str is set to "adsf". This is something you don't want. You can easily fix it by replacing
cin >> n;
with something like this:
1 2 3 4 5 6
|
cin >> n;
if (!cin)
{
cin.clear();
while (cin.get()!='\n');
}
|
OR you could do something like this:
1 2 3
|
string input;
getline(cin,input);
istringstream(input)>>n;
|
I find the latter to be a cleaner way.
getline(cin,input)
doesn't leave anything in the input buffer, and bad input can't affect your stream's status.
ne555 wrote: |
---|
(You could pass an istream object instead of using cin too) |
Yes, I suppose I could do that. But why? In most of the cases I'll work with cin/cout for console input/output. And I don't suppose I can use this to validate input from a file, since I can't ask a file to re-enter the data correctly (to the best of my knowledge...).
ne555 wrote: |
---|
Besides, with the getline, if the input comes like this
you'll only read the first number and ignore the rest of the line. |
Well, I think that's actually an advantage of the method I use. If you allow input like this, how will you implement the validation procedure? You can't check them separately, you have to get them all before you check them. Well, I suppose you could do something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
int a,b,c,d;
bool oka, okb, okc, okd;
oka=okb=okc=okd=false;
while (true)
{
cout << "enter a b c d : ";
if (!oka)
{
cout << "enter a: ";
cin>>a;
if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
else oka=true;
}
if (!okb)
{
cout << "enter b: ";
cin>>b;
if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
else okb=true;
}
if (!okc)
{
cout << "enter c: ";
cin>>c;
if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
else okc=true;
}
if (!okd)
{
cout << "enter d: ";
cin>>d;
if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
else okd=true;
}
break;
}
|
But that's an overkill too. I prefer this, even if it doesn't allow me to enter the numbers in one line.
1 2 3 4 5 6
|
int a,b,c,d;
cout << "enter a b c d : ";
while (!get_int(a,"enter a: "));
while (!get_int(b,"enter b: "));
while (!get_int(c,"enter c: "));
while (!get_int(d,"enter d: "));
|
ne555 wrote: |
---|
Also
if (min>max) return get_int(n,invalid_msg,max,min,range_msg);
If you always call the function with the right arguments (i.e. constants), you'll make an unnecessary check in every function call. |
I don't think that check really slows me down, but if you don't like it you can remove it.