Ввод-вывод с произвольным доступом




Под понятием произвольного доступа к файлу подразумевается ряд различных моментов:

· можно произвольно обращаться к любой записи или любому байту в файле, в противоположность последовательному доступу, когда данные извлекаются или передаются в поток строго по очереди;

· в открытом файле можно произвольно чередовать операции чтения и записи;

· ввод-вывод с произвольным доступом является по преимуществу бесформатным.

Для позиционирования потока используются функции seekg() и seekp().

Разница между ними в том, что первая перемещает позицию чтения в потоке, а вторая устанавливает новую позицию в выходном потоке. Если используется поток типа fstream, и он открыт в режиме чтения-записи, то все равно, какую функцию применять для позиционирования.

Для определения текущей позиции tellg() и tellp(). Первая возвращает позицию чтения во входном потоке, а вторая – позицию в выходном потоке.

Примеры программ

Рассмотрим примеры использования функции работы с файлами и строками.

Пример 11.3 Поиск вхождения слова в файле

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

int main ()

{

setlocale ( LC_ALL, "Russian" );

const int len = 81;

char word [ len ], line [ len ], end_word [] = "done";

 

//пересоздадим файл и откроем для чтения/записи

fstream f ( "lab11.txt", ios :: in | ios :: out | ios :: trunc );

if (! f )

{

cout << "Ошибка открытия файла" << endl;

return - 1;

}

//введем несколько строк для дальнейшего поиска в них

do

{

cin >> line;

//с файловым потоком можно работать как со стандартными cin и cout

f << line << endl;

}

//продолжаем пока не введем done

while ( strcmp ( line, end_word ));

//сбросим файловый поток на начало

f. seekg ( 0 );

cout << "Содержимое файла: " << endl;

//содержимое файла на экран

//выполняем пока не достигнем конца файла

while (! f. eof ())

{

f >> line;

cout << line << endl;

}

cout << "Введите слово для поиска: ";

cin >> word;

 

//сбрасываем бит-признак конца файла eofbit

f. clear ();

//сбросим файловый поток на начало

f. seekg ( 0 );

//определим длину искомого слова

size_t l_word = strlen ( word );

//счетчик вхождения слова

int wc = 0;

//читаем построчно и ищем слово word в строке

while ( f. getline ( line, len ))

{

//поместим указатель p на начало строки

char * p = line;

//strstr возвращает указатель

// на элемент из строки p с которого начинается word

while ( p = strstr ( p, word ))

{

//используем указатель не текущую позицию в строке

char * c = p;

 

//переместим p на символ сразу за концом слова

p += l_word;

//проверим стоит ли наше слово отдельно

//или это просто подстрока в другом (большем) слове

//проверим совпадает ли начало слова с началом строки

if ( c != line )

//проверим символ перед началом слова

//на принадлежность к разделителям

if (! ispunct (*( c - 1 )) &&! isspace (*( c - 1 )))

//начинается не с начала строки и

//не с разделителя => ищем дальше

continue;

 

//символы перед началом слова подходят

//проверяем символы за окончанием слова

//если это пробелы, символы пунктуации

//или конец строки => увеличиваем счетчик слов

if ( ispunct (* p ) || isspace (* p ) || (* p == '\0' ))

{

wc ++;

cout << "Слово найдено" << endl;

}

}

}

cout << "Количество вхождений слова: " << wc << endl;

return 0;

}

Рассмотрим другой подход к решению предложенной выше задачи. В библиотеке C++ есть функция strtok, которая разбивает предложенную строку на лексемы в соответствии с заданным набором разделителей. При ее использовании нет необходимости выделять и проверять начало и конец слова. Потребуется лишь сравнит с искомым словом, слово, выделенное strtok. Для этого просто необходимо задать разделители.

Пример 11.4 Поиск вхождения слова в файле с помощью strtok

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <string>

using namespace std;

int main ()

{

setlocale ( LC_ALL, "Russian" );

const int len = 81;

char word [ len ], line [ len ], end_word [] = "done";

 

//пересоздадим файл и откроем для чтения/записи

fstream f ( "lab11.txt", ios :: in | ios :: out | ios :: trunc );

if (! f )

{

cout << "Ошибка открытия файла" << endl;

return - 1;

}

//введем несколько строк для дальнейшего поиска в них

do

{

cin >> line;

f << line << endl;

}

//продолжаемпоканевведем done

while ( strcmp ( line, end_word ));

cout << "Введите слово для поиска: ";

cin >> word;

 

//сбрасываем бит-признак конца файла eofbit

f. clear ();

//сбросим файловый поток на начало

f. seekg ( 0 );

//Список разделителей

char delims [] = ",.!? /<>|()*:;\"";

 

//Указатель на начало слова

char * token;

//счетчик вхождения слова

int wc = 0;

//читаем построчно и ищем слово word в строке

while ( f. getline ( line, len ))

{

//находим первый символ не из разделителей

//находим первый символ не из разделителей

token = strtok ( line, delims );

//проверяем, остались ли еще слова

while ( token != NULL )

{

//strtok заменяет символ после разделителя

//на NULL поэтому можно сравнивать искомое и

//найденноеслово

if (! strcmp ( token, word ))

wc ++;

//Для поиска следующей лексемы в той же строке

//strtok необходимо передать NULL

token = strtok ( NULL, delims );

}

}

cout << "Количество вхождений слова: " << wc << endl;

return 0;

}

