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

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

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

#include <iostream>

#include <string.h>

#include <stdio.h>

using namespace std;

void main()

{

char *filename = new char[128],*p;

cout << "Enter name of file: ";

gets(filename);

cout << "\nName of file: " << filename << "\n";

strupr(filename);

p = strstr (filename,".TXT");

if (p)

cout << "Name has extension" << "\n";

else

{ p = strchr (filename,'.');

if (p)

*p=NULL; //Удалить любое другое расширение.

strcat (filename,".TXT");

}

cout << "Name of file: " << filename << "\n";

delete [] filename;

}

Эта программа создает имя файла, которое обязательно заканчивается расширением .ТХТ. Чтобы определить, есть ли в имени файла это расширение, программа выполняет оператор

p = strstr (filename,".TXT");

Подобно strchr(), функция strstr() возвращает адрес подстроки или нуль, если искомая строка не найдена. Если же цель будет обнаружена, указатель p установится равным ее адресу, в данном примере - адресу точки в подстроке .ТХТ. Поскольку расширение может быть введено и строчными буквами, программа выполняет оператор

strupr(filename);

чтобы перед вызовом функции strstr() преобразовать буквы оригинальной строки в прописные.

Пример также демонстрирует способ усечения строки в позиции заданного символа или подстроки. Здесь вызывается функция strstr(), чтобы установить указатель p равным адресу первой точки в строке filename. Если результат этого поиска не нулевой, то выполнится оператор, который запишет вместо точки нулевой байт:

*p = NULL;

Тем самым будет присоединен новый конец строки в том месте, где раньше находилось расширение файла. Теперь строка готова к добавлению нового расширения путем вызова функции strcat()

Программа для замены в слове X всех букв "a" на сочетание "ky".

#include <string.h>

#include <stdio.h>

void main ()

{

/*

k - переменная для прохода по оригинальному массиву

i - переменная для прохода по результативному массиву

n - длина оригинального массива

*/

int k=0,i=0, n;

/*

x1 - оригинальный массив

x2 - результативный массив (больше в два раза, на

случай, если оригинальный весь заполнен буквами 'a')

px1 - указатель для перемещения по оригинальному массиву

px2 - указатель для перемещения по результативному массиву

*/

char x1[40],x2[80],*px1,*px2;

// Запрос на ввод оригинального массива

puts( "Enter word (max 39 letters) ");

gets(x1);

/*

записываем адреса начала

оригинального и результативного

массивов в указатели

*/

px1 = x1;

px2 = x2;

/*

вычисляем рельную длину

оригинального массива

*/

n = strlen(x1)+1;

// цикл поэлементно перебирает

// оригинальный массив

while (k<n)

{

// если значение текущего элемента

// не совпадает с 'a'

if (*(px1+k)!='a')

{

// копируем текущий элемент

// в результативный массив

*(px2+i) = *(px1+k);

// переходим к следующим элементам

i++;

k++;

}

// если значение текущего элемента

// совпадает с 'a'

else

{

// записываем символ 'k' в текущую

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

*(px2+i) = 'k';

// записываем символ 'y' в следующую

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

*(px2+i+1) = 'y';

// переходим к следующему элементу

// оригинального массива

k++;

// "перепрыгиваем" через один элемент

// результативного массива

i += 2;

}

}

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

puts(x2);

}

Программa для замены всех сочетаний "ky" в слове X на букву "a".

#include <string.h>

#include <stdio.h>

void main ()

{

/*

k - переменная для прохода по оригинальному массиву

i - переменная для прохода по результативному массиву

n - длина оригинального массива

*/

int k=0,i=0, n;

/*

x1 - оригинальный массив

x2 - результативный массив

px1 - указатель для перемещения по оригинальному массиву

px2 - указатель для перемещения по результативному массиву

*/

char x1[40],x2[40],*px1,*px2;

// Запрос на ввод оригинального массива

puts( "Enter word (max 39 letters) ");

gets(x1);

/*

записываем адреса начала

оригинального и результативного

массивов в указатели

*/

px1 = x1;

px2 = x2;

/*

вычисляем рельную длину

оригинального массива

*/

n = strlen(x1)+1;

// цикл поэлементно перебирает

// оригинальный массив

while (k<n)

{

// проверяем, если два символа

// в текущей позиции оригинального

// массива не совпадают с буквосочетанием "ky"

if (strncmp((px1+k),"ky",2)!=0)

{

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

// из текущей позиции в

// результативный массив и

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

*(px2+i++) = *(px1+k++);

}

// если же два символа

// в текущей позиции оригинального

// массива совпадают с буквосочетанием "ky"

else

{

// записываем в результативный массив

// символ 'a', и переходим на один

// символ вперед. В оригинальном переходим

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

*(px2+i++) = 'a';

k += 2;

}

}

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

puts(x2);

}

Программa, удваивающая каждую букву слова Х.

#include <string.h>

#include <stdio.h>

void main ()

{

// n - длина оригинального массива *2

int n;

/*

x1 - оригинальный массив

x2 - результативный массив (больше в два раза)

px1 - указатель для перемещения по оригинальному массиву

px2 - указатель для перемещения по результативному массиву

*/

char x1[40],x2[80],*px1,*px2;

// Запрос на ввод оригинального массива

puts( "Enter word (max 39 letters) ");

gets(x1);

/*

записываем адреса начала

оригинального и результативного

массивов в указатели

*/

px1 = x1;

px2 = x2;

/*

вычисляем двойную длину

оригинального массива

*/

n = 2*strlen(x1);

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

// результативного массива '\0'

*(px2+n) = '\0';

// цикл поэлементно перебирает

// оригинальный массив

while ((*px1)!='\0')

{

// записываем значение из текущей позиции

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

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

// переходим на один элемент вперёд

*px2++ = *px1;

// записываем значение из текущей позиции

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

// результативного массива, в обоих массивах

// переходим на один элемент вперёд

*px2++ = *px1++;

}

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

puts(x2);

}

Функции и строки в стиле С

Функции с аргументами — строками в стиле С

Предположим, что требуется передать строку функции в виде аргумента. Доступны три варианта представления строки:

• массив char;

• константная строка в двойных кавычках (также называемая строковым литералом)',

• указатель на char, установлены в адрес начала строки.

Все три варианта, однако, являются типом указателя на char (или, короче, тип char *), поэтому все три можно использовать в качестве аргументов функций, обрабатывающих строки:

char ghost[15] = "galloping";

char * str = "galumphing";

int nl = strlen (ghost) ; // ghost - это &ghost[0]

int n2 = strlen (str); // указатель на char

int n3 = strlen("gamboling"); // адрес строки

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

Одно важное отличие между строкой в стиле С и обычным массивом состоит в том, что строка имеет встроенный ограничивающий нулевой символ. (Вспомните, что массив char, который содержит символы, но не содержит нулевой символ — это просто массив, а не строка.) Это значит, что вы не должны передавать размер строки в качестве аргумента. Вместо этого функция может использовать цикл для поочередного чтения каждого символа строки до тех пор, пока не будет достигнут ограничивающий нулевой символ.

Пример задачи.

#include <iostream>

using namespace std;

unsigned int c_in_str (const char * str, char ch);

void main()

{

setlocale (LC_CTYPE, "russian");

char mmm[15] = "minimum"; // строка в массиве

// Некоторые системы требуют предварить char словом static,

// чтобы разрешить инициализацию массива

char *wail = "ululate"; // wail указывает на строку

unsigned int ms = c_in_str (mmm, 'm');

unsigned int us = c_in_str(wail, 'u');

cout << ms << " m characters in " << mmm << endl; // вывод количества символов m

cout << us << " u characters in " << wail << endl; // вывод количества символов и

}

// Эта функция подсчитывает количество символов ch в строке str

unsigned int c_in_str (const char * str, char ch)

{

unsigned int count = 0;

while (*str) // завершение, когда *str равно '\0'

{

if (*str == ch)

count++;

str++; // перемещение указателя на следующий символ

}

return count;

}

Вывод:

3 m characters in minimum

2 u characters in ululate

Для продолжения нажмите любую клавишу . . .

Сама функция демонстрирует стандартный способ обработки символов в строке:

while (*str)

{

операторы

str++;

}

Изначально str указывает на первый символ строки, поэтому *str представляет сам первый символ. Например, непосредственно после первого вызова функции *str имеет значение m — первый символ в minimum. До тех пор, пока символ не является нулевым (\0), *str не равно нулю и цикл продолжается. В конце каждого шага цикла выражение str++ увеличивает указатель на 1 байт, так что он указывает на следующий символ в строке. В конечном итоге str указывает на завершающий нулевой

символ, что делает *str равным нулю, и цикл прекращается.

Функции, возвращающие строки в стиле С

Теперь предположим, что требуется написать функцию, возвращающую строку. Конечно, функция может это сделать. Но она может вернуть адрес строки, и это наиболее эффективно. Например, листинг 7.10 определяет функцию buildstr (), возвращающую указатель. Эта функция принимает два аргумента: символ и число. Используя new, она создает строку, длина которой равна переданному числу, и инициализирует каждый ее элемент значением переданного символа. Затем она возвращает указатель на эту новую строку.

функция, возвращающая указатель на char

#include <iostream>

using namespace std;

char * buildstr(char c, int n) ; // прототип

void main()

{

setlocale (LC_CTYPE, "russian");

int times;

char ch;

cout << "Enter a character: "; // ввод символа

cin >> ch;

cout << "Enter an integer: "; // ввод целого числа

cin >> times;

char *ps = buildstr (ch, times) ;

cout << ps << endl;

delete [] ps; // освобождение памяти

ps = buildstr(' + ', 20) ; // повторное использование указателя

cout << ps << "-DONE-" << ps << endl;

delete [] ps; // освобождение памяти

}

// Строит строку из п символов с

char * buildstr(char c, int n)

{

char * pstr = new char[n + 1];

pstr[n] = '\0'; // завершение строки

while (n-- > 0)

pstr[n] = c; // заполнение остатка строки

return pstr;

}

Вывод:

Enter a character: #

Enter an integer: 10

##########

-DONE-

Для продолжения нажмите любую клавишу . . .

Использование противоположного порядка потребовало бы примерно такого кода:

int i = 0;

while (i < n)

pstr[i++] = c;

Обратите внимание, что переменная pstr является локальной по отношению к функции buildstr (), поэтому, когда эта функция завершается, память, занятая pstr (но не самой строкой), освобождается. Но поскольку функция возвращает значение pstr, программа имеет возможность получить доступ к новой строке через указатель ps в main().

Функции и объекты класса string

Хотя строки в стиле С и класс string служат в основном одним и тем же целям, класс string больше похож на структуру, чем на массив. Например, структуру можно присвоить другой структуре, а объект — другому объекту. Структуру можно передавать как единую сущность в функцию, и точно так же можно передавать объект. Когда требуется несколько строк, можно объявить одномерный массив объектов string вместо двумерного массива char.

В листинге представлен короткий пример, в котором объявляется массив объектов string и передается функции, отображающей их содержимое.

#include <iostream>

#include <string>

using namespace std;

const int SIZE = 5;

void display(const string sa[], int n);

void main()

{

setlocale (LC_CTYPE, "russian");

string list[SIZE]; // массив из 5 объектов string

cout << "Enter your " << SIZE << " favorite astronomical sights:\n";

// Ввод астрономических объектов

for (int i = 0; i < SIZE; i++)

{

cout << i + 1 << " : ";

getline (cin,list[i]);

}

cout << "Your list:\n"; // вывод списка астрономических объектов

display (list, SIZE);

}

void display(const string sa[], int n)

{

for (int i = 0; i < n; i++)

cout << i + 1 << " : " << sa[i] << endl;

}

Вывод:

Enter your 5 favorite astronomical sights:

1 : eath

2 : moon

3 : venera

4 : saturn

5 : mars

Your list:

1 : eath

2 : moon

3 : venera

4 : saturn

5 : mars

Для продолжения нажмите любую клавишу . . .

Если вам нужен массив string, вы просто используете обычный формат объявления массива:

string list[SIZE]; // массив из 5 объектов string

Каждый элемент массива list — это объект string, и он может использоваться следующим образом:

getline(cin,list[i]);

Аналогично, формальный аргумент sa является указателем на объект string, поэтому sa [і] — объект типа string, и он может использоваться соответственно:

cout « і + 1 « ": " « sa[i] « endl;

Домашнее задание:

  1. Введите информацию о сотруднике: фамилия, имя, отчество, возраст, телефон. А потом вывести введенную информацию на экран. Вводится информация об имени и отчестве должна сразу и с пробелами и другими символами, аналогично и инфо о телефоне, использовать для ввода строк char массив.

  1. Введите строку символов, используя char массив. Результат работы программы: вывод информации о длине строки (сколько символов), вывести первые 3 символа строки, а потом и последние 3 символа.

  1. Запрос имени заказчика и заказываемого десерта. Информация вводится, а после выводится в предложении. Использовать класс string. Переделать desert.cpp

  1. Напишите программу, которая запрашивает у пользователя имя, фамилию, а затем конструирует, сохраняет и отображает третью строку, состоящую из фамилии пользователя, за которой следует запятая, пробел и его имя. Используйте массивы char и функции из заголовочного файла cstring. Пример запуска должен выглядеть так:

Enter your first name: Flip

Enter your last name: Fleming

Here's the information in a single string: Fleming, Flip

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

Enter your first name: Flip

Enter your last name: Fleming

Here's the information in a single string: Fleming, Flip

  1. Пользователю предлагается ввести строку из букв, цифр и разных знаков. Программа определяет количество букв в строке, количество цифр и количество знаков. Вся эта информация выводится на экран.

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

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