Почему размер моего вектора, полного структур, такой большой, когда я загружаю его сериализацию из файла? - PullRequest
1 голос
/ 02 апреля 2009

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

Файл, в который я загружаюсь, пуст. Моя программа загружается примерно за 10 секунд, и теперь я знаю почему. Это потому, что размер моего вектора равен 250 тысячам. Ой, подождите ... на этот раз я запустил его, размер моего вектора был 5 172 285. Это довольно большой вектор, полный структур. Нет ошибок во время выполнения или компиляции, но я уверен, что делаю что-то не так. Файл, в который я загружаю, тоже полностью пуст.

Код:

// Project 5.cpp : main project file.

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

using namespace System;
using namespace std;
#pragma hdrstop

int checkCommand (string line);

template<typename T>
void writeVector(ofstream &out, const vector<T> &vec);

template<typename T>
vector<T> readVector(ifstream &in);

struct InventoryItem {
    string Item;
    string Description;
    int Quantity;
    int wholesaleCost;
    int retailCost;
    int dateAdded;
} ;


int main(void)
{
    cout << "Welcome to the Inventory Manager extreme! [Version 1.0]" << endl;
    ifstream in("data.dat");
    if (in.is_open()) { cout << "File \'data.dat\' has been opened successfully." << endl; } else { cout << "Error opening data.dat" << endl; return 0;}
    cout << "Loading data..." << endl;
    vector<InventoryItem> structList = readVector<InventoryItem>( in );
    cout <<"Load complete." << endl;

    while (1)
    {

        string line = "";
        cout << "There are currently " << structList.size() << " items in memory.";
        cout << endl;
        cout << "Commands: " << endl;
        cout << "1: Add a new record " << endl;
        cout << "2: Display a record " << endl;
        cout << "3: Edit a current record " << endl;
        cout << "4: Exit the program " << endl;
        cout << endl;
        cout << "Enter a command 1-4: ";

        getline(cin , line);


        int rValue = checkCommand(line);
        if (rValue == 1)
        {
            cout << "You've entered a invalid command! Try Again." << endl;
        } else if (rValue == 2){ 
            cout << "Error calling command!" << endl;
        } else if (!rValue) {
            break;
        }
    }


    system("pause");

    return 0;
}

int checkCommand (string line)
{
    int intReturn = atoi(line.c_str());
    int status = 3;

    switch (intReturn)
    {
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;
        case 4:
            status = 0;
            break;
        default:
            status = 1;
            break;
    }
    return status;
}

template<typename T>
void writeVector(ofstream &out, const vector<T> &vec)
{
    out << vec.size();

    for(vector<T>::const_iterator i = vec.begin(); i != vec.end(); i++)
    {
        out << *i;
    }
}

ostream &operator<<(ostream &out, const InventoryItem &i)
{
    out << i.Item << i.Description;
    out << i.Quantity;
    out << i.wholesaleCost << i.retailCost;
    out << i.dateAdded;
    return out;
}

istream &operator>>(istream &in, InventoryItem &i)
{
    in >> i.Item >> i.Description;
    in >> i.Quantity;
    in >> i.wholesaleCost >> i.retailCost;
    in >> i.dateAdded;
    return in;
}



template<typename T>
vector<T> readVector(ifstream &in)
{
    size_t size;
    in >> size;

    vector<T> vec;
    vec.reserve(size);

    for(unsigned int i = 0; i < size; i++)
    {
        T tmp;
        in >> tmp;
        vec.push_back(tmp);
    }

    return vec;
}

Может кто-то просто показать мне, как превратить это в программу, которая может записать в файл сериализованные векторы, полные структур, а затем прочитать их обратно, чтобы я мог отредактировать их и сохранить их для последующей загрузки? О, боже мой, что это была за поездка!

СПАСИБО за любую помощь, которую вы можете оказать!

Ответы [ 4 ]

5 голосов
/ 02 апреля 2009

Вы говорите, что файл на самом деле пуст. Первая строка в readVector выглядит так:

in >> size;

Как вы думаете, что на самом деле закончится в размерах? Так как он пуст, это приведет к ошибке, которую вы не обнаружите. Переменная size останется неинициализированной - следовательно, вы видите странные значения в ней, поскольку она принимает любое значение, которое было в памяти в то время. Вы можете проверить состояние потока, используя проверку:

if (in)

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

3 голосов
/ 02 апреля 2009

Если ваш входной файл пуст, то vector должен быть пустым. Вы не должны идти за черту:

if (in.is_open()) 

- ваша программа (когда я запускаю ее на своем компьютере) закрывается.

Можете ли вы объяснить, почему у вас есть следующее?

#include <String>

using namespace System;

#pragma hdrstop

Самым простым для реализации является чтение содержимого файла за один раз, сохранение элементов в памяти, редактирование их в памяти и запись в файл один раз при редактировании. Это, конечно, не очень хорошая техника с точки зрения памяти или производительности. Но проблема, которую вы пытаетесь решить, не является тривиальной. Прочитайте FAQ 36 , чтобы лучше понять свою задачу.

3 голосов
/ 02 апреля 2009

Итак, если ваш файл пуст и вы делаете:

size_t size;
in >> size;

vector<T> vec;
vec.reserve(size);

Как вы думаете, что произойдет? Размер не может быть прочитан и использует случайное значение

0 голосов
/ 02 апреля 2009

Вы используете пустые файлы, но когда вы загружаете файл, вы ищете размер. Если файл не имеет размера в файле, вы можете получить мусор в вашу переменную размера.

Итак, попытка поставить ноль в первой строке файла «data.dat».

Edit: Вышеупомянутое предложение было только временным исправлением. Вы можете попробовать это:

in >> size;
//input operation failed
if(in.fail())
    //return, or whatever you need to do
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...