Перейти к содержимому

String c что это

  • автор:

String c что это

Мы можем работать со строками в С++ в так называемом С-стиле как с массивами символов, которые оканчиваются на нулевой байт ‘0’. Однако, что если такой символ не будет найден или в процессе манипуляций со строкой будет удален, то дальшейшие действия с такой строкой могут иметь недетерминированный результат. По этой причине строки в С-стиле считаются небезопасными, и рекомендуется для хранения строк в C++ использовать тип std::string из модуля .

Объект типа string содержит последовательность символов типа char, которая может быть пустой. Например, определение пустой строки:

std::string message;

Также можно инициализировать или присвоить переменной string конкретную строку:

std::string message ; // или так std::string message2 = "Hello METANIT.COM!"; std::string message3("Hello METANIT.COM!");

В данном случае переменная message получит копию строкового литерала «Hello METANIT.COM!». В своем внутреннем представлении переменная message будет хранить массив символов, который также заканчивается на нулевой байт. Однако реализация типа string и предлагаемые им возможности делают работу с этим типом более безопасной.

И можно инициализировать объект string другим объектом string:

std::string hello; std::string message ; // message = "hello world" // или так // std::string message (hello); // std::string message = hello;

Мы можем вывести подобную строку на консоль:

#include #include int main() < std::string message ; std::cout 

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

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

std::string hello ; char c ; // e hello[0]='M'; std::cout 

Поскольку объект string представляет последовательность символов, то эту последовательность можно перебрать с помощью цикла for. Например, подсчитаем, сколько раз в строке встречается буква "l":

#include #include int main() < unsigned count<>; // счетчик, сколько раз встречается символ std::string message< "Hello World">; for(const char c: message) < if(c == 'l') < count++; >> std::cout 

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

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

#include #include int main() < std::string name; std::cout > name; std::cout

Input your name: Tom Your name: Tom

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

Input your name: Tom Smith Your name: Tom

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

#include #include int main()

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

Input your name: Tom Smith Your name: Tom Smith

String c что это

Определяет шаблон basic_string класса контейнера и различные вспомогательные шаблоны.

Дополнительные сведения о basic_string классе см. в разделе basic_string "Класс"

Синтаксис

#include

Замечания

Язык C++ и библиотека Standard C++ поддерживают два типа строк:

  • Массивы символов, оканчивающиеся нулевым символов, часто называют строками C.
  • Объекты шаблона класса, тип basic_string , обрабатывающие все char аргументы шаблона, такие как.

Определения типов

Введите имя Description
string Тип, описывающий специализацию шаблона basic_string класса с элементами типа char в виде string .
wstring Тип, описывающий специализацию шаблона basic_string класса с элементами типа wchar_t в виде wstring .
u16string Тип, описывающий специализацию шаблона basic_string класса на основе элементов типа char16_t .
u32string Тип, описывающий специализацию шаблона basic_string класса на основе элементов типа char32_t .

Операторы

Operator Description
operator+ Сцепляет два строковых объекта.
operator!= Проверяет, что строковый объект слева от оператора не равен строковому объекту справа от оператора.
operator== Проверяет, равен ли строковый объект слева от оператора строковому объекту справа от оператора.
operator< Проверяет, что строковый объект слева от оператора меньше строкового объекта справа от оператора.
operator

Проверяет, что строковый объект слева от оператора меньше или равен строковому объекту справа от оператора.
operator

Функция шаблона, вставляющая строку в выходной поток.
operator> Проверяет, что строковый объект слева от оператора больше строкового объекта справа от оператора.
operator>= Проверяет, что строковый объект слева от оператора больше или равен строковому объекту справа от оператора.
operator>> Функция шаблона, извлекающая строку из входного потока.

Специализированные функции шаблонов

Имя Описание
hash Создает хэш строки.
swap Меняет местами массивы символов двух строк.
stod Преобразует последовательность символов в double .
stof Преобразует последовательность символов в float .
stoi Преобразует последовательность символов в int .
stold Преобразует последовательность символов в long double .
stoll Преобразует последовательность символов в long long .
stoul Преобразует последовательность символов в unsigned long .
stoull Преобразует последовательность символов в unsigned long long .
to_string Преобразует значение в string .
to_wstring Преобразует значение в расширенную строку.

Функции

Function Description
getline Шаблон string Извлеките строку по строке из входного потока.

Классы

Класс Description
basic_string Класса Шаблон класса, описывающий объекты, которые могут хранить последовательность произвольных символьных объектов.
char_traits Структура Шаблон класса, описывающий атрибуты, связанные с символом типа CharType

Специализации

