Save file data to a c ++ map

1

I can not read a txt file correctly and transfer it to a map in c ++.

The code I've developed works only if it has no "" spaces in the txt, if it has looped and does not work. Here is the code:

void dados::pesquisarProdutos(){

arq.open("produtos.txt",ios::in);

if (arq.fail()){
    perror("erro ao pesquisar: ");
    sleep(1);
    return;
}

string nome;
float preco;
int qnt;

while (!arq.eof()){
    arq >> nome >> preco >> qnt;
    map1.insert(make_pair(nome,loja(nome,preco,qnt)));
}

cout << "Qual produto procura: ";
getline(cin,nome);

it = map1.find(nome);

cout << it->first << "preco: "<< it->second.getPreco() << "quantidade: "<<
     it->second.getEstoque();

arq.close();}

If the product name is, for example, rice, it saves on the map and works normal, now if it is white rice, of the error. By the way the problem is in reading space, but I do not know how to solve.

Thanks for the help

    
asked by anonymous 28.08.2017 / 02:59

2 answers

1

In your case, using a blank space as a field delimiter is not a good idea.

I suggest that your data use another type of delimiter, such as the semicolon ( ; ):

Arroz Integral;10.50;100
Arroz Branco;15.50;100
Feijao Preto;5.70;350
Feijao Carioca;4.50;200
Milho;3.25;50
Trigo;7.10;50

In this way, you can use code like this to solve your problem:

#include <cstdlib>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <map>


class Produto
{
    public:

        Produto( void ) {}
        virtual ~Produto( void ) {}

        std::string nome( void ){ return m_nome; }
        float preco( void ){ return m_preco; }
        int qnt( void ){ return m_qnt; }

        void parse( std::string s )
        {
            std::size_t pos = 0;
            std::string tok;
            std::vector< std::string > v;

            while((pos = s.find(";")) != std::string::npos)
            {
                tok = s.substr( 0, pos );
                v.push_back(tok);
                s.erase( 0, pos + 1 );
            }

            v.push_back(s);

            m_nome = v[0];
            m_preco = atof(v[1].c_str());
            m_qnt = atoi(v[2].c_str());
        }

    private:

        std::string m_nome;
        float m_preco;
        int m_qnt;
};


int main( int argc, char * argv[] )
{
    std::ifstream arq( "produtos.txt" );
    std::string linha;
    std::map< std::string, Produto > mp;
    std::map< std::string, Produto >::iterator it;

    while( std::getline( arq, linha ) )
    {
        Produto p;
        p.parse( linha );
        mp.insert( std::make_pair( p.nome(), p ) );
    }

    it = mp.find(argv[1]);

    if( it == mp.end() )
    {
        std::cout << "Produto Nao Encontrado!" << std::endl;
        return 1;
    }

    Produto & p = it->second;

    std::cout << "Nome: " << p.nome() << std::endl
              << "Preco: " << p.preco() << std::endl
              << "Quantidade: " << p.qnt() << std::endl;

    return 0;
}

Testing:

$ ./produtos "Banana"
Produto Nao Encontrado!

$ ./produtos "Milho"
Nome: Milho
Preco: 3.25
Quantidade: 50

$ ./produtos "Arroz Integral"
Nome: Arroz Integral
Preco: 10.5
Quantidade: 100

$ ./produtos "Feijao Carioca"
Nome: Feijao Carioca
Preco: 4.5
Quantidade: 200
    
28.08.2017 / 21:43
1

A stream is usually extracted by whitespace. Thus, the fields of a stream are separated by this delimiter and when one of the fields has this delimiter internally, it conflicts, as you have noticed.

The simplest solution is to modify this delimiter by replacing it, for example with '|'. So the first thing you should do is change how the fields are formatted in your txt file, having each line as something like:

nome | preço | quantidade

After that, you just have to split the line in this new format. For this, you should convert this line to a new stream , stringstream , using this new delimiter and extracting the data as it had done before.

For example:

#include <sstream>
#include <iostream>
#include <string>
#include <cstdlib>

int main()
{
    // Simulando um stream do arquivo
    std::stringstream str("foo bar | 5.44 | 5\nbaar fooo | 6.01 |10");
    std::string name;
    double price;
    int qnt;

    std::string tmp; // serve para inicializar o stringstream stream
    while (std::getline(str, tmp))
    {
        std::stringstream stream(tmp);
        std::getline(stream, name, '|'); // extraindo name

        std::getline(stream, tmp, '|');  // extraindo price e convertendo
        price = std::atof(tmp.c_str());

        std::getline(stream, tmp, '|');  // extraindo qnt e convertendo
        qnt = std::atoi(tmp.c_str());

        std::cout << name << " | " << price << " | " << qnt << std::endl;
    }
}
    
28.08.2017 / 19:28