struct array of characters

4

I'm having to remember programming in c ++ to teach a beginner class in programming logic. Subject this I have not seen for years.

A struct was declared however when entering a string, the stream jumps to the next line. I looked for related topics here I did not find anything related.

Any help is welcome.

#include <iostream>
#include <string.h>

using namespace std;

struct Agenda{
    char nome[50];
    int cod;
};

int main()
{
    Agenda a[3];

    for(int i=0;i<3;i++){
        cout << "Nome: ";
        cin.get(a[i].nome, 50);
        cout << "Cód: ";
        cin >> a[i].cod;

    }

    for(int i=0;i<3;i++){
        cout << a[i].nome << "\t" << a[i].cod << "\n";
    }



    return 0;
}

Running Image

I'm thanking you from here

    
asked by anonymous 26.10.2018 / 22:53

1 answer

2

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

        
    26.10.2018 / 23:45