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

Чтение/запись файла - C++

Восстановить пароль Регистрация
 
kebal
9 / 9 / 0
Регистрация: 02.11.2012
Сообщений: 153
20.02.2013, 03:49     Чтение/запись файла #1
Вот сделал такую прогу. Очень простая. Создает файл, где есть 100 полей.
Каждое поле это строка из индекса, названия, кол-ва (например тут инструментов), цены.
например
5 Молоток 10 50.50
И реализовал простенькие методы для работы.
Но почему-то не работает 5 метод. Когда я создаю два объекта
1 молоток 2 4
2 тяпка 6 8
А после этого изменяю кол-во молотков с двух на любое число, которое имеет более одного знака, то это каким-то образом влияет на тяпку и при выводе печатает полный бред. При этом изменение названия молотка либо же цены молотка проходит абсолютно нормально. При этом все эти три метода почти полные копии друг друга и поэтому я вот всё пытаюсь найти где же ошибка. Кто даст ответ или натолкнет проплюсую все ответы в этой теме, слишком уж много кода тут.
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Инвентаризация.cpp: определяет точку входа для консольного приложения.
//
 
#include "stdafx.h"
#include <fstream>
#include <iostream>
using namespace std;
 
struct Instrument {
    int num;
    char instName[30];
    int kolvo;
    double price;
};
 
int getChoice();
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "Russian");
    fstream myFileReader("hardware.dat", ios::in | ios::out);
 
    if (! myFileReader) {
        cerr << "Файл не может быть открыт" << endl;
        system("pause");
        exit(1);
    }
 
    Instrument my = {0, "", 0, 0.0};
 
    for (int i = 0; i < 100; i++) {
        myFileReader.write((char *) &my, sizeof(Instrument));
    }
    myFileReader.flush();
    int choice;
    while ((choice = getChoice()) != 7) {
        switch(choice) {
            //вставляет новый инструмент
        case(1):
            {
                cout << "Введите индекс, название, кол-во, цену. " << endl;
                cin >> my.num >> my.instName >> my.kolvo >> my.price;
                myFileReader.seekg((my.num - 1) * sizeof(Instrument));
                Instrument temp;
                myFileReader.read((char *) &temp, sizeof(Instrument));
                if (temp.num == 0) {
                    myFileReader.seekp((my.num - 1) * sizeof(Instrument));
                    myFileReader.write((char *) &my, sizeof(Instrument));
                    myFileReader.flush();
                }
                else
                    cout << "Данный счёт уже существует!" << endl;
                break;
            }
            //печатает уже введенные инструменты
        case(2):
            {
                cout << "Полный список: " << endl;
                myFileReader.seekg(0);
                myFileReader.read((char *) &my, sizeof(Instrument));
                while (! myFileReader.eof()) {
                    if (my.num != 0) {
                        cout << my.num << ' ' << my.instName << ' ' << my.kolvo << ' ' << my.price << endl;
                    }
                    myFileReader.read((char *) &my, sizeof(Instrument));
                }
                break;
            }
            //удаляет инструмент
        case(3):
            {
                cout << "Введите номер записи, которую вы хотите удалить: " << endl;
                int num;
                cin >> num;
                myFileReader.seekp((num - 1) * sizeof(Instrument));
                Instrument temp = {0, "", 0, 0.0};
                myFileReader.write((char *) &temp, sizeof(Instrument));
                myFileReader.flush();
                break;
            }
            //изменяет имя инструмента
        case(4):
            {
                cout << "Введите номер записи, в которой вы хотите сделать изменение: " << endl;
                int num;
                cin >> num;
                myFileReader.seekg((num - 1) * sizeof(Instrument));
                myFileReader.read((char *) &my, sizeof(Instrument));
                if (my.num == 0) {
                    cout << "Такой записи не существует" << endl;
                    break;
                }
                cout << "Введите новое название: ";
                cin >> my.instName;
                myFileReader.seekp((num - 1) * sizeof(Instrument));
                myFileReader.write((char *) &my, sizeof(Instrument));
                myFileReader.flush();
                break;
            }
            //изменяет кол-во инструментов
        case(5):
            {
                cout << "Введите номер записи, в которой вы хотите сделать изменение: " << endl;
                int num;
                cin >> num;
                myFileReader.seekg((num - 1) * sizeof(Instrument));
                myFileReader.read((char *) &my, sizeof(Instrument));
                if (my.num == 0) {
                    cout << "Такой записи не существует" << endl;
                    break;
                }
                cout << "Введите новое кол-во: ";
                cin >> my.kolvo;
                myFileReader.seekp((num - 1) * sizeof(Instrument));
                myFileReader.write((char *) &my, sizeof(Instrument));
                myFileReader.flush();
                break;
            }
            //изменяет стоимость
        case(6):
            {
                cout << "Введите номер записи, в которой вы хотите сделать изменение: " << endl;
                int num;
                cin >> num;
                myFileReader.seekg((num - 1) * sizeof(Instrument));
                myFileReader.read((char *) &my, sizeof(Instrument));
                if (my.num == 0) {
                    cout << "Такой записи не существует" << endl;
                    break;
                }
                cout << "Введите новую стоимость: ";
                cin >> my.price;
                myFileReader.seekp((num - 1) * sizeof(Instrument));
                myFileReader.write((char *) &my, sizeof(Instrument));
                myFileReader.flush();
                break;
            }
        default:
            cout << "Неправильное число." << endl;
            break;
        };
        //myFileReader.flush();
        myFileReader.clear();
    }
 
    system("pause");
    return 0;
}
 
int getChoice() {
    cout << "Введите число:" << endl
         << "1 для ввода нового инструмента;" << endl
         << "2 для получения всего списка;" << endl
         << "3 для удаления записей;" << endl
         << "4 изменить название;" << endl
         << "5 изменить количество;" << endl
         << "6 изменить стоимость;" << endl
         << "7 для завершения программы;" << endl;
    int choice;
    cin >> choice;
    return choice;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.02.2013, 03:49     Чтение/запись файла
Посмотрите здесь:

Запись и чтение из файла C++
Си, Запись и Чтение из файла. C++
Запись и чтение из файла C++
C++ Запись и чтение из файла
C++ запись\чтение из файла
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
20.02.2013, 05:18     Чтение/запись файла #2
Я такой ошибки не получил, но... Почитайте это: http://www.kalinin.ru/programming/cpp/31_07_00.shtml
http://habrahabr.ru/post/142662/ Размер вашей структуры 46 байт. sizeof(Instrument) показывает у меня - 48. При записи в файл памяти под структурой будут записываться два лишних байта. Поэтому писать в файл нужно именованные поля структуры, а не память под ней(или использовать специальные приёмы для задания выравнивания: Использование #pragma pack(push,1)... pack(pop)). Читать тоже в именованные поля структуры. Потом, непонятна цель первоначальной записи 100 пустых структур в файл.
kebal
9 / 9 / 0
Регистрация: 02.11.2012
Сообщений: 153
20.02.2013, 14:21  [ТС]     Чтение/запись файла #3
Ну 100 пустых структур нужно для того, чтобы например они не по порядку записывались, а чтобы например записать в первую и 53 строку и т.д.

Добавлено через 28 минут
Ещё данную ошибку можно воспроизвести так, например ввести такой инструмент
1 molot 10 5
Важно, чтобы после названия шло число двухзначное.
А затем попробовать ввести инструмент с индексом 2, например
2 tyapka 3 4
Тогда программа напишет, что "Данный счёт уже существует", хотя это не верно.

Добавлено через 33 минуты
Но что если даже размер у него 48 байт? Ведь если я например сделал первую запись, то когда я делаю вторую запись я отступаю ведь тоже 48 байт от начала файла, а не 46. Значит всё должно быть ок.
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 14:22     Чтение/запись файла #4
kebal, прикрепи файл, с которым работает она)
kebal
9 / 9 / 0
Регистрация: 02.11.2012
Сообщений: 153
20.02.2013, 15:13  [ТС]     Чтение/запись файла #5
Это не имеет никакого значения, с каким файлом она работает, ведь при запуске программы содержимое файла очищается.
Вот опять же, использовал
#pragma pack(push, 1)
struct Instrument {
...
};
#pragma pack(pop)
Теперь sizeof(Instrument) даёт 46.
И теперь опять если первая запись в виде
1 molot 10 5
то вторая запись уже выдаёт "Данный счёт уже существует".
То есть хоть с использование #pragma pack хоть без первая запись залазит на вторую не понятно почему.

Добавлено через 2 минуты
А что ещё более занимательно, так это при вводе нового инструмента там стоит условие
C++
1
2
3
if (my.num == 0) {
   //сделать запись
}
при печати стоит обратное условие
C++
1
2
3
if (my.num != 0) {
  //напечатать информацию об этом объекте
}
Но при этом оба дают условие false. При этом состояние объекта в первом и втором случае не изменялось...

Добавлено через 34 минуты
в чём может быть проблема?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
20.02.2013, 15:18     Чтение/запись файла #6
Цитата Сообщение от kebal Посмотреть сообщение
в чём может быть проблема?
C++
1
fstream myFileReader("hardware.dat", ios::in | ios::out | ios::binary);
kebal
9 / 9 / 0
Регистрация: 02.11.2012
Сообщений: 153
20.02.2013, 15:45  [ТС]     Чтение/запись файла #7
Кстати с ios::binary работает и без #pragma pack. То, о чём я и говорил, просто отступает не 46, а 48 байтов, разве что просто режим был текстовый, потому и не работало.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
20.02.2013, 15:51     Чтение/запись файла #8
Цитата Сообщение от kebal Посмотреть сообщение
Кстати с ios::binary работает и без #pragma pack. То, о чём я и говорил, просто отступает не 46, а 48 байтов, разве что просто режим был текстовый, потому и не работало.
Не работало, мотому что код кривой. Совет, насчёт записи-чтения структур остаётся в силе. #pragma pack это для windows. Писать в файл неизвестно что, не есть Ок.
kebal
9 / 9 / 0
Регистрация: 02.11.2012
Сообщений: 153
20.02.2013, 15:55  [ТС]     Чтение/запись файла #9
Всмысле "не работало, потому что код кривой"? Я поставил ios::binary и всё теперь работает, значит дело было только в этом. И почему писать в файл неизвестно что? В первой статье, на которую ты дал ссылку очень хорошо написано, почему например получилось не 46, а 48 байт. И опять же, если использовать #pragma pack, то ты разве что уменьшаешь кол-во отступов внутри файла, сокращая его размер. И "тогда был бред", а "сейчас не бред, так как уменьшили кол-во пробелов" как-то не очень стыкуется.
Van111
кодер с++
208 / 187 / 4
Регистрация: 03.08.2011
Сообщений: 2,585
Записей в блоге: 12
20.02.2013, 15:57     Чтение/запись файла #10
kebal, используйте контейнер map , используйте класс который бы отвечал за хранение и операции над товарами
kebal
9 / 9 / 0
Регистрация: 02.11.2012
Сообщений: 153
20.02.2013, 16:02  [ТС]     Чтение/запись файла #11
Van111, я всего-лишь учился работать с файлами и я должен был понять почему происходит какая-либо ошибка.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.02.2013, 16:04     Чтение/запись файла
Еще ссылки по теме:

Запись и чтение из файла C++
C++ Запись и чтение с файла
C++ Запись и чтение из файла

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

Или воспользуйтесь поиском по форуму:
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
20.02.2013, 16:04     Чтение/запись файла #12
Цитата Сообщение от kebal Посмотреть сообщение
Всмысле "не работало, потому что код кривой"? Я поставил ios::binary и всё теперь работает, значит дело было только в этом. И почему писать в файл неизвестно что? В первой статье, на которую ты дал ссылку очень хорошо написано, почему например получилось не 46, а 48 байт. И опять же, если использовать #pragma pack, то ты разве что уменьшаешь кол-во отступов внутри файла, сокращая его размер. И "тогда был бред", а "сейчас не бред, так как уменьшили кол-во пробелов" как-то не очень стыкуется.
Я остаютсь при своём мнении. А вольному - воля...
Yandex
Объявления
20.02.2013, 16:04     Чтение/запись файла
Ответ Создать тему
Опции темы

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