Форум программистов, компьютерный форум CyberForum.ru

Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна - C++

Восстановить пароль Регистрация
 
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 01:40     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #1
Имеется задачка:
Написать программу которая будет записывать бинарные данные в файл, а так-же строковые данные типа std::string, считывать их обратно. Функции write() и read()

решил вот так..
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
 
struct person {
    std::string name; //имя
    int age;          //возраст
    double height;    //рост
};
const char *file = "d://person.max";
 
int main() {
    setlocale(0, "");
    person ps;
    std::ifstream fin;
    std::ofstream fout;
        //показывает содержимое файла при старте
    fin.open(file, std::ios_base::in | std::ios_base::binary);
    if (fin.is_open()) {
        std::cout << "Данные в файле \"person.max\":\n";
        unsigned int kol = 0;
        while (fin.read((char *)&ps, sizeof(ps))) {
            std::cout << kol + 1 << ") " << ps.name 
                << ", возраст " << ps.age 
                << ", рост " << ps.height << '\n';
            kol++;
        }
        fin.close();
    }
    //добавление данных в файл
    fout.open(file, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
    if (!fout.is_open()) {
        std::cerr << "ERROR\n";
        exit(EXIT_FAILURE);
    }
    std::cout << "Введите имя (пустая строка для выхода):\n";
    int i = 0;
    std::getline(std::cin, ps.name);
    while (ps.name.size() > 0) {
        std::cout << "Введите возраст: ";
        std::cin >> ps.age;
        std::cout << "Введите рост: ";
        std::cin >> ps.height;
        fout.write((char *)&ps, sizeof(ps));
        std::cout << "Введите имя (пустая строка для выхода):\n";
        i++;
        std::getline(std::cin, ps.name);
    }
    fout.close();
        //показывает модифицированный файл
    fin.open(file, std::ios_base::in | std::ios_base::binary);
    if (fin.is_open()) {
        std::cout << "Новые данные в файле:\n";
        unsigned int kol = 0;
        while (fin.read((char *)&ps, sizeof(ps))) {
            std::cout << kol + 1 << ") " << ps.name 
                << ", возраст " << ps.age << 
                ", рост " << ps.height << '\n';
            kol++;
        }
        fin.close();
    }
    system("pause");
    return 0;
}
Проблема в том, что программа вроде и работает, а вроде и нет.. Крашится при закрытии консольного окна.. может кто чем просветит?
Спасибо.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.09.2014, 01:40     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна
Посмотрите здесь:

чтение бинарных файлов C++
Чтение\запись файлов C++
C++ чтение/запись файлов
C++ Чтение бинарных файлов
C++ Чтение бинарных файлов
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 02:02     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #2
Структуры с такими полями (string) не годятся для записи бинарным методом (write) в файл.
Запись и чтение структуры с файла
Сначала читаете из файла, а потом записываете в файл? Это как?
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 08:47  [ТС]     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #3
alsav22, ну если файл еще не создан, то и не читается ничего.
Окей, проблему, кажется понял, я так понимаю, мне придется в два потока записывать данные в файл, string в текстовом виде и остальное в бинарном? Или есть какое то другое решение задачки?
Ilot
Модератор
Эксперт С++
1767 / 1142 / 223
Регистрация: 16.05.2013
Сообщений: 3,020
Записей в блоге: 5
Завершенные тесты: 1
08.09.2014, 08:56     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #4
Цитата Сообщение от trev Посмотреть сообщение
Окей, проблему, кажется понял, я так понимаю, мне придется в два потока записывать данные в файл, string в текстовом виде и остальное в бинарном? Или есть какое то другое решение задачки?

Все значительно проще. В классе string есть метод c_str который возвращает си строку. Вот и пишите ее в файл. Только не забудте поместить в файл информацию о длине этой строки.
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 14:43  [ТС]     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #5
Ilot, Мы не ищем легких путей
а вообще, инфу принял, буду разбираться
всем спс <3

Добавлено через 5 часов 8 минут
Выручайте
С записью в файл, вроде, все ок..
а вот с чтением из файла проблемы =\
P.S. Переделал под ООП.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//Person.h
#include <string>
#include <iostream>
#include <fstream>
#include <cstring>
#pragma warning(disable : 4996)
 
const char *file = "d://person11.bin";
 
class Person {
    std::string name;
    int age;
    double height;
public:
    //конструкторы
    explicit Person(const std::string &name_, int age_, double height_)
        : name(name_), age(age_), height(height_) { }
    Person(const Person &ps) 
        : name(ps.name), age(ps.age), height(ps.height) { }
    //методы bin_write и bin_read
    void bin_write() {
        std::ofstream fout(file, 
            std::ios_base::out | std::ios_base::app | std::ios_base::binary);
        if (!fout.is_open()) {
            std::cerr << "ERROR\n";
            exit(EXIT_FAILURE);
        }
        else {
            char *cstr = new char[name.length() + 1];
            std::strcpy(cstr, name.c_str());
            fout.write((char *)&cstr, sizeof(cstr));
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            delete[] cstr;
            fout.close();
        }
    }
    void bin_read() {
        std::ifstream fin;
        fin.open(file, std::ios_base::in | std::ios_base::binary);
        if (fin.is_open()) {
            std::cout << "Данные в файле \"person2.max\":\n";
            unsigned int kol = 0;
            char *cstr = new char[name.length() + 1];
            while (!fin.eof()) {
                fin.read((char *)&cstr, sizeof(cstr) * CHAR_BIT);
                std::cout << kol + 1 << ") " << cstr;
                fin.read((char *)&age, sizeof(age));
                std::cout << ", возраст " << age;
                fin.read((char *)&height, sizeof(height));
                std::cout << ", рост " << height << '\n';
                kol++;
            }
            fin.close();
        }
    }
    //деструктор
    ~Person() { }
};
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 17:11     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #6
Цитата Сообщение от trev Посмотреть сообщение
ну если файл еще не создан, то и не читается ничего.
Ну, да. Это я туплю.
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 17:19  [ТС]     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #7
нашел на форуме такой вот пост по теме..
Цитата Сообщение от I.M. Посмотреть сообщение
...или извращаться с бинарным файлом и строкой дальше)
при записи данных в файл - перед каждой строкой надо вначале записывать ее длину, а затем только само содержимое строки. также надо использовать не sizeof(std::string), а вызывать метод size() у этой строки.
при чтении из файла - вначале считываете длину будущей строки, создаете временный массив char* соответствующей длины, в него считываете данные из файла и только потом переносите этот массив в нужную std::string...
То есть с записью в файл я, кажется, разобрался :
C++
1
2
3
4
5
6
7
char *cstr = new char[name.length() + 1];
            std::strcpy(cstr, name.c_str());
            fout.write((char *)&cstr, name.size());
            delete[] cstr;
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            fout.close();
а вот с чтением вообще туплю дико уже несколько часов к ряду.. Судя по цитате, нужно считать длинну будущей строки.. а вот как это сделать хз.. =\
пока есть вот такой код по чтению из файла, но он не работает
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
std::cout << "Данные в файле \"" << file << "\":\n";
            unsigned int kol = 0;
            while (!fin.eof()) {
                char *cstr = new char[name.length() + 1];
                fin.read((char *)&cstr, name.size());
                std::cout << kol + 1 << ") " << cstr;
                fin.read((char *)&age, sizeof(age));
                std::cout << ", возраст " << age;
                fin.read((char *)&height, sizeof(height));
                std::cout << ", рост " << height << '\n';
                kol++;
            }
            fin.close();
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 17:27     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #8
Вот это неправильно:
C++
1
fout.write((char *)&cstr, sizeof(cstr));
sizeof() выдаст размер указателя, а не размер массива.
Вижу, что нашли правильный вариант.

Добавлено через 3 минуты
Цитата Сообщение от trev Посмотреть сообщение
То есть с записью в файл я, кажется, разобрался :
Не вижу записи в файл длины строки.

Добавлено через 4 минуты
Вот это неправильно:
C++
1
2
char *cstr = new char[name.length() + 1];
fin.read((char *)&cstr, name.size()); // !!! просто cstr
Сначала нужно прочитать из файла длину строки (сначала, естественно, записать её туда). Потом создать массив нужного размера, потом прочитать туда саму строку. И не нужно брать адрес у указателя - &cstr, просто cstr (это и так адрес).
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 17:32  [ТС]     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #9
alsav22,
теперь правильно записываю файл?
C++
1
2
3
4
5
6
7
8
9
10
char *cstr = new char[name.length() + 1];
            std::strcpy(cstr, name.c_str());
            unsigned int *len = new unsigned int(name.length() + 1);
            fout.write((char *)len, sizeof(len));
            fout.write((char *)cstr, name.size());
            delete[] cstr;
            delete[] len;
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            fout.close();
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
08.09.2014, 18:28     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #10
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от trev Посмотреть сообщение
теперь правильно записываю файл?
Я бы так сделал:
C++
1
2
3
4
5
6
    int length = name.size();
    fout.write((char *)&length, sizeof(length)); // записываем размер строки
    fout.write((char *)name.c_str(), name.size()); // записываем строку
    fout.write((char *)&age, sizeof(age));
    fout.write((char *)&height, sizeof(height));
    fout.close();
Добавлено через 26 минут
Тогда чтение строки, как-то так будет (в итерации):
C++
1
2
3
4
5
6
7
        int length;
        fin.read((char *)&length, sizeof(length)); // читаем размер строки
        char* cstr = new char[length + 1]; // массив под строку
        fin.read((char *)cstr, length); // читаем строку
        cstr[length] = '\0'; // делаем из массива Си строку
        name = cstr; // заносим массив в string 
        delete [] cstr;
Добавлено через 11 минут
И ещё... Чтобы избежать пустого чтения (когда EOF уже считан, а итерация ещё не закончена), проверку на EOF нужно сделать после считывания размера строки.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.09.2014, 20:14     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна
Еще ссылки по теме:

Запись бинарных файлов C++
Крашится программа при попытке присваивания значения элементу дин-го массива C++
C++ Программа крашится при вводе данных

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
08.09.2014, 20:14  [ТС]     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна #11
Цитата Сообщение от alsav22 Посмотреть сообщение
int length = name.size();
здесь точно все правильно? не
C++
1
length = name.length()
Добавлено через 7 минут
сори, туплю.. это одно и тоже..)

Добавлено через 1 час 6 минут
Выкладываю готовый вариант, может кому пригодится
Благодарю за помощь!
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//определение класса
//person.h
#include <string>
#include <iostream>
#include <fstream>
 
#ifndef PERSON_H_
#define PERSON_H_
 
 
const char *file = "d://person.bin";
 
class Person {
    std::string name;
    int age;
    int height;
public:
    //конструкторы
    Person() 
        : name("nobody"), age(0), height(0) { }
    Person(const std::string &name_, int age_ = 0, int height_ = 0)
        : name(name_), age(age_), height(height_) { }
    Person(const Person &ps)
        : name(ps.name), age(ps.age), height(ps.height) { }
    //методы bin_write и bin_read
    void bin_write() const {
        std::ofstream fout(file,
            std::ios_base::out | std::ios_base::app | std::ios_base::binary);
        if (!fout.is_open()) {
            std::cerr << "ERROR\n";
            exit(EXIT_FAILURE);
        }
        else {
            unsigned int len = name.size();
            fout.write((char *)&len, sizeof(len));          //записываем длину строки
            fout.write((char *)name.c_str(), name.size());  //записываем строку
            fout.write((char *)&age, sizeof(age));
            fout.write((char *)&height, sizeof(height));
            fout.close();
        }
    }
    void bin_read() {
        std::ifstream fin;
        fin.open(file, std::ios_base::in | std::ios_base::binary);
        if (fin.is_open()) {
            std::cout << "Данные в файле \"" << file << "\":\n";
            unsigned int kol = 1;
            do {
                int len;
                fin.read((char *)&len, sizeof(len));
                if (fin.eof())
                    break;
                char *cstr = new char[len + 1];
                fin.read((char *)cstr, len);
                cstr[len] = '\0';
                name = cstr;
                delete[] cstr;
                fin.read((char *)&age, sizeof(age));
                fin.read((char *)&height, sizeof(height));
                std::cout << kol << ") " << name
                    << ", возраст: " << age
                    << ", рост: " << height << '\n';
                kol++;
            } while (fin.good());
            fin.close();
        }
    }
    //деструктор
    ~Person() { }
};
#endif // !PERSON_H_
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//main.cpp
#include "stdafx.h"
#include "Person.h"
#include "ctime"
 
int main() {
    setlocale(0, "");
    std::srand(time(NULL));
    Person *man = new Person[4];
    man[0] = Person("Maks", 15 + rand() % 20, 120 + rand() % 100);
    man[1] = Person("Stas", 15 + rand() % 20, 120 + rand() % 100);
    man[2] = Person("Rost", 15 + rand() % 20, 120 + rand() % 100);
    man[3] = Person("Volod'ka", 20 + rand() % 30, 120 + rand() % 100);
    for (int i = 0; i < 4; i++) {
        man[i].bin_write();
        if (i == 3)
            man[i].bin_read();
    }
    system("pause");
    return 0;
}
Yandex
Объявления
08.09.2014, 20:14     Запись и чтение бинарных файлов. Программа крашится при закрытии консольного окна
Ответ Создать тему
Опции темы

Текущее время: 02:48. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru