Для циклов и ввода данных? - PullRequest
1 голос
/ 28 марта 2012

пытаюсь выяснить, как сделать небольшую программу инвентаризации, и я не могу на всю жизнь понять, почему она не работает.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

struct record
{
    int item_id;
    string item_type;
    int item_price;
    int num_stock;
    string item_title;
    string item_author;
    int year_published;
};

void read_all_records(record records[]);
const int max_array = 100;
int main()
{
    record records[max_array];
    read_all_records(records);

    cout << records[2].item_author;
    return 0;
}

void read_all_records(record records[])
{
    ifstream invfile;
    invfile.open("inventory.dat"); 
    int slot = 0;
    for (int count = 0; count<max_array; count++);
    {
        invfile >> records[slot].item_id >> records[slot].item_type >> records[slot].item_price >> records[slot].num_stock >> records[slot].item_title >> records[slot].item_author >> records[slot].year_published;
        slot++;
    }
    invfile.close();

}

Я проверяю ее, распечатываяВторой пункт из записи автора.Когда я запускаю его, он вообще не показывает имя автора.Файл .dat находится практически в каждой папке, где находится проект (я забыл, в какой папке он должен быть), поэтому он там.Проблема не в том, что файл не работает.Массив ничего не печатает.Мой inv файл в основном:

123456 книга 69.99 16 название и т. д. и т. д.

и повторяется для разных книг / компакт-дисков и т. д. все в одной строке, без пробелов.Должен просто следующий.

Ответы [ 3 ]

0 голосов
/ 28 марта 2012

Добавьте небольшой чек:

 if (!invfile.is_open()) {
  cout<<"file open failed";
  exit(1);
 }

Таким образом, вам не нужно копировать входной файл везде, как вы делаете сейчас ;-) Вы читаете в определенном порядке, поэтому ваш вводФайл должен иметь тот же порядок и требуемое количество входов.

Вы печатаете 3-й элемент записи структуры.Таким образом, вы должны иметь как минимум 3 записи.Я не вижу ничего плохого в вашем коде.Было бы намного проще, если бы вы могли опубликовать свой образец входного файла.

0 голосов
/ 28 марта 2012

Если бы я делал это, я думаю, я бы структурировал это немного по-другому.

Во-первых, я бы перегрузил operator>> для record:

std::istream &operator>>(std::istream &is, record &r) { 
    // code about like you had in `read_all_records` to read a single `record`
    // but be sure to return the `stream` when you're done reading from it.
}

Тогда я бы использовал std::vector<record> вместо массива - он гораздо менее подвержен ошибкам.

Чтобы прочитать данные, я бы использовал std::istream_iterator s, вероятно, предоставив их конструктору для vector<record>:

std::ifstream invfile("inventory.dat");

std::vector<record> records((std::istream_iterator<record>(invfile)),
                             std::istream_iterator<record>());

Между ними (т. Е. После создания файла, но перед вектором) находится место, где вы вставляете обработку ошибок, примерно в порядке, рекомендованном @Tom Kerr - проверки для is_open(), bad() , eof() и т. Д., Чтобы выяснить, что (если что-то) идет не так при попытке открыть файл.

0 голосов
/ 28 марта 2012

Вы должны убедиться, что файл открыт.

invfile.open("inventory.dat"); 
if (!invfile.is_open())
  throw std::runtime_error("couldn't open inventory file");

Вы должны убедиться, что чтение вашего файла работает и прерывается при достижении конца файла.

invfile >> records[slot].item_id >> records[slot].item_type ...
if (invfile.bad())
  throw std::runtime_error("file handling didn't work");
if (invfile.eof())
  break;

Возможно, вы хотите прочитать каждую запись за раз, поскольку из этого кода неясно, как потоки C ++ должны различать каждое поле.

Обычно вы ожидаете использовать std::getlineразделите поля на разделители, а затем используйте что-то вроде boost::lexical_cast для анализа типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...