Имя Описание
char_traits Структура Структура, которая является специализацией структуры char_traits шаблона для элемента типа char .
char_traits Структура Структура, которая является специализацией структуры char_traits шаблона для элемента типа wchar_t .
char_traits Структура Структура, которая является специализацией структуры char_traits шаблона для элемента типа char16_t .
char_traits Структура Структура, которая является специализацией структуры char_traits шаблона для элемента типа char32_t .

10.6 – Строки в стиле C

В уроке «4.12 – Знакомство с std::string » мы определили строку как набор последовательных символов, таких как "Hello, world!" . Строки – это основной способ работы с текстом в C++, а std::string упрощает работу с ними.

Современный C++ поддерживает два разных типа строк: std::string (как часть стандартной библиотеки) и строки в стиле C (изначально унаследованные от языка C). Оказывается, std::string реализована с использованием строк в стиле C. В этом уроке мы подробнее рассмотрим строки в стиле C.

Строки в стиле C

Строка в стиле C – это просто массив символов, в котором используется нулевой терминатор. Нулевой терминатор – это специальный символ ( '\0' , ASCII код 0), используемый для обозначения конца строки. В более общем смысле, строка в стиле C называется строкой с завершающим нулем.

Чтобы определить строку в стиле C, просто объявите массив char и инициализируйте его строковым литералом:

char myString[]< "string" >;

Хотя "string" состоит только из 6 букв, C++ автоматически добавляет нулевой терминатор в конец строки за нас (нам не нужно включать его самим). Следовательно, myString на самом деле представляет собой массив длиной 7!

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

#include #include // для std::size int main() < char myString[]< "string" >; const int length< static_cast(std::size(myString)) >; // const int length< sizeof(myString) / sizeof(myString[0]) >; // если C++17 не поддерживается std::cout ; index < length; ++index) std::cout << static_cast(myString[index])

Эта программа дает следующий результат:

string has 7 characters. 115 116 114 105 110 103 0

Этот 0 – это код ASCII нулевого терминатора, добавленного в конец строки.

При объявлении строк таким образом рекомендуется использовать [] и позволить компилятору самому вычислить длину массива. Таким образом, если позже вы измените строку, вам не придется изменять длину массива вручную.

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

char myString[]< "string" >; // хорошо myString = "rope"; // не нормально!

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

#include int main() < char myString[]< "string" >; myString[1] = 'p'; std::cout

Эта программа напечатает:

spring

При печати строки в стиле C std::cout печатает символы до тех пор, пока не встретит нулевой терминатор. Если вы случайно перезапишете нулевой терминатор строки (например, присвоив что-то элементу myString[6] ), вы получите не только все символы в строке, но std::cout просто продолжит печатать всё из соседних слотов памяти до тех пор, пока не наткнется на 0!

Обратите внимание, что это нормально, если массив по размеру больше, чем содержащаяся в нем строка:

#include int main() < char name[20]< "Alex" >; // используется только 5 символов (4 буквы + нулевой терминатор) std::cout

В этом случае будет напечатана строка "Alex" , и std::cout остановится на нулевом терминаторе. Остальные символы в массиве игнорируются.

Строки в стиле C и std::cin

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

В этом случае мы можем объявить массив больше, чем нам нужно:

#include int main() < char name[255]; // объявляем массив достаточно большим, чтобы вместить 255 символов std::cout > name; std::cout

В приведенной выше программе мы выделили для имени массив из 255 символов, предполагая, что пользователь не будет вводить столько много символов. Хотя это обычно встречается в программировании на C/C++, это плохая практика, поскольку ничто не мешает пользователю ввести более 255 символов (непреднамеренно или с умыслом).

Чтение строк в стиле C с помощью std::cin рекомендуется выполнять следующим способом:

#include #include // для std::size int main() < char name[255]; // объявляем массив достаточно большим, чтобы вместить 255 символов std::cout

Вызов cin.getline() считывает имя длиной до 254 символов (оставляя место для нулевого терминатора!). Любые лишние символы будут отброшены. Таким образом, мы гарантируем, что не переполним массив!

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

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

strcpy() позволяет копировать строку в другую строку. Чаще всего это используется для присвоения значения строке:

#include int main() < char source[]< "Copy this!" >; char dest[50]; std::strcpy(dest, source); std::cout 

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

#include int main() < char source[]< "Copy this!" >; char dest[5]; // обратите внимание, что длина dest всего 5 символов! std::strcpy(dest, source); // переполнение! std::cout

Многие программисты рекомендуют вместо этого использовать strncpy() , которая позволяет указать размер буфера и гарантирует, что переполнение не произойдет. К сожалению, strncpy() не гарантирует, что строки завершаются нулем, что по-прежнему оставляет много места для переполнения массива.