Пример 11.5 Произвольный доступ к файлу

// Открыть файл как двоичный сразу для ввода и вывода

// (создать новый, если отсутствует или перезаписать старый)

// Ввести элементы с клавиатуры

// Поменять знак четных элементов

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <iomanip>

using namespace std;

int main ()

{

setlocale ( LC_ALL, "Russian" );

const int NP = 10;

const int IS = sizeof(int); //размерэлемента int

int pt, i;

// Открытие файла для чтения/записи.

fstream fs ( "random.txt",

ios :: binary | ios :: in | ios :: out | ios :: trunc );

if (! fs )

{ cerr << "Ошибка открытия файла." << endl;

return 1; }

// Первоначальная запись файла.

cout << "Начальныезаняения:" << endl;

for ( i = 0; i < NP; i ++)

{ pt = i;

//Приводим pt к типу char* для нормальной работы write

fs. write ((char*)& pt, IS );

cout << setw ( 4 ) << pt; }

cout << endl << endl;

// Чтение файла от конца к началу.

cout << "Читаем из файла в обратном порядке:" << endl;

for ( i = 0; i < NP; i ++)

{

//Перемещаемся к i-му элементу с конца

fs. seekg (-( i + 1 ) * IS, ios :: end );

//Приводим pt к типу char* для нормальной работы read

fs. read ((char*)& pt, IS );

cout << setw ( 4 )<< pt;

};

cout << endl << endl;

// Переписать четные индексы.

for ( i = 1; i < NP / 2; i ++)

{

//перемещаемся к i-му элементу

fs. seekg ( 2 * i * IS );

//читаем i-ыйэлемент

fs. read ((char*)& pt, IS );

//меняем значение на противоположное

pt = - pt;

//возвращаемся на шаг назад, к только что прочитанному элементу

int p = fs. tellg ();

p -= IS;

fs. seekg ( p );

//перезаписываемего

fs. write ((char*)& pt, IS ); }

//выводим файл на экран

cout << "После перезаписи:" << endl;

fs. seekg ( 0 );

for ( i = 0; i < NP; i ++)

{ fs. read ((char*)& pt, IS );

cout << setw ( 4 ) << pt; }

cout << endl;

fs. close ();

return 0 ;}

Замечание. Когда эта программа открывает уже существующий файл, он усекается до нулевой длины (т.е. все его данные теряются). Если необходимо работать с уже имеющимися в файле данными, нужно убрать бит ios::trunc из режима открытия потока.

Варианты заданий

Вариант 1

Написать программу, которая считывает текст из файла и выводит на экран только цитаты, то есть предложения, заключенные в кавычки.

Вариант 2

Написать программу, которая считывает текст из файла и выводит на экран только предложения, состоящие из заданного количества слов.

Вариант 3

Написать программу, которая считывает английский текст из файла и выводит на экран слова текста, начинающиеся и оканчивающиеся на гласные буквы.

Вариант 4

Написать программу, которая считывает текст из файла и выводит на экран только строки, не содержащие двузначных чисел.

Вариант 5

Написать программу, которая считывает текст из файла и выводит на экран только предложения, начинающиеся с тире, перед которым могут находиться только пробельные символы.

Вариант 6

Написать программу, которая считывает английский текст из файла и выводит его на экран, заменив каждую первую букву слов, начинающихся с гласной буквы, на прописную.

Вариант 7

Написать программу, которая считывает текст из файла и выводит его на экран, заменив цифры от 0 до 9 на слова «ноль», «один»,..., «девять», начиная каждое предложение с новой строки.

Вариант 8

Написать программу, которая считывает текст из файла, находит самое длинное слово и определяет, сколько раз оно встретилось в тексте.

Вариант 9

Написать программу, которая считывает текст из файла и выводит на экран сначала вопросительные, а затем восклицательные предложения.

Вариант 10

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

Вариант 11

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

Вариант 12

Написать программу, которая считывает текст из файла и выводит на экран сначала предложения, начинающиеся с однобуквенных слов, а затем все остальные.

Вариант 13

Написать программу, которая считывает текст из файла и выводит на экран предложения, содержащие максимальное количество знаков пунктуации.

Вариант 14

Написать программу, которая считывает текст из одного файла, содержащего только цифры. Выводит его содержимое на экран, и записывает в другой файл заменив цифры от 0 до 9 на слова «ноль», «один»,..., «девять», начиная каждое число с новой строки, а цифры разделяя пробелами.

 

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2018-01-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: