Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
L_r_05.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
96.26 Кб
Скачать

Лабораторная работа № 5. Решение задач с использованием строковых литералов

1. Цель работы

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

  1. Подготовка к работе

Изучить правила организации . Необходимо знать основные особенности представления строковых литералов в языке С++ [лекции 10, 14].

  1. Теоретическая часть:

В С++ есть два вида стрк:

  • С-строки (символьные);

  • класс стандартной библиотеки С++ string.

С-строка – это массив символов, завершающийся символом с кодом 0 (нуль-терминатором). Класс string более безопасен в использовании, но и более ресурсоемок, чем С-строки.

Описание строк. Длина динамической строки может быть выражением, не динамической строки – константным выражением (чаще всего константой):

const int len_s = 80;

char s[len_s]; //хранится 79 символов + 0-терминатор

При задании строки необходимо учитывать 0-терминатор.

Строки при описании можно инициализировать строковыми константами:

char a[100] = “Строковая константа”;

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

char a[] = “Строковая константа”; // выделено под 20 символов

Для размещения строки в динамической памяти:

char *p = new char[m]; // p – указатель на char

char *q = (char *)malloc(m * sizeof(char));

Динамические строки нельзя инициализировать при создании. Оператор

char *str = “Строковая константа”;

создает не строковую переменную, а указатель на строковую константу, изменить которую невозможно.

Ввод – вывод строк.

  • для ввода строки, состоящей из одного слова (ввод до первого пробельного символа: пробела, знака табуляции, символа перевода строки) используется cin:

const int n = 80;

char s[n];

cin >> s; cout << s << endl;

  • для ввода строки, состоящей из нескольких слов, используются методы getline или get класса istream, объектом которого является cin. Для вызова метода после имени объекта ставится точка, а затем пишется имя метода:

const int n = 80;

char s[n];

cin.getline(s,n); cout << s << endl;

cin.get(s,n); cout << s << endl;

Метод getline считывает из входного потока (n-1) символов или менее (если символ перевода строки встретиться ранее) и записывает их в строковую переменную s. Символ перевода строки (он же ‘\n’, появляется во входном потоке при нажатии клавиши Enter) также сичтывается (удаляется) из входного потока, вместо него размещается завершающий нуль-терминатор.

Метод get работает аналогично, но оставляет в потоке символ перевода строки. В строковую переменную добавляется завершающий нуль-терминатор.

Нельзя обращаться к методу get с двумя аргументами два раза подряд, не удалив ‘\n’ из входного потока. Это возможно вызовом метода get без параметров:

cin.get(s,n); cout << s << endl;

cin.get(); // убрали ‘\n’

cin.get(s,n); cout << s << endl;

  • для ввода нескольких строк удобно использовать метод getline в заголовке цикла:

const int n = 80;

char s[n];

while (cin.getline(s,n)) {

cout << s << endl;

… }

  • для ввода строки (до тпервого пробельного символа) можно использовать функцию scanf(), а для вывода - printf(), задав спецификацию формата ‘%s:

const int n = 80;

char s[n];

scanf(“%s”, s); printf(“%s”, s);

  • чтобы ввечти строку из нескольких слов используется спецификация ‘%cс указанием максимального количества вводимых символов:

scanf(“%80с”, s);

  • при выводе можно задать количество позиций, отводимых под строку; строка при этом выравнивается по правому краю отведенного поля:

printf(“%80s”, s);

  • для ввода-вывода строк используются также специальные функции gets() и puts():

const int n = 80;

char s[n];

gets(s); puts(s);

Функция gets(s) читает символы с клавиатуры до появления символа новой строки и помещает их в строку s (сам символ в строку не включается, вместо него в строку заносится нуль-символ). Функция возвращает указатель на строку s, а в случае возникновения ошибки или конца файла – NULL.

Функция puts(s) выводит строку s на стандартное устройство вывода, заменяя завершающий нуль-терминатор символом новой строки. Возвращает неотрицательное значение при успехе или EOF (признак конца файла) при ошибке.

Операции со строками.

  • присваивание выполняется с помощью функций стандартной библиотеки или посимвольно «вручную». Например, чтобы присвоить строке р строку а можно воспользоваться функциями strcpy() или strnсpy():

char a[100] = “Строковая константа”;

char *p = new char [m];

strcpy(p,a);// копирование всех символов строки а + «\0» в р

strncpy(p,a,strlen(a)+1); //копирование указанного количества //(strlen(a)+1)символов строки а в строку р

Для использования этих функций следует подключить заголовочный файл <string.h>.

Функция strlen(a) возвращает фактическую длину строки а не включая нуль-символ.

  • для преобразования строки в целое число используется функция atoi(), в длинное целое – atol(), в вещественное число с двойной точностью – atof().

Пример применения функций преобразования:

char a[]= “10) Рост – 162 см, вес – 59.5 кг”;

int num;

long rost;

double ves;

num = atoi(a);

rost = atol(&a[11]);

ves = atof(&a[25]);

cout << num << ‘ ‘ << rost << ‘ ‘ << ves;

Работа с символами.

Для хранения отдельных символов используются переменные типа char. Их ввод – вывод также может выполняться как с помощью классов ввода-вывода, так и с помощью функций библиотеки.

При использовании классов ввод – вывод осуществляется с помощью операций помещения в поток >> и извлечения потока <<, так и методов get() и get(char):

#include <iostream.h>

int main(){

char c, d, e;

cin >> c; // так ввести пробел нельзя

cin >> d >> e;

cout << c << d << e;

c = cin.get(); //возвращает код символа в с

cin.get(d); cin.get(e); // запись символов d и е в переменные

cout << c << e;

return 0;}

В заголовочном файле <stdio.h> определены функции для стандартного ввода (getchar()) и вывода (putchar())

char c, d;

c = getchar();

d = getchar(); putchar(d);

Рассмотрим примеры:

  1. Поиск подстроки.

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

Так как переносы отсутствуют, то текст умещается в одной строке. Для ее хранения выделим строковую переменную длиной в 81 символ (дополнительный для нуль-символа).

Последовательность символов, не содержащая пробелов, длиной так же должна быть не более 80 символов, иначе поиск завершится неудачей. Для ее хранения тоже вывделим строковую переменную, длиной 81 символ.

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

#include <string.h>

int main(){

const int len = 81; // длина строки и последовательности

char word[len], line[len]; // описание строки и

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

cout<<”Введите строку не более 80 симв”;

cin.getline(line, len);

cout<<”Введите слово для поиска”; cin >> word;

if (strstr(line, word)) // поиск последовательности в строке

cout<<”Присутствует!” << endl;

else

cout<<”Отсутствует!” << endl;

return 0; }

  1. Подсчет количества вхождений слова в строку.

Написать программу, определяющую сколько раз встретилось заданное слово в строке. Длина строки не превышает 80 символов. Текст не содержит переносов слов.

Цель данной задачи состоит в том, чтобы после первого удачного поиска не выходить из цикла просмотра, а увеличить счетчик и продолжить просмотр. Результатом работы программы является количество вхождение слова в текст. Его представим в виде целой переменной.

Слово может находиться либо в начале строки, либо после разделителя или знака пунктуации. Определим слово схематически:

слово =

{начало строки | знак пунктуации | разделитель}

символы, составляющие слово

{конец строки | знак пунктуации | разделитель}

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

При обнаружении совпадения с символами, составляющими слово, требуется определить, является ли оно самостоятельным словом или частью другого слова (например, искомое слово «кот» может содержаться в словах «котенок», «трикотаж», «трескотня» и т.д.). Следовательно, нужно проверить символ, стоящий после слова, и если слово не находится в начале строки, то и символ перед ним. Эти символы проверяются на принадлежность множеству знаков пунктуации и разделителей.

. . .

int main(){

const int len = 81;

char word[len], line[len];

cout<<”Введите строку не более 80 симв”;

cin.getline(line, len);

cout<<”Введите слово для поиска”; cin >> word;

int l_word = strlen(word); // длина слова

int count = 0; // счетчик количества вхождений

char *p = line; // указатель устанавливаем на начало строки

while( p = strstr(p, word)){

char *c = p; // указатель устанавливаем на начало слова в

p += l_word; // указатель перемещаем на длину введенного

// слова

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

if (c != line)

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

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

// символ после слова разделитель?

if(ispunct(*p) || isspace(*p) || (*p ==’\0’)) count++;

}

cout << “Кол-во вхождений слова”<< count << endl;

return 0;

}

В рассмотренном примере вводится служебная переменная с для хранения адреса начала вхождения подстроки. Символы, ограничивающие слово, проверяются с помощью функций, хранящихся в заголовочном файле <ctype.h>. Следующий за словом символ проверяется также на признак конца строки (нуль-символ).

Для многократного поиска вхождения подстроки в заголовке цикла используется функция strstr(). Очередной поиск должен выполняться с позиции, следующей за найденной на предыдущем шаге подстрокой. Для хранения этой позиции определяется вспомогательный указатель р, который на каждой итерации цикла наращивается на длину подстроки.

Давайте теперь рассмотрим другой вариант решения этой задачи. В С++ есть функция strtok(), которая разбивает переданную ей строку на лексемы (слова) в соответствии с заданным набором разделителей. Теперь нам не придется выделять и проверять начало и конец слова «вручную», а лишь сравнить с искомым словом слово, выделенное с помощью strtok(). Правда список разделителей придется задать вручную.

. . .

int main(){

const int len = 81;

char word[len], line[len];

cout<<”Введите строку не более 80 симв”;

cin.getline(line, len);

cout<<”Введите слово для поиска”; cin >> word;

char razdel[] = “,.!/”?<>)(|\*;:”; // ввод разделителей

int count = 0; // счетчик количества вхождений

char *token;

token = strtok(line, razdel); // адрес 1-го слова

while( token != NULL){

/* strtok заменяет на NULL разделитель, наход-ся после

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

if(!strcmp(token, word)) count++; // сравнение слов

token = strtok(NULL, razdel); // поиск следующего слова

}

cout << “Кол-во вхождений слова”<< count << endl;

return 0;

}

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