Save file data to a c++ map

Asked

Viewed 387 times

1

I am not able to read a txt file correctly and transfer to a map in c++.

The code I developed works only if you don’t have spaces " " in txt, if you loop and it doesn’t work. Here’s 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 in the map and works normal, now if it is white rice, error. Apparently the problem is reading space, but I don’t know how to solve.

Thanks for your help

  • Why is the C tag? C and C++ a completely different program.

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

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

1

A stream is normally extracted by white spaces. Thus, the fields of a stream are separated by this delimiter and when one of the fields has this delimiter internally, gives conflict, as you realized.

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, just do the separation of the line in this new format. For this, you should convert this line into a new stream, the stringstream, using this new delimiter and extract 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;
    }
}

Browser other questions tagged

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