How to deal with the use of getline() in a for(;)?

Asked

Viewed 1,326 times

1

I’m storing author names of books in a string array.

     for(int i = 0; i<qt; i++)
        {
            cin >> nome;
            NOME[i] = nome;
        }

But I want to have the full name, first name and last name, so I thought I’d do:

for(int i = 0; i<qt; i++)
        {
            getline(cin,nome);
            NOME[i] = nome;
        }

But, if qt == 2 for example, it will only read the name of an author, type "Flavio Melo", after reading the first it will not read the second name.

So I tried:

for(int i = 0; i<qt; i++)
        {
            LIMPA_BUFFER;
            getline(cin,nome);
            NOME[i] = nome;
        }

Where LIMPA_BUFFER; ago cin.ignore(INT_MAX, '\n'). But still, he will read the name of the first author, the second, and then jump to a third author! (still in the case where qt == 2). When I print the vector with the names of the authors, do not print any name.

How do I read the full names, store in the array, and display the names normally using the getline()?

Here follows the full TAD implementation code:

My problem is in case 1: and in the method inserir_autor()

# include <iostream>
# include <stdio.h>
# include <stdlib.h>
# include <climits>
# include <cassert>

#define TAM_max 10
#define LIMPA_BUFFER    cin.ignore(INT_MAX, '\n')

using namespace std;

class Livro
{
private:
    friend class Data;

    string *Autores;
    string Titulo;
    int aux = 0;

public:

    Livro ()
    {
        Autores = new string [TAM_max+1];
    }

    /// Titulo do livro
    void titulo_livro (string titulo)
    {
        Titulo = titulo;
    }

    /// Adiciona os autores principais
    void inserir_autor (string* &nome_aut, int qt)
    {
        aux = qt;
        for(int i = 0; i<qt; i++)
        {
            Autores[i] = nome_aut[i];
        }

    }

    /// Adiciona mais autores
    bool inserir_mais_autores (string novo_aut)
    {
        if(aux < TAM_max)
        {
            Autores[aux] = novo_aut;
            aux++;
            return true;
        }
        else
            return false;

    }

    /// Remove um autor
    bool remover_autor (string autor_remv)
    {
        for(int i = 0; i<TAM_max ; i++)
        {
            if(Autores[i] == autor_remv)
            {
                for(int j=i; j<TAM_max; j++)
                {
                    Autores[j] = Autores[j+1];
                }
                aux--;
                return true;
            }
        }
        return false;
    }

    /// Altera o titulo
    void altera_titulo (string novo_titulo)
    {
        Titulo = novo_titulo;
        cout << "\n Seu novo Titulo: " << Titulo << endl;
    }



    /// Altera autor
    bool altera_autor (string autor, string novo_autor)
    {
        for(int i = 0 ; i<TAM_max; i++)
        {
            if(Autores[i] == autor)
            {
                Autores[i] = novo_autor;
                return true;
            }
        }
        return false;

    }

    /// Imprime os dados do livro
    void imprime_livro()
    {
        cout << "\t Dados do livro:" << "\n" << endl;
        cout << "\n Titulo: " << Titulo << endl;
        cout << "\n Autores: \n" << endl;
        for(int i = 0 ; Autores[i] != "" ; i++)
        {
            cout<< "[" << i+1 << "] = " << Autores[i] << "\n" <<endl;
        }
    }

};


class Data
{
private:
    friend class Livro;
    int DIA = 0, MES = 0, ANO = 0;

public:

    bool verifica_data(int dia, int mes, int ano)
    {
        if( (dia >= 1 && dia <= 31) && (mes >= 1 && mes <= 12) ) //verifica se os numeros sao validos)
        {
            if ((dia == 29 && mes == 2) && ((ano % 4) == 0 && (ano % 100)!= 0 || (ano % 400) == 0)) //verifica se o ano e bissexto
            {
                return true;
            }
            if (dia <= 28 && mes == 2) //verifica o mes de fevereiro
            {
                return true;
            }
            if ((dia <= 30) && (mes == 4 || mes == 6 || mes == 9 || mes == 11)) //verifica os meses de 30 dias
            {
                return true;
            }
            if ((dia <=31) && (mes == 1 || mes == 3 || mes == 5 || mes == 7 || mes ==8 || mes == 10 || mes == 12)) //verifica os meses de 31 dias
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    void inserir_data(int dia, int mes, int ano)
    {
        DIA = dia;
        MES = mes;
        ANO = ano;
    }

    void imprime_data()
    {
        cout << " Data de Publicacao: " << "\n" << endl;
        cout << DIA << "/" << MES << "/" << ANO << "\n" <<endl;
    }

};

int main()
{

    Livro L;
    Data D;

menu:

    cout << "\n" << endl;
    system("cls");

    int op=0;
    cout << "\tEstante Virtual\n" << endl;
    cout << "1 - Cadastrar livro" << endl;
    cout << "2 - Imprimir dados" << endl;
    cout << "3 - Remover um autor(a)" << endl;
    cout << "4 - Inserir novo autor(a)" << endl;
    cout << "5 - Alterar nome do livro" << endl;
    cout << "6 - Alterar data de publicacao" << endl;
    cout << "7 - Alterar nome de um autor(a)" << endl;
    cout << "0 - Encerrar programa"<< "\n"  << endl;

    cin >> op;
    switch (op)
    {
    case 0:
        return 0;

    case 1:
        {
            system("cls");

            int qt = 0;
            int dia = 0, mes = 0, ano = 0;
            bool valida_data;
            string titulo;

            cout << " Nome do livro: \n" << endl;
            LIMPA_BUFFER;
            getline(cin, titulo);
            L.titulo_livro(titulo);

            cout << "\n Informe a quantidade de autores: \n" << endl;
            cin >> qt;

            while(qt > 0)
            {
                if(qt > 0 && qt <= TAM_max)
                    break;
                else
                {
                    cout << "\n Informe no minimo 1 e no maximo 10 autores" << endl;
                    cin >> qt;
                }

            }

            cout << "\n Informe seus nomes: \n" << endl;
            string *NOME = new string [TAM_max+1];
            string nome;

            for(int i = 0; i<qt; i++)
            {
                cin >> nome;
                NOME[i] = nome;
            }


            L.inserir_autor(NOME,qt);

            cout << "\n Data de publicacao: \n" << endl;
            cin >> dia >> mes >> ano;
            valida_data = D.verifica_data(dia,mes,ano);
            if(valida_data == true)
            {
                D.inserir_data(dia,mes,ano);
            }
            else
            {
                while(valida_data == false) //Enquanto não for válido, então...
                {
                    cout << "\n Data invalida! \n\n Informe uma data de publicacao valida: \n" << endl;
                    cin >> dia >> mes >> ano;
                    valida_data = D.verifica_data(dia,mes,ano);
                }
                D.inserir_data(dia,mes,ano);
            }

            system("cls");
            cout << " Cadastro efetuado com sucesso! \n" << endl;
            system("pause");
            break;
        }

    case 2:
        {
            system("cls");
            L.imprime_livro();
            D.imprime_data();

            system("pause");
            break;
        }

    case 3:
        {
            system("cls");
            string autor_remv;

            cout << " Informe o autor que deseja remover: " << endl;
            cin >> autor_remv;

            bool valor = L.remover_autor(autor_remv);
            if(valor == true)
                cout << "\n Autor removido com sucesso! \n" << endl;
            else
                cout << "\n Autor inexistente! \n" << endl;

            system("pause");
            break;
        }

    case 4:
        {
            system("cls");
            string autor;
            bool valor;

            cout << " Informe o nome do autor: " << endl;
            cin >> autor;

            valor = L.inserir_mais_autores(autor);
            if(valor == true)
                cout << "\n Autor cadastrado com sucesso! \n" << endl;
            else
                cout << "\n Limite maximo de autores atingido! \n" << endl;

            system("pause");
            break;
        }

    case 5:
        {
            system("cls");
            string novo_titulo;

            cout << " Informe o novo nome para o livro: \n" << endl;
            LIMPA_BUFFER;
            getline(cin, novo_titulo);
            L.altera_titulo(novo_titulo);
            cout << "\n Titulo alterado com sucesso! \n" << endl;

            system("pause");
            break;

        }

    case 6:
        {
            system("cls");
            int dia = 0, mes = 0, ano = 0;

            cout << " Informe a nova data: \n" << endl;
            LIMPA_BUFFER;
            cin >> dia >> mes >> ano;
            D.inserir_data(dia,mes,ano);

            cout << "\n Data alterada com sucesso! \n" << endl;

            system("pause");
            break;

        }

    case 7:
        {
            system("cls");
            string autor, novo_autor;
            bool valor;

            cout << " Informe o nome do autor que sera modificado:" << endl;
            cin >> autor;

            cout << "\n Informe o novo nome:" << endl;
            cin >> novo_autor;

            valor = L.altera_autor(autor, novo_autor);

            if(valor == true)
                cout << "\n Autor renomeado com sucesso! \n\n" << endl;
            else
                cout << "\n '" << autor << "' nao foi encontrado! \n\n" << endl;

            system("pause");
            break;

        }
    }
    goto menu;
    return 0;
}
  • Put a functional code demonstrating the problem.

  • @bigown, the code is pretty big, but I’ll put.

  • 1

    Just put a part that shows the problem in a way that you can compile and execute. http://answall.com/help/mcve

  • @bigown, I put it all in, you can rotate it. Go to option 1, and just follow the instructions. Now my problem is that I want to add the full name of the author and I can’t get a good command or logic for this.

  • @Filipimaciel Has more elegant solution, but you can simply put more of a getline in the same loop. For example, echo on the screen "type the first name", getline(), "type the last name", and another getline() within the same loop.

  • I will not have the patience to find the mistake for you. If someone does, you will have an answer. Doing MCVE is important to facilitate who will help you and to develop as a solution maker. As the text there speaks, you may find the problem alone trying to isolate it.

  • @Bacco, in this case, would name and surname be in separate variables? Because if using the same one it will override. If you have in distinct variables, like a pro name and another for last name, how would I put these variables together in a single position of the string array?

  • @bigown, sorry but did not understand your suggestion. What would be MCVE?

  • Read the link that I passed you up.

  • @Filipimaciel I’m just giving a preliminary tip, let’s see if it comes out any good answer that suits you ;) . I would suggest that you think carefully about the desired structure, and if you need to add to the question all the necessary details of your specific need, taking advantage of the fact that you have not answered yet. As for the MCVE, the link in blue that the bigown posted has the explanation.

  • @bigown, Oh yes, thank you, I’ll try that.

  • @Bacco, Tranquil, I will think of something. I will try to take this to my fellow students, if I get answer I put here. Thank you!

  • @Filipimaciel of curiosity, what would be the problem of the person typing "Filipi Maciel" in the same getline? Would there be any particular reason why you separate the name and the surname will put in the same place?

Show 8 more comments

1 answer

2


A possible solution passes, as you presented in your question, by the use of the function getline. The replacement in this case is almost immediate. You just have to ensure that the buffer cin is cleaned before using the function getline. Your code would look like this:

case 1:
    {
        system("cls");

        //(...)

        cout << "\n Informe seus nomes: \n" << endl;
        string *NOME = new string [TAM_max+1];
        string nome;

        //limpar buffer
        cin.clear();
        cin.ignore(INT_MAX, '\n');

        for(int i = 0; i<qt; i++)
        {
            //cin >> nome;
            getline(cin, nome);
            NOME[i] = nome;
        }

        L.inserir_autor(NOME,qt);

        //(...)

        system("cls");
        cout << " Cadastro efetuado com sucesso! \n" << endl;
        system("pause");
        break;
    }

As a final comment, I suggested using the class vector instead of using pointers for the string class. In your case there is no advantage, on the contrary, it is giving rise to a "memory Leak" (memory leak/leak):

Every time you register the names of the authors of the books you’re allocating memory that is never released:

  string *NOME = new string [TAM_max+1];
  • Hello @Bruno, I tried it and it really worked. I had implemented a very inelegant solution, which was the following: char NOMEAUX[100]; and used the function gets() to read and store each character within this vector. Then pass this vector to NOME[i] = nome;, that accepted to pass a string and convert it into a single string. Your solution worked, but I couldn’t figure out why you should clean the buffer just once before going to for, and I also didn’t understand why cleaning the buffer inside the for is a problem. You can help me with these doubts?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.