Чтение данных из файла в векторе

Моя задача — прочитать эти данные из файла в вектор:

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

Это моя попытка, но откат не работает. Я уже посмотрел несколько примеров здесь, в Stack Overflow, но почему-то это не работает.

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;
}

Что я делаю не так?


person mooncrater    schedule 15.05.2018    source источник
comment
Пожалуйста, объясните, каково текущее поведение, а не просто Это не работает (что за сообщение об ошибке компилятора?), и покажите минимальный воспроизводимый пример состоит из примера ввода/вывода.   -  person user202729    schedule 15.05.2018
comment
Возможный обман?   -  person user202729    schedule 15.05.2018
comment
Несвязанный: Почему iostream::eof внутри условия цикла считается неправильным ?   -  person user4581301    schedule 15.05.2018
comment
маловероятно, что push_back сломан. Вы должны объяснить, почему это не работает   -  person 463035818_is_not_a_number    schedule 15.05.2018
comment
(в этом случае бывает, что ввод не имеет значения, тогда вам не нужно открывать файл и читать ввод, они не требуются в минимальный воспроизводимый пример в любом случае)   -  person user202729    schedule 15.05.2018
comment
@mooncrater Вместо того, чтобы оставлять комментарий с благодарностью, вы можете просто принять ответы. Прочтите это.   -  person user202729    schedule 15.05.2018
comment
Добро пожаловать в Stack Overflow! Вам действительно следует избегать using namespace std - это плохая привычка, и может незаметно изменить смысл вашей программы, когда вы этого не ожидаете. Привыкайте использовать префикс пространства имен (std намеренно очень короткий) или импортировать только нужные вам имена в наименьшую разумную область действия. Это особенно пагубно для файлов заголовков, так как теперь вы создаете проблему для каждого исходного файла, который включает заголовок!   -  person Toby Speight    schedule 15.05.2018


Ответы (4)


структура является агрегатным типом, но для помещения объекта структуры в вектор структуры вам необходимо создать его, даже если он может быть временным:

#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;
}

Также с небольшой модификацией и наличием параметризованного конструктора в структуре Kitchen вы можете избежать внутренней операции копирования/перемещения push_back и напрямую использовать 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;
}
person PapaDiHatti    schedule 15.05.2018
comment
С инициализацией Aggregate, которая показана в сценарии push_back, нам нужно создать временный объект, который будет перемещен, и с этим подходом к конструктору объект будет создан на месте внутри вектора. - person PapaDiHatti; 15.05.2018
comment
Здесь проверка не будет компилироваться: repl.it/repls/PhysicalFrivolousOctagon - person PapaDiHatti; 15.05.2018

Что вы делаете неправильно, так это пытаетесь передать 4 случайные переменные в push_back, который на самом деле принимает только одну, и эта имеет тип значения вектора.

Kitchen k; 
myFile >> k.price >> k.name >> k.manufacturer >> k.color;
Kitchens.push_back(k);
person acraig5075    schedule 15.05.2018

push_back берет Kitchen. Код предоставляет части файла Kitchen. Попробуйте emplace_back или создайте временный экземпляр Kitchen для перехода в push_back.

person user4581301    schedule 15.05.2018

Сделаем это правильно.

Начиная с заголовка, не включайте больше определений, чем необходимо для этого заголовка, и не импортируйте все идентификаторы из std в глобальное пространство имен.

#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}
    {}
};

Я добавил простой конструктор, так как он понадобится нам позже для emplace_back.

Теперь реализуйте main(). Для воспроизводимого примера лучше читать из потока строк, чем возиться с файлами:

#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";
}

Обратите внимание, что !eof() не гарантирует, что чтение будет успешным. Вместо этого мы пытаемся прочитать, а затем проверяем, находится ли входной поток в состоянии сбоя. После цикла мы могли бы (если бы захотели) на самом деле проверить, что мы достигли конца файла, а не какое-то условие отказа - я опустил это для этой простой программы.

person Toby Speight    schedule 15.05.2018