Your requirements appear to suggest that the input data is fixed-type. You only need supply the correct type for
cin >>
to work.
1 2 3 4 5 6 7 8 9
|
string surname;
string name;
int age;
string placeofbirth;
int telephonenumber;
...
cin >> surname >> name >> age >> placeofbirth >> telephonenumber;
|
Now, here's your reported problem: whitespace. A person's name(s) and the place of birth may have whitespace in it. This requires you to do some more careful parsing.
In fact, this leads us to one of the most obnoxious parts of I/O:
Input is always harder than output!
I recommend you read a line (an entire record) as a string, then parse out the individual components of the string. This will make your life significantly easier.
Continuing, I'll assume a line of input that looks like this:
De Sola, Juán Omar 22 A Coruña 777-123-456
The trick is to notice where the type of thing changes:
1. Surnames terminate with a comma (you may generally require that.
If your professor disagrees, ask him how to separate family and given names.)
2. Age is composed of numeric digits.
3. A city/province/state/country is
not composed of any digits
-OR- it is not the phone number.
4. Phone number is composed of digits and optional + and - signs.
Let's split that up, then.
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
|
struct PersonalData
{
std::string surname;
std::string given_names;
unsigned age;
std::string place_of_birth;
unsigned long long phone_number;
};
std::istream& operator >> ( std::istream& ins, PersonalData& pdata )
{
std::string s;
if (!getline( ins, s )) return ins;
// Find the important breaks in the string
auto index_end_of_surname = s.find( ',' );
auto index_first_age_digit = s.find_first_of( "0123456789" );
auto index_end_of_age = s.find( ' ', index_first_age_digit );
auto index_first_phone_digit = s.find_last_not_of( "0123456789+- " ) + 1;
// Break out the pieces
pdata.surname = trim( s.substr( 0, index_end_of_surname ) );
pdata.given_names = trim( s.substr( index_end_of_surname + 1, index_first_age_digit - index_end_of_surname - 1 ) );
pdata.age = string_to<decltype(pdata.age)>( s.substr( index_first_age_digit, index_end_of_age - index_first_age_digit ), 0 );
pdata.place_of_birth = trim( s.substr( index_end_of_age, index_first_phone_digit - index_end_of_age ) );
pdata.phone_number = string_to<decltype(pdata.phone_number)>( strip_not_of( s.substr( index_first_phone_digit ), "0123456789" ), 0 );
return ins;
}
|
You'll notice that a lot of helper routines are used.
trim:
http://www.cplusplus.com/faq/sequences/strings/trim/
string_to:
1 2 3 4 5 6 7 8
|
template <typename T>
T string_to( const std::string& s, const T& default_value = T() )
{
T result;
std::istringstream ss( s );
ss >> result >> std::ws;
return ss.eof() ? result : default_value;
}
|
strip_not_of: you can create your own, or store the phone number as a string, etc.
Here's the code I used to test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
std::ostream& operator << ( std::ostream& outs, const PersonalData& pdata )
{
return outs << pdata.surname << ", " << pdata.given_names << " " << pdata.age << " " << pdata.place_of_birth << " " << pdata.phone_number;
}
int main()
{
std::istringstream input
(
"De Sola, Juán Omar 22 A Coruña 777-123-456\n"
"Solíz, Mario 35 Seville +34 777 654 321"
);
std::vector <PersonalData> student_personal_data;
{
PersonalData pd;
while (input >> pd)
student_personal_data.emplace_back( pd );
}
for (auto pd : student_personal_data)
std::cout << pd << "\n";
}
|
De Sola, Juán Omar 22 A Coruña 777123456
Solíz, Mario 35 Seville 34777654321 |
I know this is a lot to take in, and I've probably written more than needed, but hopefully it will help.
Notice also that I took a few liberties with error handling: basically
ignoring errors and returning a record anyway.
Hope this helps.