LINUX.ORG.RU

С++ - запись в файлы

 


0

2

Есть вот такой кусок кода:

ofstream write("results/users.dat", ios_base::binary | ios_base::out);
if(write == NULL)
	  {
	    cout << "Файл недоступен для записи!" << endl;
	  }
	  else
	  {
	  do
	    {
	      cout << "Введите ID пользователя (от 1 до 100, 0 для выхода): ";
	      cin >> uz.userID;
	    } while(uz.userID < 0 or uz.userID > 100);
	    while(uz.userID != 0)
	    {
	      cout << "Введите имя пользователя и количество комментариев: \n";
	      cin >> uz.nickname >> uz.comments;
	      write.seekp((uz.userID-1) * sizeof uz, ios_base::beg);
	      write.write((char*)&uz, sizeof uz);
	      cout << "Введите ID пользователя (от 1 до 100, 0 для выхода): ";
	      cin >> uz.userID;
	    }
	    cout << "Завершение программы." << endl;
	    write.close();
Проблемы начинаются с момента открытия потока на запись. На первом этапе работы создаётся файл, в который записывается структура. Вторым этапом должна быть запись данных в файл. Так вот, при создании файла всё записывается как надо - 100 строк, забитых нулями. Далее поток закрывается и при получении от пользователя подтверждения на запись данных открывается новый поток ввода, и тут файлу приходит кабздец, в нём остаётся одна строка, плюс к этому последние введённые данные записываются дважды. В принципе, пока писал - понял, как обойти проблему (первый поток записи не закрывается, работа продолжается с ним же), но вопрос остался: как при открытии файла на запись не пролюбить все данные в нём? Вариант с ios::app проблему решает только частично, так как писать нужно в произвольную часть файла.

★★★★

Последнее исправление: Valkeru (всего исправлений: 1)

if(write == NULL)

хотел было вбросить, но, действительно, у ofstream есть operator void*(). Слава перегрузке!

yoghurt ★★★★★
()
write == NULL


!write

У ofstream есть operator !.

Deleted
()
Последнее исправление: romeo250501 (всего исправлений: 2)
Ответ на: комментарий от DELIRIUM

А у меня одного от отступов глаза заболели?

+1 Пока в виме gg=G не скастовал, код не осилил.

JaneDoe
()
Ответ на: комментарий от Valkeru

данные пишутся в конец файла, делаю я seekp или нет

Что-то как-то не верится. Давай strace покажи, посмотрим, что там происходит на самом деле.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от JaneDoe

Хм, да, без параметров открытия работает, но если указывать параметры ios_base::out | ios_base::binary - то опять всё ломается. Хвост файла отсекается, последняя запись дублируется.

Valkeru ★★★★
() автор топика

Напиши это на сях, будет проще и понятней! И работать будет, в отличие от...

anonymous
()
Ответ на: комментарий от yoghurt

хотел было вбросить, но, действительно, у ofstream есть operator void*(). Слава перегрузке!

Ага, тоже начал писать коммент на эту тему, а потом глянул перегруженные операторы.

andreyu ★★★★★
()

Вам обязательно нужно использовать ofstream?

andreyu ★★★★★
()

И куда у тебя seekp происходит?...

invy ★★★★★
()
Ответ на: комментарий от RazrFalcon

Немедленно вернитесь в стадо.

anonymous
()

Давай разберём по частям, тобою написанное...

if(write == NULL)

Щас бы ofstream с указателем сравнить (это должно правильно работать, что не отменяет абсурдности написанного)

uz.userID < 0 or uz.userID > 100
Использовать в 2016 алиасы, завезённые в лихих 80-х специально для инвалидов, у которых в кодировке нет «|» — тоже зашквар, в общем.
seekp((uz.userID-1) * sizeof uz, ios_base::beg)
Но зачем, когда у seekp есть перегрузка, принимающая только абсолютное смещение?
write.close();
man RAII
ret = stat("results/users.dat", &buf);
Сначала они мешают сишный и плюсовый код, а потом говорят, что читабельность хреновая и вообще кресты не нужны.
cin >> &answ;
Один лишний символ — и стек идёт по известному месту. Ох уж эти оптимизаторы.

А если по теме, то попробуй добавить ещё флаг in (out можешь убрать, он у ostream’а в любом случае есть)

Softwayer ★★
()

Сначала они мешают сишный и плюсовый код

Будто что-то плохое ;) Скажи уж тогда, как можно дёрнуть stat из крестов кроме как через system(). Всё что гуглится - именно в таких формах, причём второй вариант не нравится тем, что надо дописывать перенаправление вывода в /dev/null

а потом говорят <...> кресты не нужны.

Ты всё перепутал, Эдик выше отметился ;)

Один лишний символ — и стек идёт по известному месту. Ох уж эти оптимизаторы.

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

read(0, "y\n", 1024)                    = 2
write(1, "\320\244\320\260\320\271\320\273 \320\264\320\260\320\275\320\275\321\213\321\205 \320\275\320\265 \321\201\321\203\321"..., 79) = 79
read(0, "y\n", 1024)                    = 2
write(1, "\320\244\320\260\320\271\320\273 \320\264\320\260\320\275\320\275\321\213\321\205 \320\275\320\265 \321\201\321\203\321"..., 79) = 79
read(0, "y\n", 1024)                    = 2
Когда cin >> &answ:
read(0, "y\n", 1024)                    = 2
brk(0)                                  = 0xf99000
brk(0xfba000)                           = 0xfba000
open("results/users.dat", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4000) = 4000
close(3)                                = 0
write(1, "\320\244\320\260\320\271\320\273 \320\264\320\260\320\275\320\275\321\213\321\205 \321\203\321\201\320\277\320\265\321\210"..., 120) = 120
При этом в остальных местах проблемы нет. http://paste.ubuntu.com/15991772/

Valkeru ★★★★
() автор топика
Ответ на: комментарий от Valkeru

Будто что-то плохое ;) Скажи уж тогда, как можно дёрнуть stat из крестов кроме как через system(). Всё что гуглится - именно в таких формах, причём второй вариант не нравится тем, что надо дописывать перенаправление вывода в /dev/null

Скоро (в C++17) будет std::filesystem, и stat можно будет оставить сишникам. А пока можно взять boost::filesystem.

deadNightTiger ★★★★★
()
Последнее исправление: deadNightTiger (всего исправлений: 1)
Ответ на: комментарий от deadNightTiger

А если не хочется брать boost::filesystem, то можно просто попробовать создать ifstream и посмотреть, всё ли у него хорошо.

Softwayer ★★
()

NULL

Не надо так, надо

nullptr

if(write == NULL)

можно проще

if (!write)

И форматирование ужасное, исправь, пожалуйста.

Какая-то магия

write.seekp((uz.userID-1) * sizeof uz, ios_base::beg);
write.write((char*)&uz, sizeof uz);
ничего не понел.

100 строк
ios_base::binary

???

BruteForce ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.