The problem is with cin.get
and how it works. In fact mix forms of different readings:
cin >>
cin.get
Generally, it creates complications because there are scenarios where they do not behave in the same way.
I'll start by quoting documentation on cin.get
in an important detail:
The delimiting character is not extracted from the input sequence if found, and there remains the next character to be extracted from the stream
Free translation:
The delimiter is not extracted from the input string if it is found, and remains the same as the next character to be extracted.
Then it happens that when you read the first code with cin >> a[i].cod
the \n
is in the entry, and then when it goes with cin.get
it does not read anything because \n
is the first caratere and is soon a delimiter . And cin.get
also does not remove it from the input creating a vicious cycle to the end.
After realizing the problem has some solutions.
cin.ignore
cin.ignore
allows you to discard characters from the entry, and you can specify how many you want to discard. In your case you just need to discard one that corresponds to \n
, which has to be done in the right place:
for(int i=0;i<3;i++){
cout << "Nome: ";
cin.get(a[i].nome, 50);
cout << "Cód: ";
cin >> a[i].cod;
cin.ignore(); // <-- consumir a quebra de linha que ficou aqui
}
See it working on Ideone
Read everything with >>
If you do all the readings in the same way, the general rule works, because they all consume the breaks in the same place.
It is important to mention that in reading string
this can be limiting if you want the string to have spaces , because this reading only reads into the space, ie only one word
If it does not work perfectly, see the example:
for(int i=0;i<3;i++){
cout << "Nome: ";
cin >> a[i].nome; // agora com >>
cout << "Cód: ";
cin >> a[i].cod;
}
See Ideone
Using std::string
In C ++ you have better way to store strings, which is to use std::string
and which simplifies your life, avoiding having to control string terminators, and other details.
It's interesting to mention this because you end up making a common mistake at this point, because reading nome
puts you an additional terminator in the string, so you have to read 49
characters and not 50
to prevent it from quitting out of allocated space.
If you change the frame field to std::string
you can read it with std::getline
and everything gets simpler:
//...
struct Agenda{
string nome; // agora string
int cod;
};
int main(){
Agenda a[3];
for(int i=0;i<3;i++){
cout << "Nome: ";
getline(cin, a[i].nome); //leitura com getline
cout << "Cód: ";
cin >> a[i].cod;
cin.ignore(); //ignore na mesma
}
//...
See also in Ideone