Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18

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

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

Студворк — интернет-сервис помощи студентам
Добрый день, помогите пожалуйста с такой ситуацией:
написал програмку для заполнения бинарного файла рандомными числами (их количество вводится в начале программы):
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
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.03.2013, 22:54
Ответы с готовыми решениями:

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

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

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

17
 Аватар для kazak
3604 / 2744 / 356
Регистрация: 11.03.2009
Сообщений: 6,306
09.03.2013, 23:43
Цитата Сообщение от 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  [ТС]
Я вот тоже пришел к выводу что считывает неправильно, но даже с циклом с постусловием чуда не произошло
0
 Аватар для kazak
3604 / 2744 / 356
Регистрация: 11.03.2009
Сообщений: 6,306
10.03.2013, 14:10
Цитата Сообщение от 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
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 14:22
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
Я вот тоже пришел к выводу что считывает неправильно, но даже с циклом с постусловием чуда не произошло
И не произойдёт, потому что до проверки условия будет вывод cout, а считался конец файла, поэтому в digit ничего не поместилось (осталось старое значение, которое и выведется второй раз).
1
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 16:32  [ТС]
ЯснопонятноВсем спасибо

Добавлено через 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
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
10.03.2013, 16:34
Считывайте из файла каждое поле по отдельности.

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

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

Написал, но считывал из текстового файла, а теперь из бинарного пытаюсь
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
10.03.2013, 17:08
Цитата Сообщение от Plu6e4ka Посмотреть сообщение
Не помогло
Ну если Вы продолжили делать так:
C++
1
file.read((char*)&im.name, sizeof(im.name));
то естественно, что не помогло
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 17:31
Проблема в том, что когда вы бинарно записываете в файл память под объектом string, то не понятно, что записывается (зависит от реализаци string). Может там указатель на строку, которая находится совсем в другом месте. Записали вы это указатель в файл. Потом считали его и пытаетесь через него что-то вывести. Отладчиком, ради интереса, посмотрите, что у вас в name перед выводом находится.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
10.03.2013, 17:34
Цитата Сообщение от alsav22 Посмотреть сообщение
Потом считали его
Считали куда? Вникуда. Никто не выделял память под символы в im.name
0
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 17:36  [ТС]
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
10.03.2013, 17:39

Не по теме:

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

1
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 18
10.03.2013, 17:40  [ТС]
Ок
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
10.03.2013, 18:56
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
 Аватар для kazak
3604 / 2744 / 356
Регистрация: 11.03.2009
Сообщений: 6,306
10.03.2013, 19:51
Plu6e4ka, если хотите string, сначала придется разобраться с понятиями POD-структура неPOD-структура и открыть новый термин - сериализация данных
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.03.2013, 19:51
Помогаю со студенческими работами здесь

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

Работа с бинарными файлами
Всем доброго времени суток. Столкнулся с такими проблемами: 1. Немогу переобразовать строку(Edit1-&gt;Text) в char* 2. Из файла выводит...

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

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

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


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это дополнительная запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru