Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
visual с++.doc
Скачиваний:
28
Добавлен:
18.08.2019
Размер:
10.99 Mб
Скачать

I. Исходные данные и результаты

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

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

П. Алгоритм решения задачи

  1. Открыть файл.

  2. Определить его длину в байтах.

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

  4. Считать файл с диска в буфер.

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

Детализируем последний пункт алгоритма. Для вывода предложения необходимо хранить позиции его начала и конца. Предложение может оканчиваться точкой, восклицательным или вопросительным знаком. Во-первых двух случаях предложе­ние пропускается. Это выражается в том, что значение позиции начала предложе­ния обновляется. Оно устанавливается равным символу, следующему за текущим, и просмотр продолжается. В случае обнаружения вопросительного знака предло­жение выводится на экран, после чего также устанавливается новое значение по­зиции начала предложения.

III. Программа и тестовые примеры

Ниже приводится текст программы. Рекомендуем вам самостоятельно разбить его для отладки на последовательность шагов аналогично предыдущим примерам, вставляя и удаляя отладочную печать. Файл с тестовым примером должен содер­жать предложения различной длины (от нескольких символов до нескольких строк), в том числе и вопросительные.

Листинг 8.3

#include <fstream.h>

#include <stdio.h>

int main()

{

setlocale( LC_ALL, "Russian" );

ifstream fin("text.txt",ios::in|ios::nocreate);

if (!fin)

{

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

return 1;

}

fin.seekg(0,ios::end); //1

long len = fin.tellg(); //2

char *buf = new char[len + 1]; //3

fin.seekg(0, ios :: beg); //4

fin.read(buf. len); //5

buf[len] = '\0';

long n = 0, i = 0, j = 0; //6

while(buf[i]) //7

{

if(buf[i] = '?') //8

{

for(j = n; j <= i; j++) cout<< buf[j];

n = i + j;

}

if(buf[i] == '.'||buf[i] == '!') n = i + j;

i++;

}

fin.close(); //9

cout << endl;

return 0;

}

Для определения длины файла используются методы seekg и tel I g класса stream. С любым файлом при его открытии связывается так называемая текущая позиция чтения или записи. Когда файл открывается для чтения, эта позиция устанавлива­ется на начало файла. Для определения длины файла мы перемещаем ее на конец файла с помощью метода seekg (оператор 1), а затем с помощью tel I g получаем ее значение, запомнив его в переменной 1 en (оператор 2).

Метод seekg(offset, org) перемещает текущую позицию чтения из файла на offset байтов относительно org. Параметр org может принимать одно из трех значений:

ios:: beg - от начала файла; i os:: cur - от текущей позиции; i os:: end - от конца файла.

beg, cur и end являются константами, определенными в классе 1 os, предке 1 f stream, а символы :: означают операцию доступа к этому классу.

В операторе 3 выделяется 1 en + -1 байтов под символьную строку buf, в которой будет храниться текст из файла. Мы выделяем на один байт больше, чем длина файла, чтобы после считывания файла записать в этот байт нуль-символ.

Для чтения информации требуется снова переместить текущую позицию на нача­ло файла (оператор 4). Собственно чтение выполняется в операторе 5 с помощью метода read(buf, I en), который считывает из файла Ten символов (или менее, если конец файла встретится раньше) в символьный массив buf.

В операторе 6 определяются служебные переменные. В переменной п будет хра­ниться позиция начала текущего предложения, переменная i используется для просмотра массива, переменная j - для вывода предложения.

Цикл просмотра массива buf (оператор 7) завершается, когда встретился нуль-сим­вол. Если очередным символом оказался вопросительный знак (оператор 8), вы­полняется вывод символов, начиная с позиции п до текущей, после чего в перемен­ную п заносится позиция начала нового предложения.

Оператор 9 (закрытие потока) в данном случае не является обязательным, так как явный вызов close() необходим только тогда, когда требуется закрыть поток рань­ше окончания действия его области видимости.

Если требуется вывести результаты выполнения программы не на экран, а в файл, в программе следует описать объект класса выходных потоков ofstream, а затем использовать его аналогично другим потоковым объектам, например:

ofstream fout("textout.txt");

if(!fout)

{

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

return 1;

}

...

fout << buf[j];

требуется закрыть поток раньше окончания действия:

fout.closeO;

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

while((buf[i] = fin.get()) != EOF

{

...

i++;

}

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

Листинг 8.4

#include <stdio.h>

int main()

{

FILE *ffseek (finin;

fin = fopen("text.txt","r");

setlocale( LC_ALL, "Russian" );

if (!fin)

{

puts("Ошибка открытия файла");

return 1;

}

fseek(fin, 0, SEEK END);

long len = ftell(fin);

char *buf = new char[len + 1];

const int l block = 1024;

int num block = len/l block;

fseek(fin, 0, SEEK SET);

fread(buf, l block, num block + 1, fin);

buf[len] = '\0';

long n = 0, i = 0, j = 0;

while(buf[i])

{

if (buf[i] == '?')

{

for (j = n; j <= i; j++)

putchar(buf[j]);

n = i + j;

}

}

fclose(fin);

printf('\n");

return 0;

}

В операторе 1 определяется указатель на описанную в заголовочном файле <stdio.h> структуру FILE. Указатель именно такого типа формирует функция от­крытия файла fopen. Ее вторым параметром задается режим открытия файла. В данном случае файл открывается для чтения (г).

Файл можно открыть в двоичном (Ь) или текстовом (t) режиме. Эти символы записывают во втором параметре, например, "rb" или "rt". Двоичный режим озна­чает, что символы перевода строки и возврата каретки (0x13 и 0x10) обрабатыва­ются точно так же, как и остальные. В текстовом режиме эти символы преобразу­ются в одиночный символ перевода строки. По умолчанию файлы открываются в текстовом режиме.

Для позиционирования указателя текущей позиции используется функция f seek с параметрами, аналогичными соответствующему методу потока (операторы 3 и 7). Константы, задающие точку отсчета смещения, описаны в заголовочном файле <stdiо. h> и имеют имена:

SEEK_SET - от начала файла; SEEK_CUR - от текущей позиции; SEEK_END - от конца файла.

Чтение из файла выполняется функцией fread(buf, size, num. file) блоками по size байт. Требуется также задать количество блоков num. В программе размер бло­ка задан в переменной равным 1024, поскольку размер кластера кратен сте­пени двойки. В общем случае чем более длинными блоками мы читаем информа­цию, тем быстрее будет выполнен ввод. Для того чтобы обеспечить чтение всего файла, к количеству блоков добавляется 1 для округления после деления.

Вывод на экран выполняется посимвольно с помощью функции putchar.

Если требуется с помощью функций библиотеки вывести результаты выполнения программы не на экран, а в файл, в программе следует описать указатель на струк­туру FILE, с помощью функции fopen открыть файл для записи (второй параметр функции - w), а затем использовать этот указатель в соответствующих функциях вывода, например:

FILE *fout;

fout = fopen(textout.txt". "w");

setlocale( LC_ALL, "Russian" );

if (!fout)

{

puts("Ошибка открытия файла вывода");

return 1;

}

putc(buf[j], fout); // или fputc(buf[j], fout);

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

fclose(fout);

Смешивать в одной программе ввод-вывод с помощью потоковых классов и с по­мощью функций библиотеки не рекомендуется.

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

Пример 8.4. Вывод предложений, состоящих из заданного количества слов

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

Рисунок 8.1 - UML-диаграмма деятельности для примера 8.4

Листинг 8.5

#include "stdafx.h"

#include <iostream>

#include <fstream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

setlocale( LC_ALL, "Russian" );

cout<<"\n"

<<"Задание: Считать текст из файла. Вывести на экран только предложения, \n"

<<"\tсостоящие из заданного количества слов\n"

<<"----------------------------------------\n";

ifstream fin("text.txt",ios::in);

if (! fin)

{

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

return 1;

}

int nword;

cout<<"Введите искомое число слов в предложении: ";

cin>>nword;

fin.seekg(0,ios::end);

int len=fin.tellg();

char *buf=new char [len+1];

fin.seekg(0,ios::beg);

fin.read(buf,len);

buf[len]='\0';

int l_beg=0,i=0,n=0,j=0;

bool exist;

exist=false;

while (buf[i])

{

if (buf[i]==' ') n++;

if (buf[i]=='.')

{

n++;

if (n==nword)

{

for(j=l_beg;j<=i;j++)

cout<<buf[j];

exist=true;

cout<<endl;

}

l_beg=i+2;

i=i+2;

n=0;

}

i++;

}

if (!exist) cout<<"Таких предложений не найдено"<<endl;

fin.close();

return 0;

}

Рисунок 8.2 – Файл для входных данных

Пример 8.5. Вывод предложений, содержащих максимальное количество знаков пунктуации

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

Рисунок 8.3 - UML-диаграмма деятельности для примера 8.5

Листинг 8.6

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <locale>

using namespace std;

int main()

{ setlocale( LC_ALL, "Russian" );

locale loc ("Russian_Russia");

cout << "Задание:\nНаписать программу, которая считывает текст\n из файла и выводит на экран предложения, \n содержащие максимальное количество знаков пунктуации.\n";

/*устанавливаем русскую локаль - чтобы писать русскими буквами =)*/

//открываем файл для чтения

ifstream FileInput("file.txt",ios::in);

//если файл не обнаружен, то аварийно выходим

if (!FileInput)

{

cout << "Ошибка! Файл не открыт!" << endl;

return 1;

}

cout << "Текст,в котором осуществляется поиск предложения с max кол-вом знаков пунктуации\n";

cout << "Чтение из файла выполняется функцией fread(buf, size, num, file) блоками по size байт!Требуется также задать количество блоков num.В программе размер блока задан в переменной равным 1024, поскольку размер кластера кратен степени двойки.В общем случае чем более длинными блоками мы читаем информацию, тем быстрее будет выполнен ввод.Для того, чтобы обеспечить чтение всего файла, к количеству блоков добавляется 1 для округления после деления.\n";

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

FileInput.seekg(0,ios::end);

/*узнаем длину файла методом tellg(), который сообщает о позиции курсора в файле (т.е. сколько байт прошел курсор)*/

int LengthOfFile = FileInput.tellg();

//создаем переменную для хранения содержимого файла

char *str = new char [LengthOfFile+1];

//устанавливаем позицию курсора в начало файла

FileInput.seekg(0,ios::beg);

/*считываем содержимое файла в переменную str на заданное число байт LengthOfFile*/

FileInput.read(str,LengthOfFile);

//добавляем символ конца строки в переменную str

str[LengthOfFile]='\0';

/*pos - текущая позиция в файле;

counter - текущее кол-во пунктационных знаков;

max - текущее максимальное кол-во пунктационных знаков;

l - число символов в предложении;

begin, end - начало и конец предложения с макс. кол-вом пункт. знаков*/

int pos = 0,l = 0,end = 0,begin = 0;

int counter = 0,max = 0;

//поиск предложения c макс кол-вом пункт. знаков

while (str[pos])

{

/*если текущий символ явл-ся пунктационным, то счетчик увеличиваем на 1*/

if (ispunct(str[pos],loc)) counter++;

//если достигнут конец предложения, то...

if (str[pos]=='.' || str[pos]=='!' || str[pos]=='?')

/*...при условии максиммального кол-ва пунктационных символов вычисляем начало и конец данного предложения...*/

if (counter>max)

{

max = counter;

counter = 0;

/*здесь вычисляем начало предложения из текущего положения вычитаем кол-во прошедших символов*/

begin = pos - l;

end = pos;

l = 0;

}

/*...иначе обнуляем количество пунктационных символов и количество символов в пердложении*/

else {counter = 0; l = 0;}

l++;

pos++;

}

l = begin;

//Вывод предложения с максимальным количеством пунктационных знаков

for(l; l < end + 1; l++)

cout << str[l];

return 0;

}

Рисунок 8.4 – Файл для входных данных

Пример 8.6. Определение количества слов в файле, состоящих не более чем из четырех букв

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

Рисунок 8.5 - UML-диаграмма деятельности для примера 8.6

Листинг 8.7

// Лабораторная работа №_8

#include "stdafx.h"

#include <windows.h>

#include <fstream>

#include <string.h>

#include <ctype.h>

#include <iostream>

#include <conio.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

setlocale( LC_ALL, "Russian" );

int n, s, ss, i, ii;

const int len = 100;

char word[len], line[len];

cout<<"\t\tЛабораторная работа №_8\n\n";

cout<< " Написать программу, которая считывает текст из файла и определяет, сколько в нем слов, состоящих из не более чем четырех букв. \n" ;

cout<<"\nНажмте клавишу для продолжения...\n\n" ;

getch();

int lword = static_cast<int>(strlen(word));

ifstream fin("text.txt");

if (!fin)

{

cout << "Error opening file." <<endl;

return 1;

}

s = 0;

ss = 0;

int count = 0;

while (fin.getline(line,len))

{

char *p = line;

ii = strlen(p);

fin.seekg(0,ios::beg);

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

{

if (p[i]!='\x20') s++ ;

if (p[i]=='\x20')

{

if (s < 5)

{

ss++;

}

s = 0;

}

}

}

cout << "\nВ файле содержатся слова, содержащие не более 4-х букв в количестве " << ss << " шт.";

getch();

return 0;

}

Аппаратура и материалы. Для выполнения лабораторной работы необходим персональный компьютер со следующими характеристиками: процессор Intel Pentium-совместимый с тактовой частотой 800 МГц и выше, оперативная память - не менее 64 Мбайт, свободное дисковое пространство - не менее 500 Мбайт, устройство для чтения компакт-дисков, монитор типа Super VGA (число цветов от 256) с диагональю не менее 15. Программное обеспечение - операционная система Windows2000/XP и выше, среда разработки приложений Microsoft Visual Studio.

Указания по технике безопасности. Техника безопасности при выполнении лабораторной работы совпадает с общепринятой для пользователей персональных компьютеров, самостоятельно не производить ремонт персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки.

Методика и порядок выполнения работы. Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент отвечает на контрольные вопросы, приведенные в конце, и поясняет выполненное индивидуальное задание. Ход защиты лабораторной работы контролируется преподавателем. Порядок выполнения работы:

1.Проработать примеры, приведенные в лабораторной работе.

2. Составить программу с использованием двумерных локальных массивов для решения задачи. Размерности локальных массивов задавать именованны­ми константами, значения элементов массива - в списке инициализации. Номер варианта определяется по формуле , где - номер студента по списку преподавателя.

Индивидуальное задание №1. Вариант:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Содержание отчета и его форма. Отчет по лабораторной работе должен состоять из:

1. Названия лабораторной работы.

2. Цели и содержания лабораторной работы.

3. Ответов на контрольные вопросы лабораторной работы.

4. Формулировки индивидуальных заданий и порядка их выполнения.

Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю.

Вопросы для защиты работы

1. Характеристика видов строк в языке С++.

2. Как описываются строки?

3. Охарактеризуйте способы ввода-вывода строк.

4. Что делают функции gets () и puts ()?

5. Каким образом выполняется операция присваивания при работе со строками?

6. Какие функции предоставляет библиотека <string. h>? Какие действия они выполняют?

7. Охарактеризуйте способы ввода-вывода символов.

8. Какая функция используетя для многократного поиска вхождения подстроки?

9. Для чего нужна функция strtok?

10. Какие значения может принимать параметр org?

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

Пример выполнения лабораторной работы №8:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]