Получение и изменение символов строки

Строки

 

В самом общем виде строка представляет собой массив символов, т.е. элементы такого массива имеют символьный тип char или wchar _ t (char 16_ t и char 32_ t используются намного реже). Тем не менее, обработка строк имеет свою специфику, связанную с тем, что количество символов в строке (длина строки) обычно становится известным только после того, как строка уже введена, а различные действия над строкой часто приводят к изменению её длины.

Как уже говорилось, в С++ имеется два основных способа работы со строками, основанных на разных способах их представления в памяти:

1. использование строк с завершающим нулём (С-строк) – способ, доставшийся в наследство от языка С, при котором строка описывается как обычный символьный массив, размер которого определяется исходя из ограничений задачи на максимальный размер вводимого текста;

2. использование типов string и wstring, определённых в стандартной библиотеке С++, не накладывающих ограничений на размер текста; для каких-то задач обработки текстов можно использовать и тип vector<char> (vector<wchar_t>).

Для использования типа string его необходимо подключить в код с помощью директивы include:

 

#include <string>

#include <iostream>

using namespace std;

int main()

{

string hello = "Hello World!";

cout << hello << "\n";

return 0;

}

 

Тип string определен в стандартной библиотеке и при его использовании надо указывать пространство имен std.

Либо можно использовать выражение using, чтобы не указывать префикс std:

 

1 using namespace std;

 

В данном случае значение переменной hello, которая представляет тип string, выводится на консоль.

Для инициализации строк можно использовать различные способы:

 

#include <string>

#include <iostream>

using namespace std;

int main()

{

string s1; // пустая строка

string s2 = "hello"; // hello

string s3("welcome"); // welcome

string s4(5, 'h'); // hhhhh

string s5 = s2; // hello

 

cout << s1 << "\n";

cout << s2 << "\n";

cout << s3 << "\n";

cout << s4 << "\n";

cout << s5 << "\n";

return 0;

}

 

Консольный вывод данной программы:

 

 

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

 

string s1;

 

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

 

string s2 = "hello";

 

В качестве альтернативы можно передавать строку в скобках после определения переменной:

 

string s3("welcome");

 

Если необходимо, чтобы строка содержала определенное количество определенных символов, то можно указать в скобках количество символов и сам символ:

 

string s4(5, 'h');

 

И также можно передать переменной копию другой строки:

string s5 = s2;

Конкатенация строк

Над строками можно выполнять ряд операций. В частности, можно объединять строки с помощью стандартной операции сложения:

#include <iostream>

using namespace std;

int main()

{

string s1 = "hello";

string s2 = "world";

string s3 = s1 + " " + s2; // hello world

cout << s3 << endl;

return 0;

}

Сравнение строк

 

К строкам можно применять операции сравнения. Оператор == возвращает true, если все символы обеих строк равны.

 

string s1 = "hello";

string s2 = "world";

 

bool result = s1 == s2; // false

result = s1 == "Hello"; // false

result = s1 == "hello"; // true

 

При этом символы должны совпадать в том числе по регистру.

Операция != возвращает true, если две строки не совпадают.

 

string s1 = "hello";

string s2 = "world";

 

bool result = s1 != s2; // true

result = s1 != "Hello"; // true

result = s1 != "hello"; // false

 

Остальные базовые операции сравнения <, <=, >, >= сравнивают строки в зависимости от регистра и алфавитного порядка символов. Например, строка "b" условно больше строки "a", так как символ b по алфавиту идет после символа a. А строка "a" больше строки "A". Если первые символы строки равны, то сравниваются последующие символы:

 

string s1 = "Aport";

string s2 = "Apricot";

bool result = s1 > s2; // false

 

В данном случае условие s1 > s2 ложно, то есть s2 больше чем s1, так как при равенстве первых двух символов ("Ap") третий символ второй строки ("o") стоит в алфавите до третьего символа второй строки ("p"), то есть "o" меньше чем "p".

Размер строки

 

С помощью метода size() можно узнать размер строки, то есть из скольких символов она состоит:

 

string s1 = "hello";

cout << s1.size() << endl; // 5

 

Если строка пустая, то она содержит 0 символов. В этом случае мы можем применить метод empty() - он возвращает true, если строка пустая:

string s1 = "";

if(s1.empty())

cout << "String is empty" << endl;

Чтение строки с консоли

Для считывания введенной строки с консоли можно использовать объект cin:

 

#include <iostream>

#include <string>

using namespace std;

int main()

{

string name;

cout << "Input your name: ";

cin >> name;

cout << "Your name: " << name << endl;

return 0;

}

 

Консольный вывод:

 

 

Однако если при данном способе ввода строка будет содержать подстроки, разделенные пробелом, то std::cin будет использовать только первую подстроку:

 

 

Чтобы считать всю строку, применяется метод getline():

 

#include <iostream>

#include <string>

using namespace std;

int main()

{

string name;

cout << "Input your name: ";

getline(cin, name);

cout << "Your name: " << name << endl;

return 0;

}

 

Метод getline принимает два объекта - cin и переменную, в которую надо считать строку.

Консольный вывод:

 

 

Получение и изменение символов строки

 

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

string hello = "Hello";

char c = hello[1]; // e

hello[0]='M';

cout << hello << endl; // Mello

Символьные массивы

Массив символов, последний элемент которого представляет нулевой символ '\0', может использоваться как строка:

 

#include <iostream>

using namespace std;

int main()

{

char letters[] = {'h', 'e', 'l', 'l', 'o', '\0'};

cout << letters << endl;

 

return 0;

}

 

Данный код выведет на консоль строку "hello". Подобное определение массива строк будет также эквивалентно следующему:

 

char letters[] = "hello";

 

 

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

Пусть требуется удалить все пробелы из введённой строки текста.

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

 

 Пример – удаление пробелов из строки

// с использованием вспомогательной строки

#include <iostream>

using namespace std;

int main()

{

int r=0,i=0; char s[80],s1[80];

cout<<"?"; cin.getline(s,80);

// перепишем в s1 все символы, кроме пробелов

for(i=0;s[i]!=0;i++)

if (s[i]!=' ') s1[r++]=s[i];

s1[r]=0; // нельзя забыть про завершающий нуль

for (i=0;s1[i]!=0;i++) s[i]=s1[i];

s[i]=0; // скопировали s1 обратно в s

cout<<s<<endl; system("pause"); return 0;

}

 

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

 

Пример – удаление пробелов из строки

// без использования вспомогательной строки

#include <iostream>

using namespace std;

int main()

{

int r=0,i=0; char s[80];

cout<<"?"; cin.getline(s,80);

for (i = 0; s[i] != 0 && s[i] != ' '; i++);// ищем первый пробел

for (int j = i; s[j] != 0; j++) {

if (s[j] != ' ') {

s[i] = s[j];// передвигаем символы внутри строки

i++;

}

}

s[i] = 0;

cout<<s<<endl; system("pause"); return 0;

}

 

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

 

Управление строками C-style

C++ предоставляет множество функций для управления строками C-style, которые подключаются с помощью заголовочного файла cstring. Вот несколько самых полезных функций:

Функция strcpy_s() позволяет копировать содержимое одной строки в другую. Чаще всего это используется для присваивания значений строке:

 

#include <iostream>

#include <cstring>

using namespace std;

int main()

{

char text[] = "Print this!";

char dest[50];

strcpy_s(dest, text);

cout << dest; // выводим "Print this!"

 

return 0;

}

 

Тем не менее, использование strcpy_s() может легко вызвать переполнение массива, если не быть осторожным! В следующей программе, длина массива dest меньше длины копируемой строки, поэтому в результате мы получим переполнение массива:

 

#include <iostream>

#include <cstring>

using namespace std;

int main()

{

char text[] = "Print this!";

char dest[5]; // обратите внимание, длина массива dest всего 5 символов!

strcpy_s(dest, text); // переполнение!

cout << dest;

 

return 0;

}

 

Ещё одной полезной функцией управления строками является функция strlen(), которая возвращает длину строки C-style (без учёта нуль-терминатора):

 

#include <iostream>

#include <cstring>

using namespace std;

int main()

{

char name[15] = "Max"; // используется только 4 символа (3 буквы + нуль-терминатор)

cout << "My name is " << name << '\n';

cout << name << " has " << strlen(name) << " letters.\n";

cout << name << " has " << sizeof(name) << " characters in the array.\n";

 

return 0;

}

 

Результат выполнения программы выше:

 

 

Обратите внимание на разницу между strlen() и sizeof(). strlen() выводит количество символов до нуль-терминатора, тогда как оператор sizeof() возвращает размер целого массива, независимо от того, что в нём находится.

Вот ещё полезные функции для управления строками C-style:

strcat() — добавляет одну строку к другой (опасно);

strncat() — добавляет одну строку к другой (с проверкой размера места назначения);

strcmp() — сравнивает две строки (возвращает 0, если они равны);

strncmp() — сравнивает две строки до определённого количества символов (возвращает 0, если они равны).

Например:

#include <iostream>

#include <cstring>

using namespace std;

int main()

{

// Просим пользователя ввести строку

char buffer[255];

cout << "Enter a string: ";

cin.getline(buffer, 255);

 

int spacesFound = 0;

// Перебираем каждый символ, который ввёл пользователь

for (int index = 0; index < strlen(buffer); ++index)

{

// Подсчитываем количество пробелов

if (buffer[index] == ' ')

spacesFound++;

}

 

cout << "You typed " << spacesFound << " spaces!\n";

 

return 0;

}


Дата добавления: 2020-11-23; просмотров: 99; Мы поможем в написании вашей работы!

Поделиться с друзьями:




Мы поможем в написании ваших работ!