1

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?

mooncrater
  • 27
  • 2
  • 4
    Please explain exactly what's the current behavior instead of just _It's not working_ (what's the compiler error message?), and show a [mcve] consists of example input/output. – user202729 May 15 '18 at 07:01
  • [Possible dupe](https://stackoverflow.com/questions/5289597/push-back-a-struct-into-a-vector)? – user202729 May 15 '18 at 07:03
  • 2
    Unrelated: [Why is iostream::eof inside a loop condition considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – user4581301 May 15 '18 at 07:05
  • it is rather unlikely that `push_back` is broken. You should explain why it isnt working – 463035818_is_not_a_number May 15 '18 at 07:10
  • 3
    (in this case, it happens that the input doesn't matter, then you don't need to open a file and read input, they're not required in a [mcve] anyway) – user202729 May 15 '18 at 07:12
  • @mooncrater Instead of leaving "Thanks" comment, you can just accept answers. Read [this](https://stackoverflow.com/help/someone-answers). – user202729 May 15 '18 at 07:35
  • Welcome to Stack Overflow! You really ought to avoid `using namespace std` - it is a bad habit to get into, and [can silently change the meaning of your program](/q/1452721) when you're not expecting it. Get used to using the namespace prefix (`std` is intentionally very short), or importing *just the names you need* into the *smallest reasonable scope*. It's especially pernicious in header files, as you now inflict the problem on every source file that includes the header! – Toby Speight May 15 '18 at 09:22

4 Answers4

2

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;
}
PapaDiHatti
  • 1,559
  • 14
  • 23
  • With Aggregate initialization that is shown with push_back scenario we need to create temporary that will be moved and with this constructor approach object will be created in place inside vector – PapaDiHatti May 15 '18 at 08:20
  • This will not compile check here : https://repl.it/repls/PhysicalFrivolousOctagon – PapaDiHatti May 15 '18 at 08:23
1

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);
acraig5075
  • 9,913
  • 3
  • 29
  • 45
1

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.

user4581301
  • 29,019
  • 5
  • 26
  • 45
1

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.

Toby Speight
  • 23,550
  • 47
  • 57
  • 84