Указания по выполнению заданий c (1012885), страница 4
Текст из файла (страница 4)
Исходные данные и результаты Исходные данные: текстовый файл неизвестного размера, состоящий из неизвест- ного количества предложений. Предложение может занимать несколько строк, (1п.веех9(0, !ов::епб); 1оп9 1еп = т!п.Се119О: спаг ьби1 - пеы сйаг [1еп + П: 11п.зееС9(0, 1ов:;Ье9): т(п.геаб(Ьит, 1еп); Ьи[[1еп] - '!О'; 1оп9 и О, т О, 3 О; ил!1е(ЬиГ[1)) ( 1Г( Ьит[!) - '?') ( // ! // 2 Н 3 // 4 // б тог ( ) = и, ) к= т; 1++) соиС «Ьит()] и=! -1; ) тт ( Ьит(т] == .
(1 Ьит(!] = '!' ) и т + 1 (-Н ' тти.с105е(); // 9 соиС « епб1; гевиги О: ) Для определения длины файла используются методы яеекд и се1 1ц класса ! т всгеаш. С любым файлом при его открытии связывается так называемая текущая позиция чтения или записи. Когда файл открывается для чтения, эта позиция устанавливается на начало файла. Для определения длины файла мы перемещаем ее на конец файла с помощью метода зеехц (оператор 1), а затем с помощью Се11д получаем ее значение, запомнив его в переменной 1еп (оператор 2). Метод веехд(оттвеС, огд) перемещает текутцую позицию чтения из файла на от! веС байтов относительно огд. Параметр огд может принимать одно из трех значений: ! оя:: Ьед — от начала файла; ! оя;: сиг — от текущей позиции; !ов;:епб — от конца файла.
Ьед. сиг и епб являются константами, определенными в классе ! оз, предке ! тяггеаш, а символы:: означают операцию доступа к этому классу. В операторе 3 выделяется 1еп + 1 байтов под символьную строку Ьит, в которой будет храниться текст из файла. Мы выделяем на один байт больше, чем длина файла, чтобы после считывания файла записать в этот байт нуль-символ. Для чтения информации требуется снова переместить текущую позицию на начало файла (оператор 4).
Собственно чтение выполняется в операторе 5 с помошью метода гезб(Ьит. 1еи), который считывает из файла 1еп символов (или менее, если конец файла встретится раньше) в символьный массив Ьит. В операторе б определяются служебные переменные. В переменной и будет храниться позиция начала текущего предложения, переменная т используется для просмотра массива, переменная т — для вывода предложения. Цикл просмотра массива бит" (оператор 7) завершается, когда встретился нуль-символ.
Если очередным символом оказался вопросительный знак (оператор 8), выполняется вывод символов, начиная с позиции п до текущей, после чего в переменную и заносится позиция начала нового предложения. Оператор 9 (закрытие потока) в данном случае не является обязательным, так как явный вызов с1озе() необходим только тогда, когда требуется закрыть поток раньше окончания действия его области видимости. Если требуется вывести результаты выполнения программы не на экран, а в файл, в программе следует описать объект класса выходных потоков отвбгевш, а затем использовать его аналогично другим потоковым обьектам, например: огвтгеаш тоиС("СехСоиС.СхС"); тт ((теис) ( соис « "Ошибка открытия файла вывода" « епб1; гесиги 1; ) тоиС с1озе().
При выполнении некоторых заданий этого семинара может потребоваться посимвольное чтение из файла. При использовании потоков оно выполняется с помощью метода деС(), Например, для программы, приведенной выше, посимвольный ввод выглядит следуюшим образом: Ми1е((ЬиПт] = т!п.деСО) .'= ЕОГ) ( т '.т; Надо учитывать, что посимвольное чтение нз файла гораздо менее эффективно. В заключение приведем вариант решения этой же задачи с использованием вместо потоковых классов библиотечных функций, унаследованных из языка С.
()!пс1ибе <вСбто.п> тпС ша!п()( Р1СЕ *т!п; ттп = горел("СехС Схт", "г"): тт" (!т!п) ( риСз("Ошибка открытия файла"); геСигп 1; ) // 1 // 2 П 3 // 4 тзеек(т!п, О. 5ЕЕК Ейц); )опд 1еп - тСе11(т!и); сиаг *бит = пеы сиаг (1еп + Ц; сопзС тпС 1 Ы осК = 1024; тпС пиш Ыоск - 1еп / 1 Ыоск; твеек((тп, О, 5ЕЕК 5ЕТ): тгеат)(Ьит, 1 Ы оск, пиш Ыосх 1, ттп); ЬиП)еп] = '(О'; П 5 // 6 // 7 П О 1опд и = О. ! - О. 1 = О: Ф!1е(Ьит(!]) ( !1( ьл(!] =" '?') [ тог ( д - и: О <- 1; Оэ+) риСсиаг(ЬитГ]]); и- ! +1: ) !т ( ЬФ(т] = ' ' )) ЬиПт] == '! ' ) п = ! + 1; тн; таиС « Ьит[б]: Если требуется закрыть поток раньше окончания действия его области видимости, используется метод с1ояе: 1с)ове( 1то); ргтн Ь1("',и"); ге(огп О; В операторе 1 определяется указатель на описанную в заголовочном файле <втп1о.
Ь> структуру Е1! Е. Указатель именно такого типа формирует функция открытия файла горел. Ее вторым параметром задается режим открытия файла. В данном случае файл открывается для чтения (г). Файл можно открыть в двоичном (Ь) или текстовом (1) режиме. Эти символы записывают во втором параметре, например, "гЬ" или "гг". Двоичный режим означает, что символы перевода строки и возврата каретки (Ох13 и Ох10) обрабатываются точно так же, как и остальные. В текстовом режиме зти символы преобразуются в одиночный символ перевода строки, По умолчанию файлы открываются в текстовом режиме.
Для позиционирования указателя текущей позиции используется функция 1вееК с параметрами, аналогичными соответствующему методу потока (операторы 3 и 7). Константы, задающие точку отсчета смещения, описаны в заголовочном файле <вс()то. Ь> и имеют имена: 5ЕЕК 5ЕТ вЂ” от начала файла; 5ЕЕК СОк — от текущей позиции; 5ЕЕК ЕИΠ— от конца файла. Чтение из файла выполняется функцией 1геад(Ьы1.
в)ге, лыш. й) е) блоками по в1ге байт. Требуется также задать количество блоков пыш. В программе размер блока задан в переменной ) Ь)оси равным 1024, поскольку размер кластера кратен степени двойки. В общем случае чем более длинными блоками мы читаем информацию, тем быстрее будет выполнен ввод. Для того чтобы обеспечить чтение всего файла, к количеству блоков добавляется 1 для округления после деления.
Вывод на экран выполняется посимвольно с помощью функции рщсбв г. Если требуется с помощью функций библиотеки вывести результаты выполнения программы не на экран, а в файл, в программе следует описать указатель на структуру Е1(Е, с помощью функции 1ореп открыть файл для записи (второй параметр функции — и), а затем использовать этот указатель в соответствующих функциях вывода, например: Г1ЕЕ *1оыг; 1ощ - 1орел(ебехсоШ.гхт", "ы"): 1 1 (! 1оос) ( риса("Ошибка открытия файла вывода"); гесигп 1: ) В целом программа, написанная с использованием функций библиотеки, может получиться более быстродействующей, но менее безопасной, поскольку программист должен сам заботиться о большем количестве деталей. Давайте повторим основные моменты этого семинара.
Длина динамической строки может быть переменной. Динамические строки 2. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. нельзя инициализировать при создании. Длина нединамической строки должна быть константным выражением, Прн задании длины строки необходимо учитывать завершающий нуль-символ. Присваивание строк выполняется с помощью функций библиотеки. Для консольного ввода-вывода строк используются либо объекты с~с и соыт, либо функции библиотеки детв, зсао1 и рога, рг)лт1. Ввод-вывод из файла может выполняться с помощью либо объектов классов 11втгеаш и о1втгеаш, либо функций библиотеки 1оегз, 1всап1 и 1рытв, 1рг1п11.
Ввод строки с помощью операции» выполняется до первого пробельного сим- вола. Для ввода строки, содержащей пробелы, можно использовать либо мето- ды 9св)тле или Оес класса т в1геаш, либо функции библиотеки четв и всап1. Смешивать в одной программе ввод-вывод с помощью потоковых классов и с помощью функций библиотеки не рекомендуется. Посимвольное чтение из файла неэффективно. Разбивайте написание программы на последовательность шагов.
Выход за границы строки и отсутствие нуль-символа являются распространен- ными причинами ошибок в программах. Средства, предоставляемые языком, влияют на алгоритм решения задачи, и по- этому перед тем, как продумывать алгоритм, необходимо эти средства изучить. Программа, написанная с использованием функций, а не классов ввода-выво- да, может получиться более быстродействующей, но менее безопасной. Недостатком С-строк по сравнению с классом в( г1 лр является отсутствие про- верки выхода строки за пределы отведенной ей памяти.
Ротс(Ьы1Ы. 1оыМ: // или 1рщс(Ьо1(1), 1оыт); После окончания вывода файл закрывается с помощью функции 1с) озе: 1с) оде(1ЬМ): Функции вывода в файл описаны в Учебнике на с. 90 и 411. Смешивать в одной программе ввод-вывод с помощью потоковых классов н с помощью функций библиотеки не рекомендуется. .