
Поиск подстрок.
Кроме поиска символов в строке, вы также можете поохотиться и за подстроками. Этот пример демонстрирует этот метод. Данная программа аналогична предыдущей, но устанавливает расширение файла .ТХТ.
#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;
Домашнее задание:
Введите информацию о сотруднике: фамилия, имя, отчество, возраст, телефон. А потом вывести введенную информацию на экран. Вводится информация об имени и отчестве должна сразу и с пробелами и другими символами, аналогично и инфо о телефоне, использовать для ввода строк char массив.
Введите строку символов, используя char массив. Результат работы программы: вывод информации о длине строки (сколько символов), вывести первые 3 символа строки, а потом и последние 3 символа.
Запрос имени заказчика и заказываемого десерта. Информация вводится, а после выводится в предложении. Использовать класс string. Переделать desert.cpp
Напишите программу, которая запрашивает у пользователя имя, фамилию, а затем конструирует, сохраняет и отображает третью строку, состоящую из фамилии пользователя, за которой следует запятая, пробел и его имя. Используйте массивы char и функции из заголовочного файла cstring. Пример запуска должен выглядеть так:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string: Fleming, Flip
Напишите программу, которая приглашает пользователя ввести его имя и фамилию, а затем построит, сохранит и отобразит третью строку, состоящую из фамилии, за которой следует запятая, пробел и имя. Используйте объекты string и методы из заголовочного файла string. Пример запуска должен выглядеть так:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string: Fleming, Flip
Пользователю предлагается ввести строку из букв, цифр и разных знаков. Программа определяет количество букв в строке, количество цифр и количество знаков. Вся эта информация выводится на экран.
Пользователь вводит строку с клавиатуры в фиксированный массив. Необходимо проверить, cколько элементов массива теперь занято и сколько свободно.