0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
1

Работа с бинарными файлами (программка дважды записывает последнее число)

09.03.2013, 22:54. Показов 1487. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, помогите пожалуйста с такой ситуацией:
написал програмку для заполнения бинарного файла рандомными числами (их количество вводится в начале программы):
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
#include <iostream>
#include <fstream>
#include <time.h>
using namespace std;
 
void random(int N){
    ofstream file("resource.bin", ios::binary|ios::out);
    srand(time(NULL));
    int digit;
    for(int i = 1;i <= N;i++){
        digit = +60-rand()%100;
        file.write((char*)&digit, sizeof digit);
    }
    file.close();
}
 
int main(int argc, char *argv[]){
    setlocale(LC_ALL, "Russian");
    int N;
    cout << "Число чисел  в файле: ";
    cin >> N;
    random(N);
    system("PAUSE");
    return 0;
}
решил проверить содержимое созданного файла и столкнулся с проблемой, которую так и не решил. Суть её в том, что программка дважды записывает последнее число. Например: -36 34 -17 38 -21 -38 -38.
Код программы которой я проверяю файл:
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
#include <iostream>
#include <fstream>
using namespace std;
 
int readFile(string name){
    ifstream file(name, ios::binary|ios::in);
    ofstream tmp("tmp", ios::binary|ios::out);
    int digit;
    if(file.is_open()){ 
        while(!file.eof()){
            file.read((char*)&digit, sizeof digit);
            cout << digit << " ";
        }
        cout << endl;
    }
    file.close();
            return 0;
}
 