В C++11 предпочтительнее использование strcpy_s() , которая добавляет новый параметр для определения размера места назначения. Однако эту функцию поддерживают не все компиляторы, и для ее использования необходимо определить __STDC_WANT_LIB_EXT1__ целочисленным значением 1.

#define __STDC_WANT_LIB_EXT1__ 1 #include // для strcpy_s int main() < char source[]< "Copy this!" >; char dest[5]; // обратите внимание, что длина dest всего 5 символов! strcpy_s(dest, 5, source); // в режиме отладки произойдет ошибка времени выполнения std::cout

Поскольку strcpy_s() поддерживают не все компиляторы, популярной альтернативой является strlcpy() , даже несмотря на то, что она нестандартна и поэтому не включена во многие компиляторы. У нее также есть свой набор проблем. Короче говоря, если вам нужно скопировать строку в стиле C, универсального решения нет.

Еще одна полезная функция – функция strlen() , которая возвращает длину строки в стиле C (без нулевого терминатора).

#include #include #include // для std::size int main() < char name[20]< "Alex" >; // используется только 5 символов (4 буквы + нулевой терминатор) std::cout 

В приведенном выше примере напечатается:

My name is: Alex Alex has 4 letters. Alex has 20 characters in the array.

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

Другие полезные функции:

  • strcat() – добавляет одну строку к другой (опасно);
  • strncat() – добавляет одну строку к другой (с проверкой длины буфера);
  • strcmp() – сравнивает две строки (возвращает 0, если они равны);
  • strncmp() – сравнивает две строки до определенного количества символов (возвращает 0, если равны).

Вот пример программы, использующей некоторые концепции из этого урока:

#include #include #include // для std::size int main() < // Просим пользователя ввести строку char buffer[255]; std::cout ; int bufferLength< static_cast(std::strlen(buffer)) >; // Перебираем все символы, введенные пользователем for (int index< 0 >; index < bufferLength; ++index) < // Если текущий символ - это пробел, сосчитать его if (buffer[index] == ' ') ++spacesFound; >std::cout

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

Не используйте строки в стиле C

О строках в стиле C знать важно, потому что они используются во многих программах. Однако теперь, когда мы объяснили, как они работают, мы порекомендуем вам вообще избегать их, когда это возможно! Если у вас нет конкретной веской причины использовать строки в стиле C, используйте вместо них std::string (определенную в заголовке ). std::string проще, безопаснее и гибче. В редком случае, когда вам действительно нужно работать с фиксированными размерами буфера и строками в стиле C (например, для устройств с ограничением памяти), мы рекомендуем использовать хорошо протестированную стороннюю строковую библиотеку, разработанную для этой цели, или std::string_view , который рассматривается в следующем уроке.

Правило

Используйте std::string или std::string_view (следующий урок) вместо строк в стиле C.

Функции обработки строк в Cи

В программе строки могут определяться следующим образом:

  • как строковые константы;
  • как массивы символов;
  • через указатель на символьный тип;
  • как массивы строк.

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

Любая последовательность символов, заключенная в двойные кавычки "" , рассматривается как строковая константа .

Для корректного вывода любая строка должна заканчиваться нуль-символом '\0' , целочисленное значение которого равно 0. При объявлении строковой константы нуль-символ добавляется к ней автоматически. Так, последовательность символов, представляющая собой строковую константу, будет размещена в оперативной памяти компьютера, включая нулевой байт.

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

Для помещения в строковую константу некоторых служебных символов используются символьные комбинации. Так, если необходимо включить в строку символ двойной кавычки, ему должен предшествовать символ "обратный слеш": '\"' .

Строковые константы размещаются в статической памяти. Начальный адрес последовательности символов в двойных кавычках трактуется как адрес строки. Строковые константы часто используются для осуществления диалога с пользователем в таких функциях, как printf() .

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

Компилятор также может самостоятельно определить размер массива символов, если инициализация массива задана при объявлении строковой константой:

char m2[]= "Горные вершины спят во тьме ночной." ;
char m3[]=< 'Т','и','х','и','е',' ','д','о','л','и','н','ы',' ','п','о','л','н','ы',' ','с','в','е','ж','е','й',' ','м','г','л','о','й','\0' >;

В этом случае имена m2 и m3 являются указателями на первые элементы массивов:

  • m2 эквивалентно &m2[0]
  • m2[0] эквивалентно 'Г'
  • m2[1] эквивалентно 'o'
  • m3 эквивалентно &m3[0]
  • m3[2] эквивалентно 'x'

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

char m2[80]= "Горные вершины спят во тьме ночной." ;

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

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

m4 = m3;
*m4 эквивалентно m3[0]= 'Т'
*(m4+1) эквивалентно m3[1]= 'и'

Здесь m3 является константой-указателем. Нельзя изменить m3 , так как это означало бы изменение положения (адреса) массива в памяти, в отличие от m4 .

Для указателя можно использовать операцию увеличения (перемещения на следующий символ):

Массивы символьных строк

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

char *poet[4] = < "Погиб поэт!", "- невольник чести -" ,
"Пал," , "оклеветанный молвой…" >;

В этом случае poet является массивом, состоящим из четырех указателей на символьные строки. Каждая строка символов представляет собой символьный массив, поэтому имеется четыре указателя на массивы. Указатель poet[0] ссылается на первую строку:
*poet[0] эквивалентно 'П',
*poet[l] эквивалентно '-'.

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

char poet[4][23];

Разница заключается в том, что такая форма задает «прямоугольный» массив, в котором все строки имеют одинаковую длину.

Массив строк

Свободный массив

сhar *poet[4];

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

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

Большинство операций языка Си, имеющих дело со строками, работает с указателями. Для размещения в оперативной памяти строки символов необходимо:

  • выделить блок оперативной памяти под массив;
  • проинициализировать строку.

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

char *name;
name = ( char *)malloc(10);
scanf( "%9s" , name);

Для ввода строки использована функция scanf() , причем введенная строка не может превышать 9 символов. Последний символ будет содержать '\0' .

Функции ввода строк

Для ввода строки может использоваться функция scanf() . Однако функция scanf() предназначена скорее для получения слова, а не строки. Если применять формат "%s" для ввода, строка вводится до (но не включая) следующего пустого символа, которым может быть пробел, табуляция или перевод строки.

Для ввода строки, включая пробелы, используется функция

char * gets( char *);

или её эквивалент
char * gets_s( char *);

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

Функции вывода строк

Для вывода строк можно воспользоваться рассмотренной ранее функцией

printf( "%s" , str); // str — указатель на строку

или в сокращенном формате

Для вывода строк также может использоваться функция

int puts ( char *s);

которая печатает строку s и переводит курсор на новую строку (в отличие от printf() ). Функция puts() также может использоваться для вывода строковых констант, заключенных в кавычки.

Функция ввода символов

Для ввода символов может использоваться функция

char getchar();

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

Функция вывода символов

Для вывода символов может использоваться функция

char putchar( char );

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

Пример Посчитать количество введенных символов во введенной строке.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

#include
#include
#include
int main() char s[80], sym;
int count, i;
system( "chcp 1251" );
system( "cls" );
printf( "Введите строку : " );
gets_s(s);
printf( "Введите символ : " );
sym = getchar();
count = 0;
for (i = 0; s[i] != '\0' ; i++)
if (s[i] == sym)
count++;
>
printf( "В строке\n" );
puts(s); // Вывод строки
printf( "символ " );
putchar(sym); // Вывод символа
printf( " встречается %d раз" , count);
getchar(); getchar();
return 0;
>

Количество введенных символов в строке

Результат выполнения

Основные функции стандартной библиотеки string.h

Основные функции стандартной библиотеки string.h приведены в таблице.

char *strcat( char *s1, char *s2)
char *strncat( char *s1, char *s2, int n)
char *strсpy( char *s1, char *s2)
char *strncpy( char *s1, char *s2, int n)
int strcmp( char *s1, char *s2)
int strncmp( char *s1, char *s2, int n)
int strlen( char *s)
char *strset( char *s, char c)
char *strnset( char *s, char c, int n)

Пример использования функций

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
int main() char m1[80] = "Первая строка" ;
char m2[80] = "Вторая строка" ;
char m3[80];
system( "chcp 1251" );
system( "cls" );
strncpy(m3, m1, 6); // не добавляет '\0' в конце строки
puts( "Результат strncpy(m3, m1, 6)" );
puts(m3);
strcpy(m3, m1);
puts( "Результат strcpy(m3, m1)" );
puts(m3);
puts( "Результат strcmp(m3, m1) равен" );
printf( "%d" , strcmp(m3, m1));
strncat(m3, m2, 5);
puts( "Результат strncat(m3, m2, 5)" );
puts(m3);
strcat(m3, m2);
puts( "Результат strcat(m3, m2)" );
puts(m3);
puts( "Количество символов в строке m1 равно strlen(m1) : " );
printf( "%d\n" , strlen(m1));
_strnset(m3, 'f' , 7);
puts( "Результат strnset(m3, 'f' , 7)" );
puts(m3);
_strset(m3, 'k' );
puts( "Результат strnset(m3, 'k' )" );
puts(m3);
getchar();
return 0;
>

Использование функций

Результат выполнения

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *