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

Удаление строки из файла через сдвиги. - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.63
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
06.06.2011, 17:47     Удаление строки из файла через сдвиги. #1
Добрый день. Прощу помочь с защитой лабы.
Есть файл тхт, в нем названия банков и значения по годам:
Банк 2000г 2001г
ВТБ; 35.4; 31.5
.....................
Банк Москвы; 0; 4.2

Что нужно:
Нам нужно удалить банки с значением 0 в один из годов. Решать эту задачу мы должны через сдвиги, так же мы не должны использовать буферные файлы или отдельные массивы строк.

Прикрепляю файл и ссылку на тему в которой решали саму лабу.
Вложения
Тип файла: txt fail.txt (489 байт, 19 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.06.2011, 17:47     Удаление строки из файла через сдвиги.
Посмотрите здесь:

Удаление строки из файла\либо удаление самого файла. C++
C++ Удаление строки из файла
C++ Удаление строки из файла
Удаление строки файла C++
C++ Удаление строки из файла
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
07.06.2011, 02:16  [ТС]     Удаление строки из файла через сдвиги. #2
upd...
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
07.06.2011, 08:59     Удаление строки из файла через сдвиги. #3
Решать эту задачу мы должны через сдвиги, так же мы не должны использовать буферные файлы или отдельные массивы строк.
Вот это совсем непонятно.
1. Обычно удаление из файла делается так: открывается исходный для чтения, новый для записи.
Пока исходный не кончился, читаем записи исходного, пишем в новый только те, которые удовлетворяют условию. В нашем случае это не равно 0.
Таким образом, ненужные записи просто пропускаются.
2. Если файл двоичный и размер записи известен и постоянен, то можно выполнять перезапись по месту, используя функцию вроде seek() - передвижение по записям.
Но в вашем случае файл-то текстовый! И размер строк в этом файле - разный!
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
07.06.2011, 10:26  [ТС]     Удаление строки из файла через сдвиги. #4
ValeryLaptev, да, файл текстовый, и просили выполнить без 1 пункта.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
07.06.2011, 10:39     Удаление строки из файла через сдвиги. #5
Цитата Сообщение от IIIa66uMEM6eP Посмотреть сообщение
ValeryLaptev, да, файл текстовый, и просили выполнить без 1 пункта.
Тогда мне в голову приходит только один способ. Открыть текстовый файл как двоичный и читать побайтно. Но гемора с запоминанием позиций начала каждой строки - много. Для двоичных файлов с записями потому и реализовано передвижение по файлу, так как там размер записи известен и фиксирован. И легко посчитать сдвиг на нужную запись от начала. А в текстовом - все строки разной длины и приходится следить за концом записи - там есть символ '\n'. Но физически - это два байта:
0x0A0D или 0x0D0A - не помню в каком порядке.
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
07.06.2011, 11:06  [ТС]     Удаление строки из файла через сдвиги. #6
ValeryLaptev, без гемора никуда. нельзя через темповский файл, нельзя массивы строк..
не могли бы подсказать что нибудь про побайтное чтение двоичного файла?
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
07.06.2011, 11:15     Удаление строки из файла через сдвиги. #7
В С++ это метод read() для объекта типа fstream.
А вообще-то в моей книжке 14 глава: Библиотека ввода-вывода.

Не по теме:

Сейчас некогда - надо уходить. Вернусь - выдам инфу.

IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
07.06.2011, 11:19  [ТС]     Удаление строки из файла через сдвиги. #8
ValeryLaptev, я в книжке гляну. спс

Добавлено через 2 минуты
Ой.. у меня наверно не так книжка, эта - Экспрес курс С++
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
07.06.2011, 14:35     Удаление строки из файла через сдвиги. #9
Цитата Сообщение от IIIa66uMEM6eP Посмотреть сообщение
ValeryLaptev, я в книжке гляну. спс

Добавлено через 2 минуты
Ой.. у меня наверно не так книжка, эта - Экспрес курс С++
Там тоже есть, но не так подробно. Поищи в сети дежавю-файл моей книжки по ООП.
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
07.06.2011, 19:26  [ТС]     Удаление строки из файла через сдвиги. #10
ValeryLaptev, да... разбиратся много.. вообщем то мою задачу можно свести к тому, что бы считать файл по байтно и если найден код нуля - то ..., что сделать тогда? как затереть..
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
07.06.2011, 21:26     Удаление строки из файла через сдвиги. #11
Не так просто.
1. Надо при чтении проверять байты 0d0a - это конец строки. И запоминать первую позицию после нее.
2. Потом читать байты до следующей 0d0a. Проверка на код нуля тебе не поможет, так как у тебя может быть число, например, такое - 100.05. Тут аж три нуля.
Мне в голову пришла мысль, что можно попробовать открыть два потока, связав их в одним файлом.. Один поток - текстовый, а второй - бинарный. Текстовый поток - чтобы вводить нормально данные и проверять на ноль. А бинарный - чтобы перемещаться по байтам этого файла.
Перемещение делается функциями seekg() - для чтения, и seekp() - для записи.
Все надо пробовать.
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
07.06.2011, 22:55  [ТС]     Удаление строки из файла через сдвиги. #12
ValeryLaptev, идея понравилась, но с seek ни чего не делал раньше, да и с бинарными файлами тоже.. поможете?
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
07.06.2011, 23:21     Удаление строки из файла через сдвиги. #13
Вот инфа.

Произвольный доступ
Как уже отмечалось, С++ позволяет выполнять позиционирование в любых потоках, кроме стандартных. Методы позиционирования приведены в табл. 14.5. Методы позиционирования различаются для входных и выходных потоков: для входных потоков (см. п.п. 27.6.1.3 в [1]) имена методов заканчиваются символом «g» (от слова get), для выходных (см. п.п. 27.6.2.4 в [1]) — символом «p» (от слова put).

Таблица 14.5. Методы позиционирования
Метод Описание
C++
1
2
3
4
5
6
pos_type tellg()    Получить текущую (абсолютную) позицию чтения
istream& seekg (pos_type p) Установить абсолютную позицию чтения
istream& seekg (off_type p, ios::seekdir s) Установить относительную позицию чтения
pos_type tellp()    Получить текущую (абсолютную) позицию записи
istream& seekp (pos_type p) Установить абсолютную позицию записи
istream& seekp (off_type p, ios::seekdir s) Установить относительную позицию записи
Функции tellp() и tellg() возвращают абсолютное смещение от начала потока. Символы потока нумеруются, как и индексы массива, начиная с нуля. Однако тип pos_type не является целым типом. Поэтому получать текущую позицию чтения в файловом потоке нужно так:
C++
1
ios::pos_type p = file.tellg();
Можно сохранить текущую позицию и в переменной типа streampos, например:
C++
1
streampos pos = file.tellp();
Переход к позиции, сохраненной в переменной pos, делается так:
C++
1
file.seekp(pos);
Несмотря на то, что тип значения позиции в потоке не является целым значением, целые константы можно использовать в качестве аргумента в методах установки позиции — выполняется преобразование по умолчанию. Символы в потоке нумеруются, начиная с нулевого, поэтому позиционирование в начало потока можно выполнить, например, так:
C++
1
file.seekg(0);
После этого опять можно будет прочитать первый символ потока.
Методы установки относительной позиции очень похожи на функцию fseek() из библиотеки <cstdio>. В классе ios_base определены следующие константы (см. п.п. 27.4.2.1.5 в [1]):
C++
1
2
3
static const seekdir beg,    // позиционирование от начала потока 
                     cur,    // позиционирование от текущей позиции
                     end;    // позиционирование от конца потока
Первый аргумент, который обычно задается целым числом (выполняется преобразование по умолчанию), является смещением (в символах) от указанной позиции. Положительное число означает смещение вперед — ближе к концу файла, отрицательное — смещение назад, к началу файла. Например, позиционироваться в конец файла можно так:
C++
1
file.seekg(0, ios::end);
При позиционировании нужно следить, чтобы позиция оставалась внутри файла. Попытка позиционироваться до начала потока или после конца приводит поток в состояние bad(). Небольшой пример показывает, как работает относительное позиционирование (листинг 14.22).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Листинг 14.22. Относительное позиционирование
int main()
{   fstream strm("c:/binfiles/oonumber2.bin",ios::binary|ios::in|ios::out);
    int a = 0;
    // читаем числа из файла и выводим 
    strm.seekg(2*sizeof(int), ios::beg);      // выставляемся от начала
    strm.read((char *)&a, sizeof(int));       // читаем
    cout << a << ' ' << '\n';
    // записываем новое число на ту же позицию
    a = 12021;
    strm.seekp(2*sizeof(int), ios::beg);      // выставляемся от начала
    strm.write((char *)&a, sizeof(int));      // записываем
    // возвращаемся, читаем снова и выводим
    strm.seekg(2*sizeof(int), ios::beg);      // выставляемся от начала
    strm.read((char *)&a, sizeof(int));       // опять читаем
    cout << a << ' ' << '\n';
    return EXIT_SUCCESS;
}
В примере открывается существующий (см. листинг 14.7) двоичный файл в режиме чтения/записи. Оба флага (ios::in|ios::out) задавать обязательно, иначе по умолчанию файловый поток открывается только для записи. Сначала читается третье от начала число, затем выполняется возврат в ту же позицию и записывается новое число. Результат можно наблюдать на экране.
C помощью методов позиционирования можно вычислить размер файла (листинг 14.23).
C++
1
2
3
4
5
6
7
8
Листинг 14.23. Функция, вычисляющая длину файла
long filesize(ifstream &stream)
{  streampos curpos = stream.tellg();    // сохраняем текущую позицию
   stream.seekg(0, ios::end);            // высталяемся на конец файла
   streampos last = stream.tellg();      // получаем позицию = длина
   stream.seekg(curpos);                 // возвращаем текущую позицию.
   return last;
}
Несмотря на то, что используются переменные типа streampos, в результате выполняется преобразование по умолчанию в тип long. Применять эту функцию можно как с двоичными файлами, так и с текстовыми, например:
C++
1
2
3
4
5
6
7
ifstream g;
g.open("c:/textfiles/result.files");
cout << filesize(g) << endl;
g.close();
g.open("c:/binfiles/bin2.bin", ios::binary);
cout << filesize(g) << endl;
g.close();
Сначала вычисляется длина текстового файла result.files, который образовался в каталоге textfiles в результате вызова функции includeFile() (см. листинг 14.5). Затем с помощью той же функции вычисляется длина двоичного файла из листинга 14.8.

Методы позиционирования облегчают обработку двоичных файлов, записанных любыми другими средствами, например, средствами языка Pascal. В С++, в отличие от языка программирования Pascal, отсутствуют типизированные файлы с записями (file of type). В языке Pascal такие файлы являются двоичными. Записи нумеруются, начиная с нуля, что обеспечивает прямой доступ к записи. Такие файлы в программе на языке Pascal по умолчанию открываются в режиме чтения/записи.
Мы вполне можем обработать такие файлы и обеспечить прямой доступ к записям по номерам средствами С++. Для этого нужно объявить в программе структуру, имеющую поля соответствующих типов, заданные в том же порядке, что в записи в программе на Pascale. Здесь нужно внимательно отнестись к проблеме выравнивания — структура в С++ должна иметь точно такой же размер, как и запись в Pascal. Далее нужно открыть файл как двоичный в режиме чтения/записи. Чтение из файла выполняется оператором
C++
1
strm.read((char *)&record, sizeof(T));
А запись выполняется оператором
C++
1
strm.write((char *)&record, sizeof(T));
Здесь sizeof(T) — размер структуры в С++, который должен совпадать с размером записи в Pascal.
Методы относительного позиционирования позволяют реализовать прямой доступ к записям этого двоичного файла. Например, позиционирование на k-ю запись для чтения выполняется оператором
C++
1
strm.seekg(k*sizeof(T), beg);
Если необходимо сместиться вперед от текущей позиции на одну запись вперед, можно воспользоваться любой из следующих инструкций:
C++
1
2
3
// эквивалентные вызовы seekg
stream.seekg(stream.tellg() + sizeof(T));     // абсолютная позиция
stream.seekg(sizeof(T), ios::cur);            // относительная позиция
Сместиться назад на одну запись можно так:
C++
1
2
stream.seekg(stream.tellg() - sizeof(T));     // абсолютная позиция
stream.seekg(-sizeof(T), ios::cur);           // относительная позиция
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
09.06.2011, 10:57  [ТС]     Удаление строки из файла через сдвиги. #14
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
попробовать открыть два потока, связав их в одним файлом
как это сделать?

Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Текстовый поток - чтобы вводить нормально данные и проверять на ноль
тоесть в этом случае 3 нуля не будет.

Все равно слабо представляю как это программно реализовать, мало с этим что то делал.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
09.06.2011, 11:40     Удаление строки из файла через сдвиги. #15
C++
1
2
fstream bin("name", ios::in|ios::out|ios::binary); // -- двоичный для перезаписи --
ifstream txt("name");                      // -- текстовый для ввода --
Я тоже подобного фокуса еще не пробовал, но насколько помню для чтения можно открывать файл одновременно несколько раз.
Но гемора тут все равно - много. Пробовать надо, фактически исследовательскую работу профодить, как будет вести себя файл и файловая система при таких наших действиях.

Из текстового файла вводить аналогично cin:
C++
1
txt >> var;
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
09.06.2011, 13:34  [ТС]     Удаление строки из файла через сдвиги. #16
ValeryLaptev, вот так защита лабораторной)
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
09.06.2011, 13:38     Удаление строки из файла через сдвиги. #17
Цитата Сообщение от IIIa66uMEM6eP Посмотреть сообщение
ValeryLaptev, вот так защита лабораторной)
Как обычно возможны два варианта...
1. Либо вы не совсем поняли препода в каких-то мелочах. Потому как перезапись ТРАДИЦИОННО исполняется только для двоичных файлов. Но никак не текстовых.
2. Либо препод совершенно не имеет реального опыта программирования. Отсюда и завихрительные требования. Ни один реальный программер не будет перезаписывать текстовый файл по месту.
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
09.06.2011, 13:40  [ТС]     Удаление строки из файла через сдвиги. #18
2. точно два, ну он паскалист - незнаю может там это проще.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
09.06.2011, 13:49     Удаление строки из файла через сдвиги. #19
IIIa66uMEM6eP, тогда можно просто рассказать ему все наши соображения. Что строки разной длины, что надо запоминать позиции концов строк, что для перезаписи нужно открывать тот же файл в двоичном байтовом режиме и т.д. Мож впечатлится информацией, которую вам пришлось раскапывать...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.06.2011, 13:51     Удаление строки из файла через сдвиги.
Еще ссылки по теме:

C++ Удаление из строки повторяющихся элементов (через функцию)
Удаление строки из файла C++
C++ Удаление строки из файла по имени

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

Или воспользуйтесь поиском по форуму:
IIIa66uMEM6eP
заставил Бендера
 Аватар для IIIa66uMEM6eP
432 / 288 / 10
Регистрация: 05.12.2010
Сообщений: 1,642
Записей в блоге: 6
09.06.2011, 13:51  [ТС]     Удаление строки из файла через сдвиги. #20
ValeryLaptev, иии)) скажет ну если все знаете - реализовывайте, приходите на защиту.. надо как то сформулировать - что бы ни вопросов ни придлогов) спасибо

Добавлено через 51 секунду
ValeryLaptev, вы же кажется тоже преподаватель?
Yandex
Объявления
09.06.2011, 13:51     Удаление строки из файла через сдвиги.
Ответ Создать тему
Опции темы

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