int main(int argc, char *argv[]){
    setlocale(LC_ALL, "Russian");
             readFile("resource.bin");
    system("PAUSE");
    return 0;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.03.2013, 22:54
Ответы с готовыми решениями:

Работа с бинарными файлами, параметры функции fseek: вывести на экран пятое по счету число
Вот имеется файл,в котором содержатся 7 вещественных чисел 1.03 2.07 4.015 2.38 5.78 9.34 8.41 ...

При вводе из файла последнее число читается дважды
Делаю вот такую несложную функцию. Считываю из файла числа, помещаю их в массив чисел и вывожу на...

Работа с бинарными файлами
Добрый день, нужно реализовать метод который будет заносить рандомную матрицу(двумерный массив) в...

Работа с бинарными файлами
Всем привет, дали задание Дано целое число K и файл, содержащий неотрицательные целые числа....

17
3528 / 2686 / 334
Регистрация: 11.03.2009
Сообщений: 6,168
09.03.2013, 23:43 2
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
Суть её в том, что программка дважды записывает последнее число.
А Вы уверены, что записывает? Может считывает?
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
while(!file.eof()){
file.read((char*)&digit, sizeof digit);
cout << digit << " ";
}
Дабы никаких чудес не возникало, проверку на конец файла следует делать непосредственно после чтения из файла, а не до него.
0
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 13:58  [ТС] 3
Я вот тоже пришел к выводу что считывает неправильно, но даже с циклом с постусловием чуда не произошло
0
3528 / 2686 / 334
Регистрация: 11.03.2009
Сообщений: 6,168
10.03.2013, 14:10 4
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
C++
1
2
3
4
while(!file.eof()){
* * * * * * file.read((char*)&digit, sizeof digit);
* * * * * * cout << digit << " ";
* * * * }
C++
1
2
3
4
5
6
7
8
while (1)
{
   file.read((char*)&digit, sizeof(digit);
   if (file.eof())
      break;
   else
      cout << digit << " ";
}
Добавлено через 2 минуты
Хотя здесь можно элегантнее, учитывая, что read возвращает количество считанных блоков
C++
1
2
while (file.read((char*)&digit, sizeof(digit)))
   cout << digit << " ";
1
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 14:22 5
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
Я вот тоже пришел к выводу что считывает неправильно, но даже с циклом с постусловием чуда не произошло
И не произойдёт, потому что до проверки условия будет вывод cout, а считался конец файла, поэтому в digit ничего не поместилось (осталось старое значение, которое и выведется второй раз).
1
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 16:32  [ТС] 6
ЯснопонятноВсем спасибо

Добавлено через 24 минуты
Теперь запара с записью/чтением структур из бинарного файла
Заполняю файл этим:
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
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
struct MyStruct
{
    string name;
    int age;
};
 
int main(){
    ofstream file("resource.bin", ios::binary|ios::out);
    MyStruct im;
    string name;int age;
    cin >> name;
    im.name = name;
    cin >> age;
    im.age = age;
    file.write((char*)&im, sizeof(im));
    file.close();
    system("PAUSE");
    return 0;
}
Читаю этим:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
struct MyStruct
{
    string name;
    int age;
};
 
int main(){
    ifstream file("resource.bin", ios::binary|ios::in);
    MyStruct im;
    if(file.is_open())
        file.read((char*)&im, sizeof(im));
    else cout << "err" << endl;
    cout << im.name << " " << im.age << endl;
    system("PAUSE");
    return 0;
}
Все работает (вторая программа считывает структуру и выводит на экран), но перед выходом она вылетает (появляется окошко "Прекращена работа програмы..."). В чем мой косяк?
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
10.03.2013, 16:34 7
Считывайте из файла каждое поле по отдельности.

P.S. И это только во-первых
0
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 16:40  [ТС] 8
Не помогло
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 16:55 9
Зачем вам тут бинарное чтение / запись? Используйте обычное (getline(), cin >>, cout <<). У вас в структуре объект string. Вы бинарно записываете память под структурой в файл. Что там записывается вообще не известно.

Добавлено через 3 минуты
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
Не помогло
Покажите как делаете.
0
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 17:06  [ТС] 10
Само задание выглядит так:
Расписание движение поездов хранится в бинарном файле и содержит информацию: пункт назначения, номер поезда, тип поезда, время отправления, время в пути. Вывести сведения о поездах, следующих в Москву в определенный временной период. Считать данные из файла в односвязный линейный список. Найти поезд определенного типа, доезжающий до Москвы за наименьшее время. Выяснить, какие поезда отправляются после 22 часов.

Написал, но считывал из текстового файла, а теперь из бинарного пытаюсь
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
10.03.2013, 17:08 11
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
Не помогло
Ну если Вы продолжили делать так:
C++
1
file.read((char*)&im.name, sizeof(im.name));
то естественно, что не помогло
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 17:31 12
Проблема в том, что когда вы бинарно записываете в файл память под объектом string, то не понятно, что записывается (зависит от реализаци string). Может там указатель на строку, которая находится совсем в другом месте. Записали вы это указатель в файл. Потом считали его и пытаетесь через него что-то вывести. Отладчиком, ради интереса, посмотрите, что у вас в name перед выводом находится.
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
10.03.2013, 17:34 13
Цитата Сообщение от alsav22 Посмотреть сообщение
Потом считали его
Считали куда? Вникуда. Никто не выделял память под символы в im.name
0
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 17:36  [ТС] 14
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
struct MyStruct
{
    string name;
    int age;
};
 
int main(){
    ifstream file("resource.bin", ios::binary|ios::in);
    MyStruct im;
    if(file.is_open()){
        file.read((char*)&im.name, sizeof(im.name));
        file.read((char*)&im.age, sizeof(im.age));
    }else cout << "err" << endl;
    cout << im.name << " " << im.age << endl;
    system("PAUSE");
    return 0;
}
Добавлено через 1 минуту
То есть лучше отказаться от класса string?
0
Croessmah
10.03.2013, 17:39
  #15

Не по теме:

Цитата Сообщение от Plu6e4ka Посмотреть сообщение
То есть лучше отказаться от класса string?
научится с ним работать.

1
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 17:40  [ТС] 16
Ок
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 18:56 17
Plu6e4ka, в какой среде делаете?

Добавлено через 52 минуты
Как-то так:
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
 
struct MyStruct
{
    string name;
    int age;
};
 
int main()
{
    MyStruct im;
    
    cin >> im.name;
    cin >> im.age;
    
    ofstream fout("resource.bin", ios::binary | ios::out);
    int size_name = im.name.size();
    // первым в файл записываем размер строки (количество символов)
    fout.write((const char*)&size_name, sizeof(size_name));
    // потом символы строки
    fout.write(im.name.c_str(), size_name);
    
    fout.write((const char*)&im.age, sizeof(im.age));
    fout.close();
    
    MyStruct im2;
    
    ifstream fin("resource.bin", ios::binary | ios::in);
    if(fin.is_open())
    {
        // читаем размер строки (количество символов записанных в файл)
        int size_name;
        fin.read((char*)&size_name, sizeof(size_name));
        
        // выделяем память под строку
        im2.name.resize(size_name);
        
        // читаем символы строки
        fin.read((char*)im2.name.c_str(), size_name);
        
        fin.read((char*)&im2.age, sizeof(im2.age));
        fin.close();
    }
    else cout << "err" << endl;
    
    cout << im2.name << " " << im2.age << endl;
    
    system("PAUSE");
    return 0;
}

Но, по моему, бинарно записывать объекты string в файл, не есть хорошо.
0
3528 / 2686 / 334
Регистрация: 11.03.2009
Сообщений: 6,168
10.03.2013, 19:51 18
Plu6e4ka, если хотите string, сначала придется разобраться с понятиями POD-структура неPOD-структура и открыть новый термин - сериализация данных
0
10.03.2013, 19:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.03.2013, 19:51
Помогаю со студенческими работами здесь

Работа с бинарными файлами
Всем доброго времени суток. Столкнулся с такими проблемами: 1. Немогу переобразовать...

Работа с бинарными файлами
Помогите пожалуйста, уже перерыла все книги и весь инет, и чего-либо понятного мне не нашла..((...

Работа с бинарными файлами
Хелпаните плз. Вот само задание. Матрицу А действительных чисел размерности M*N (M&lt;N) и вектор...

Работа с бинарными файлами
Вот проблемный код: if ($fd = fopen($f, &quot;rb&quot;)) { $temp = tmpfile(); while ( !feof($fd) ) { ...

Работа с бинарными файлами
Написать программу для обработки информации о планшетах. Информация включает следующие данные: -...

Работа с бинарными файлами
Доброго времени суток всем! Есть задача с помощью скрипта взять другой скрипт и сохранить его в...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru