Подсчет числа записей в бинарном файле

352
07 марта 2017, 17:01

Подскажите ,пожалуйста,в чем ошибка.

У меня есть три функции: запись в файл,чтение из файла и подсчет записей в файле.

В моей программе 3 аргумента:1й символ,2й количество записей,которые я хочу вывести, и 3й имя файла. Объявление класса:

#pragma once
#include <iostream>
#include <string>
#include "String.h"
#include <fstream>
#include <vector>
#define string String
#define END std::endl

typedef double d;
typedef int i;
class City
{
private:
    string Name;
    i Ppl;
    d Area;
    i Birth;
    i Schools;
    std::ofstream wRecord;
    std::vector<string> lines;
    std::ifstream readRecord;   
public:
    City();
    ~City();
    void showInfo();
    void getData();
    void diskIn(int n,int r );
    void diskOut(int num);
    static int diskCount();
};

Определение методов класса:

#include "City.h"
#include "String.h"
#include <iostream>
#include <fstream>
#include <io.h>

City::City() : Name("NoName"), Ppl(0), Area(0.0), Birth(0), Schools(0)
{}
City::~City()
{
    wRecord.close();
    readRecord.close();
}
void City::showInfo() {
    std::cout << "Name\t\t" << "People\t\t" << "Area\t\t" << "Birth\t\t" << "Schools\t\t" << END;
    std::cout <<""<<Name<<"\t\t" << Ppl<<"\t\t" << Area<<"\t\t" << Birth<<"\t\t" << Schools<< END;
}
void City::getData()
{
        std::cout << "Enter a name of the city:   ";
        (std::cin >> Name).get();
        std::cout << "Enter quanity of people in the city:   ";
        std::cin >> Ppl;
        std::cout << "Enter area of the city:   ";
        std::cin >> Area;
        std::cout << "Enter a year of foundation of the city:   ";
        std::cin >> Birth;
        std::cout << "Enter quanity of schools in the city:   ";
        std::cin >> Schools;
}
void City::diskIn(int n,int r)//Чтение
{
    std::ifstream readRecord;
    readRecord.open("6.bin", std::ios::binary);
    readRecord.seekg(n * sizeof(City));
    std::cout << n << END;
    for (int i = 0; i < r; i++) {
        readRecord.read((char*)this, sizeof(*this));
    }
}

void City::diskOut(int num) //Запись
{
    std::ofstream wRecord;
    wRecord.open("6.bin", std::ios::binary);
    for (int i = 0; i < num; i++) {
        wRecord.write((char*)this, sizeof(*this));
    }
}

int City::diskCount()//Подсчет
{
    std::ifstream readRecord;
    readRecord.open("6.bin", std::ios::binary);
    readRecord.seekg(0, std::ios::end);
    return (int)readRecord.tellg() / sizeof(City);
}

Мой объект:

City c;
    if (argv[1] == create){
        int n = atoi(argv[2]);
        std::cout << "1 " << argv[1] <<"2 "<<argv[2] <<"3 "<<argv[3]<< END;
        for (int j = 0; j < n; j++) {
            c.getData();
            c.diskOut(n);
        }
    }
    if (argv[1] == read) {
        int n = City::diskCount();
        int r = atoi(argv[2]);
        std::cout << "1 " << argv[1] << "2 " << argv[2] << "3 " << argv[3] <<"r"<<n <<END;
        std::cout << "In file: " << n << "cities" << END;
        for (int i = 0; i < n; i++) {
            c.showInfo();
            c.diskIn(i,r);
        }
    }

Моя проблема , в том что, я не могу прочитать из файла записи, срабатывает только конструктор по умолчанию.Проблема явно в diskIn. Нужно читать не весь файл, а определенное количество в нем,если я убираю мои циклы из diskIn и diskOut, то программа, работает,НО читает все.

Я хочу спрашивать у пользователя, сколько он хочет видеть записей, если хочет больше , чем есть в файле, то вывести соответствующее сообщение и тогда уже вывести все записи.А если 2 записи из 3, то вывести ровно 2.

Answer 1

С вашим классом City категорически забудьте о записи/чтении в простом бинарном виде! Писать/читать просто содержимое памяти можно для того, что именуется plain old data, т.е. фундаментальные типы без указателей...

Например, у вас в нем есть поле string Name;. Что вы запишете? Думаете, содержимое Name? Ничуть, посмотрите внутрь файла сами. Там будет записан скорее всего указатель на место в памяти, где находится сама строка. При чтении при том же выполнении вы еще можете указывать на то же место в памяти. Но сохраните файл, а потом прочтите в другой программе - и вы будете иметь не пойми что в не пойми каком месте...

Я уж молчу про вектор строк или поток...

У вас должна быть своя функция, которая правильно пишет каждое поле, и, соответственно, правильно его читает. Каждое. И соответствующая функция чтения.

Например, строку оно пишет как сначала длину, потом указанное в длине количество байт строки. Читает - наоборот: сначала длину, потом выделяет буфер в памяти и читает в него...

Запись в файл и чтение таких вещей, как, например,

std::ofstream wRecord;

вообще не имеет смысла.

И еще в качестве PS - за вот такое

typedef double d;
typedef int i;

равно как и за такое

#define string String

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

for(int i = 0; i < N; ++i) 

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

Еще PPS - зачем вы вообще держите потоки в объекте класса? Какой в этом глубокий смысл? Как минимум вы сами себе обрезаете возможность копирования, но это так, побочный эффект. Разве ГОРОД как таковой содержит какие-то файловые потоки? Даже если не город, а просто объект, - зачем ему содержать файлы, из которых он читается/пишется? Они же по отношению к объекту - внешние сущности...

READ ALSO
Нужна помощь в написании драйвера на C++

Нужна помощь в написании драйвера на C++

Обшарив очень много форумов/сайтов не смог найти ничего полезного по поводу написания драйвера на C++Хочу написать простой драйвер, который...

328
Проверка выхода за пределы вектора

Проверка выхода за пределы вектора

У меня есть вектор с элементамиМне нужно выводить по три элемента

348
MFC, Memory Leak при передаче параметров в поток

MFC, Memory Leak при передаче параметров в поток

День добрыйУже полтора дня пытаюсь разобраться в причинах сообщений об утечках памяти(Memory Leaks Detected

483
Пример lstm нейросети [требует правки]

Пример lstm нейросети [требует правки]

Есть у кого пример lstm сети? На гитхабе не нашел того, что подходит

505