mooncrater
mooncrater

Reputation: 27

Read data from a file in vector

My task is to read this data from a file into a vector:

21000 Landhau Nolte brown
19000 Modern_fit Hoeffner magnolie
14700 Pure_Style Wellmann black

This is my attempt, but push back isn't working. I already looked at some examples here at Stack Overflow, but somehow it's not working.

functions.h:

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;

struct Kitchen {
    double price;
    string name;
    string manufacturer;
    string color;
};

main.cpp:

#include "functions.h"

int main(){

    vector<Kitchen> Kitchens;

    fstream myFile;
    myFile.open("kitchen.txt", ios::in);
    if (myFile.is_open()) {
        while (!myFile.eof()) {
            double price;
            string name;
            string manufacturer;
            string color;
            myFile >> price >> name >> manufacturer >> color;
            Kitchens.push_back(price, name, manufacturer, color);

        }

        myFile.close();
    }
    else cout << "not opened." << endl;

    system("PAUSE");
    return EXIT_SUCCESS;
}

What am I doing wrong?

Upvotes: 1

Views: 84

Answers (4)

Toby Speight
Toby Speight

Reputation: 30709

Let's do this properly.

Starting with the header, don't include more than needed for the definitions in that header, and don't import all identifiers from std into the global namespace.

#include <string>

struct Kitchen {
    double price;
    std::string name;
    std::string manufacturer;
    std::string color;

    Kitchen(double price, std::string name,
            std::string manufacturer, std::string color)
        : price{price}, name{name}, manufacturer{manufacturer}, color{color}
    {}
};

I've added a simple constructor, as we'll need that for emplace_back later.

Now implement the main(). For a reproducible example, it's better to read from a string stream than to have to mess about with files:

#include <vector>
#include <sstream>
#include <iostream>

int main()
{
    std::vector<Kitchen> kitchens;

    std::istringstream file("21000 Landhau Nolte brown\n"
                            "19000 Modern_fit Hoeffner magnolie\n"
                            "14700 Pure_Style Wellmann black\n");

    {
            double price;
            std::string name;
            std::string manufacturer;
            std::string color;
            while (file >> price >> name >> manufacturer >> color) {
                kitchens.emplace_back(price, name, manufacturer, color);
            }
    }

    std::clog << "Read " << kitchens.size() << " kitchens from input\n";
}

Note here that !eof() doesn't guarantee that a read will succeed. Instead, we attempt the read, and then test whether the input stream is in a failure state. After the loop, we could (if we wanted) actually check that we reached end of file, rather than some failure condition - I've omitted that for this simple program.

Upvotes: 1

PapaDiHatti
PapaDiHatti

Reputation: 1921

structure is an aggregate type but for pushing struct object into vector of struct, you have to create one even though it can be temporary :

#include <iostream>
#include <vector>
using namespace std;
struct Kitchen {
    double price;
    string name;
    string manufacturer;
    string color;
};
int main() {
  std::vector<Kitchen> kt;
  kt.push_back(Kitchen{21000,"Landhau","Nolte","brown"});

 return 0;
}

Also with minor modification and having a parameterized constructor in your Kitchen struct you can avoid internal copying/moving operation of push_back and directly use emplace_back.

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
struct Kitchen {
    double price;
    string name;
    string manufacturer;
    string color;
    Kitchen(double p,
            const string& n,
            const string &m,
            const string &c):price(p),name(n),manufacturer(m),color(c) {}
};
int main(){

    vector<Kitchen> Kitchens;

    fstream myFile;
    myFile.open("kitchen.txt", ios::in);
    if (myFile.is_open()) {
        while (!myFile.eof()) {
            double price;
            string name;
            string manufacturer;
            string color;
            myFile >> price >> name >> manufacturer >> color;
            Kitchens.emplace_back(price, name, manufacturer, color);

        }

        myFile.close();
    }
    else cout << "not opened." << endl;

    system("PAUSE");
    return EXIT_SUCCESS;
}

Upvotes: 2

user4581301
user4581301

Reputation: 33932

push_back takes a Kitchen. The code is providing pieces of a Kitchen. Give emplace_back a try or instantiate a temporary Kitchen to pass into push_back.

Upvotes: 1

acraig5075
acraig5075

Reputation: 10756

What you're doing wrong is trying to pass 4 random variables to a push_back that actually only takes one, and that one is of the value type of the vector.

Kitchen k; 
myFile >> k.price >> k.name >> k.manufacturer >> k.color;
Kitchens.push_back(k);

Upvotes: 1

Related Questions