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?

7
  • 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 minimal reproducible example consists of example input/output. Commented May 15, 2018 at 7:01
  • Possible dupe? Commented May 15, 2018 at 7:03
  • 2
    Unrelated: Why is iostream::eof inside a loop condition considered wrong? Commented May 15, 2018 at 7:05
  • it is rather unlikely that push_back is broken. You should explain why it isnt working Commented May 15, 2018 at 7: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 minimal reproducible example anyway) Commented May 15, 2018 at 7:12

4 Answers 4

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; } 
Sign up to request clarification or add additional context in comments.

2 Comments

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
This will not compile check here : repl.it/repls/PhysicalFrivolousOctagon
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); 

Comments

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.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.