Всё дело в древности неправильного обращения со строками в Си. Во всех начальных уроках показывают так:
char * str = "Hello world" ; int str_len = strlen(str);
Это очень неправильно. Здесь в переменную записывается указатель на первую букву , а программа не знает какой длины строка и вызывается функция strlen . И даже массив служебный, основываясь на длине этой строки невозможно создать, так-как это число не константа.
Правильно записывать так :
char const str[]="Hello again"; int const str_len = sizeof(str)-1; bool arr[sizeof(str)-1];
Здесь совершенно всё по-другому. str - это массив фиксированной длины включая завершающий символ '\0' . Количество значащих букв по-этому меньше на одну. Размер строки и массива определена в момент компиляции и по-этому можно создать нужный вспомогательный массив. А так-же если-что передать размер строки в другие функции без использования strlen . Чтобы передать строку в функцию придётся обойтись указателем (сам массив целиком нельзя) и размер (известный во время компиляции).
// gcc -Wall -Wpedantic -std=c11 -Os cor_str.c # include # include typedef struct < char const * str; size_t len ; >Str ; void f(Str s) < printf("f:s.str=%s\n",s.str); printf("f:s.len=%ld\n",s.len); >int main() < char const * old_s = "123"; // размер строки без конечного символа '\0' // вычисляется в момент выполнения программы printf("strlen(old_s)=%ld\n",strlen(old_s)); // storage size of ‘old_arr’ isn’t constant // static char old_arr[strlen(old_s)]; // размер указателя printf("sizeof(old_s)=%ld\n",sizeof(old_s)); // размер массива с конечным char '\0' // вычисляется в момент компиляции // строка засунута в код // char const cor_s[]="abc"; // строка есть программе static char const cor_s[]="abc"; printf("sizeof(cor_s)=%ld\n",sizeof(cor_s)); printf("cor_s=%s\n",cor_s); static char cor_arr[sizeof(cor_s)]; Str s = ; f(s); >
Строковые и символьные литералы (C++)
В C++ поддерживаются различные типы строк и символов, а также доступны различные способы выражения значений литералов каждого из этих типов. В исходном коде содержимое символьных и строковых литералов выражается с помощью кодировки. Универсальные имена символов и escape-символы позволяют представить любую строку, используя только основную кодировку исходного кода. Необработанные строковые литералы позволяют не использовать escape-символы и могут применяться для выражения всех типов строковых литералов. Вы также можете создавать std::string литералы, не выполняя дополнительные действия по созданию или преобразованию.
#include using namespace std::string_literals; // enables s-suffix for std::string literals int main() < // Character literals auto c0 = 'A'; // char auto c1 = u8'A'; // char auto c2 = L'A'; // wchar_t auto c3 = u'A'; // char16_t auto c4 = U'A'; // char32_t // Multicharacter literals auto m0 = 'abcd'; // int, value 0x61626364 // String literals auto s0 = "hello"; // const char* auto s1 = u8"hello"; // const char* before C++20, encoded as UTF-8, // const char8_t* in C++20 auto s2 = L"hello"; // const wchar_t* auto s3 = u"hello"; // const char16_t*, encoded as UTF-16 auto s4 = U"hello"; // const char32_t*, encoded as UTF-32 // Raw string literals containing unescaped \ and " auto R0 = R"("Hello \ world")"; // const char* auto R1 = u8R"("Hello \ world")"; // const char* before C++20, encoded as UTF-8, // const char8_t* in C++20 auto R2 = LR"("Hello \ world")"; // const wchar_t* auto R3 = uR"("Hello \ world")"; // const char16_t*, encoded as UTF-16 auto R4 = UR"("Hello \ world")"; // const char32_t*, encoded as UTF-32 // Combining string literals with standard s-suffix auto S0 = "hello"s; // std::string auto S1 = u8"hello"s; // std::string before C++20, std::u8string in C++20 auto S2 = L"hello"s; // std::wstring auto S3 = u"hello"s; // std::u16string auto S4 = U"hello"s; // std::u32string // Combining raw string literals with standard s-suffix auto S5 = R"("Hello \ world")"s; // std::string from a raw const char* auto S6 = u8R"("Hello \ world")"s; // std::string from a raw const char* before C++20, encoded as UTF-8, // std::u8string in C++20 auto S7 = LR"("Hello \ world")"s; // std::wstring from a raw const wchar_t* auto S8 = uR"("Hello \ world")"s; // std::u16string from a raw const char16_t*, encoded as UTF-16 auto S9 = UR"("Hello \ world")"s; // std::u32string from a raw const char32_t*, encoded as UTF-32 >
Строковые литералы не могут иметь префикс или u8 L , u и U префиксы для обозначения узкого символа (однобайтового или многобайтового), UTF-8, широкий символ (UCS-2 или UTF-16), кодировки UTF-16 и UTF-32 соответственно. Необработанный строковый литерал может иметь R , u8R и LR uR UR префиксы для необработанных эквивалентов этих кодировок. Чтобы создать временные или статические std::string значения, можно использовать строковые литералы или необработанные строковые литералы с суффиксом s . Дополнительные сведения см. в разделе "Строковые литералы " ниже. Дополнительные сведения о базовом наборе исходных символов, универсальных именах символов и использовании символов из расширенных кодовых страниц в исходном коде см. в разделе "Наборы символов".
Символьные литералы
Символьный литерал состоит из символьной константы. Он представлен символом, окруженным одними кавычками. Существует пять типов символьных литерала:
- Обычные символьные литералы типа char , например 'a'
- Символьные литералы UTF-8 типа char ( char8_t в C++20), например u8'a'
- Расширенные символьные литералы типа wchar_t , например L'a' .
- Символьные литералы типа char16_t UTF-16, например u'a'
- Символьные литералы типа char32_t UTF-32, например U'a'
Символ, используемый для литерала символов, может быть любым символом, за исключением зарезервированных символов обратной косой черты ( \ ), одной кавычки ( ' ) или новой строки. Зарезервированные символы можно указывать с помощью escape-последовательности. Символы можно указывать с помощью универсальных имен символов, при условии что тип является достаточно крупным для размещения символа.
Кодировка
Литералы символов кодируются по-разному на основе префикса.
- Литерал символов без префикса — обычный символьный литерал. Значение обычного символьного литерала, содержащего один символ, escape-последовательность или универсальное имя символа, которое может быть представлено в наборе символов выполнения, имеет значение, равное числовому значению его кодировки в наборе символов выполнения. Обычный литерал символов, содержащий несколько символов, escape-последовательность или универсальное имя символов, является многофакторным литералом. Многофакторный литерал или обычный символьный литерал, который не может быть представлен в наборе символов выполнения, имеет тип int , и его значение определяется реализацией. Сведения о MSVC см. в следующем разделе майкрософт.
- Символьный литерал, начинающийся с L префикса, — это символьный литерал. Значение символьного литерала, содержащего один символ, escape-последовательность или универсальное имя символов, имеет значение, равное числовому значению его кодировки в наборе символов, если литерал символов не имеет представления в наборе расширенных символов выполнения, в этом случае значение определяется реализацией. Значение расширенных символьных литералов, содержащих несколько символов, escape-последовательностей или универсальных имен символов, определяется реализацией. Сведения о MSVC см. в следующем разделе майкрософт.
- Символьный литерал, начинающийся с u8 префикса, — это символьный литерал UTF-8. Значение символьного литерала UTF-8, содержащего один символ, escape-последовательность или универсальное имя символов, имеет значение, равное значению точки кода ISO 10646, если оно может быть представлено одним блоком кода UTF-8 (соответствующим блоку элементов управления C0 и Basic Latin Юникод). Если значение не может быть представлено одним блоком кода UTF-8, программа не сформирована. Символьный литерал UTF-8, содержащий несколько символов, escape-последовательность или универсальное имя символов, является неправильно сформированным.
- Символьный литерал, начинающийся с u префикса, является литералом символов UTF-16. Значение символьного литерала UTF-16, содержащего один символ, escape-последовательность или универсальное имя символов, имеет значение, равное значению точки кода ISO 10646, если оно может быть представлено одной единицей кода UTF-16 (соответствующей базовой многоязычной плоскости). Если значение не может быть представлено одним блоком кода UTF-16, программа не сформирована. Литерал символа UTF-16, содержащий несколько символов, escape-последовательность или универсальное имя символов, является неправильно сформированным.
- Символьный литерал, начинающийся с U префикса, — это символьный литерал UTF-32. Значение символьного литерала UTF-32, содержащего один символ, escape-последовательность или универсальное имя символов, имеет значение, равное значению точки кода ISO 10646. Символьный литерал UTF-32, содержащий несколько символов, escape-последовательность или универсальное имя символов, является неправильно сформированным.
Escape-последовательности
Существует три вида escape-последовательностей: простая, восьмеричная и шестнадцатеричная. Escape-последовательности могут быть любым из следующих значений:
Значение |
escape-последовательность |
новая строка |
\n |
обратная косая черта |
\\ |
горизонтальная табуляция |
\t |
вопросительный знак |
? Или\? |
вертикальная табуляция |
\v |
одинарная кавычка |
\' |
BACKSPACE |
\b |
двойная кавычка |
\" |
Возврат каретки |
\r |
нуль-символ |
\0 |
Смена страницы |
\f |
восьмеричный |
\ooo |
оповещение (колокольчик) |
\a |
шестнадцатеричный |
\xhhh |
Восьмеричная escape-последовательность — это обратная косая черта, за которой следует последовательность из одной до трех восьмеричных цифр. Восьмеричная escape-последовательность завершается на первом символе, который не является восьмеричной цифрой, если обнаружена раньше, чем третья цифра. Максимально возможное восьмеричное значение . \377
Шестнадцатеричная escape-последовательность — это обратная косая черта, за которой следует символ x , за которой следует последовательность одной или нескольких шестнадцатеричных цифр. Начальные нули пропускаются. В обычном или префиксном литерале символов u8 самое высокое шестнадцатеричное значение 0xFF. В расширенном символьном литерале с префиксом L или u максимальное шестнадцатеричное значение — 0xFFFF. В расширенном символьном литерале с префиксом U максимальное шестнадцатеричное значение — 0xFFFFFFFF.
В этом примере кода показаны некоторые примеры экранированных символов с помощью обычных литералов символов. Тот же синтаксис escape-последовательности действителен для других типов литеральных символов.
#include using namespace std; int main() < char newline = '\n'; char tab = '\t'; char backspace = '\b'; char backslash = '\\'; char nullChar = '\0'; cout /* Output: Newline character: ending Tab character: ending Backspace character:ending Backslash character: \ending Null character: ending */
Символ обратной косой черты ( \ ) — это символ продолжения строки, когда он помещается в конце строки. Если символ обратной косой черты требуется использовать как символьный литерал, необходимо ввести две косые черты подряд ( \\ ). Дополнительные сведения о символе продолжения строки см. в разделе Phases of Translation.
Только для систем Майкрософт
Чтобы создать значение из узкого многофакторного литерала, компилятор преобразует последовательность символов или символов между одними кавычками в 8-разрядные значения в 32-разрядное целое число. Несколько символов в литерале заполняют соответствующие байты по мере необходимости от высокого до низкого порядка. Затем компилятор преобразует целое число в тип назначения, следуя обычным правилам. Например, чтобы создать char значение, компилятор принимает байт низкого порядка. Для создания значения wchar_t или char16_t компилятор принимает младшее слово. Компилятор выдает предупреждение о том, что результат усекается, если какие-либо биты заданы выше назначенного байта или слова.
char c0 = 'abcd'; // C4305, C4309, truncates to 'd' wchar_t w0 = 'abcd'; // C4305, C4309, truncates to '\x6364' int i0 = 'abcd'; // 0x61626364
Восьмеричная escape-последовательность, которая, как представляется, содержит более трех цифр, рассматривается как 3-разрядная октальная последовательность, за которой следует последующие цифры в виде символов в многофакторном литерале, что может дать удивительные результаты. Например:
char c1 = '\100'; // '@' char c2 = '\1000'; // C4305, C4309, truncates to '0'
Escape-последовательности, которые, как представляется, содержат неосьмеривые символы, оцениваются как восьмеричное последовательность до последнего октационного символа, а затем остальные символы в виде последующих символов в многохарактерном литерале. Предупреждение C4125 создается, если первый не восьмеричный символ является десятичной цифрой. Например:
char c3 = '\009'; // '9' char c4 = '\089'; // C4305, C4309, truncates to '9' char c5 = '\qrs'; // C4129, C4305, C4309, truncates to 's'
Восьмеричная escape-последовательность, которая имеет более высокое значение, чем \377 вызывает ошибку C2022: value-in-decimal : слишком большой для символа.
Последовательность escape,которая, как представляется, имеет шестнадцатеричные и не шестнадцатеричные символы, оценивается как многофакторный литерал, содержащий шестнадцатеричную последовательность escape-последовательности до последнего шестнадцатеричного символа, за которым следует не шестнадцатеричные символы. Шестнадцатеричная escape-последовательность, содержащая шестнадцатеричные цифры, приводит к ошибке компилятора C2153: "шестнадцатеричные литералы должны иметь по крайней мере одну шестнадцатеричную цифру".
char c6 = '\x0050'; // 'P' char c7 = '\x0pqr'; // C4305, C4309, truncates to 'r'
Если расширенный символьный литерал, префиксированный с L несколькими диаграммами, то значение берется из первого символа, а компилятор вызывает предупреждение C4066. Последующие символы игнорируются, в отличие от поведения эквивалентного обычного многофакторного литерала.
wchar_t w1 = L'\100'; // L'@' wchar_t w2 = L'\1000'; // C4066 L'@', 0 ignored wchar_t w3 = L'\009'; // C4066 L'\0', 9 ignored wchar_t w4 = L'\089'; // C4066 L'\0', 89 ignored wchar_t w5 = L'\qrs'; // C4129, C4066 L'q' escape, rs ignored wchar_t w6 = L'\x0050'; // L'P' wchar_t w7 = L'\x0pqr'; // C4066 L'\0', pqr ignored
Раздел , посвященный майкрософт , заканчивается здесь.
универсальные имена символов
В символьных литералах и машинных (не являющихся необработанными) строковых литералах любой символ может быть представлен универсальным именем символа. Универсальные имена символов формируются префиксом \U , за которым следует восьмизначная кодовая точка Юникода или префикс \u , за которым следует четырехзначная точка кода Юникода. Все восемь или четыре знака, соответственно, должны присутствовать для создания корректного универсального имени символа.
char u1 = 'A'; // 'A' char u2 = '\101'; // octal, 'A' char u3 = '\x41'; // hexadecimal, 'A' char u4 = '\u0041'; // \u UCN 'A' char u5 = '\U00000041'; // \U UCN 'A'
Суррогатные пары
Универсальные имена символов не могут кодировать значения в диапазоне суррогатных точек кода D800-DFFF. Для суррогатных пар Юникода укажите универсальное имя символа, используя \UNNNNNNNN , где NNNNNNNN — восьмизначная кодовая точка для символа. При необходимости компилятор создает суррогатную пару.
В C++03 язык допускает только подмножество символов, представленных их универсальными именами символов, и допускает некоторые универсальные имена символов, которые фактически не представляют допустимые символы Юникода. Эта ошибка была исправлена в стандарте C++11. В C++11 в символьных и строковых литералах и идентификаторах можно использовать универсальные имена символов. Дополнительные сведения об универсальных именах символов см. в разделе Character Sets. Дополнительные сведения о Юникоде см. в статье Unicode. Дополнительные сведения о суррогатных парах см. в статье Surrogate Pairs and Supplementary Characters(Суррогатные пары и дополнительные символы).
Строковые литералы
Строковый литерал представляет последовательность символов, которые вместе образуют строку с завершающим нулем. Символы должны быть заключены в двойные кавычки. Существуют следующие типы строковых литералов.
Узкие строковые литералы
Узкий строковый литерал — это не префиксированный, разделенный двойными кавычками массив const char[n] типа, в котором n — длина массива в байтах. Обычный строковый литерал может содержать любые графические символы, за исключением двойных кавычек ( " ), обратной косой черты ( \ ) или символа новой строки. Обычный строковый литерал также может содержать перечисленные выше escape-последовательности и универсальные имена символов, которые помещаются в байте.
const char *narrow = "abcd"; // represents the string: yes\no const char *escaped = "yes\\no";
Строки в кодировке UTF-8
Строка в кодировке UTF-8 — это префиксированный, разделенный двойным кавычками массив типа, завершаемый значением NULL, где n — длина закодированного массива const char[n] в байтах. Строковый литерал с префиксом u8 может содержать любые графические символы, за исключением двойных кавычек ( " ), обратной косой черты ( \ ) или символа новой строки. Строковый литерал с префиксом u8 может также содержать перечисленные выше escape-последовательности и любые универсальные имена символов.
C++20 представляет переносимый char8_t (UTF-8 закодированный 8-разрядный тип символа Юникода). В C++20 u8 префиксы литералов указывают символы или строки char8_t вместо char .
// Before C++20 const char* str1 = u8"Hello World"; const char* str2 = u8"\U0001F607 is O:-)"; // C++20 and later const char8_t* u8str1 = u8"Hello World"; const char8_t* u8str2 = u8"\U0001F607 is O:-)";
Расширенные строковые литералы
Широкий строковый литерал — это массив констант wchar_t , префиксируемый символом null, который префиксируется " L " и содержит любой графический символ, кроме двойной кавычки ( " ), обратной косой черты ( \ ) или символа новой строки. Расширенный строковый литерал может содержать перечисленные выше escape-последовательности и любые универсальные имена символов.
const wchar_t* wide = L"zyxw"; const wchar_t* newline = L"hello\ngoodbye";
char16_t и char32_t (C++11)
В C++11 доступны символьные типы char16_t (портативный, 16-разрядный Юникод) и char32_t (32-разрядный Юникод):
auto s3 = u"hello"; // const char16_t* auto s4 = U"hello"; // const char32_t*
Необработанные строковые литералы (C++11)
Необработанный строковый литерал — это массив, завершающий значение NULL, любой тип символа, который содержит любой графический символ, включая двойную кавычку (), обратную косую черту ( " \ ) или новый символ. Необработанные строковые литералы часто применяются в регулярных выражениях, которые используют классы символов, а также в строках HTML и XML. Примеры см. в следующей статье: Bjarne Stroustrup's FAQ on C++11(Вопросы и ответы о C++11 от Бьерна Страуструпа).
// represents the string: An unescaped \ character const char* raw_narrow = R"(An unescaped \ character)"; const wchar_t* raw_wide = LR"(An unescaped \ character)"; const char* raw_utf8a = u8R"(An unescaped \ character)"; // Before C++20 const char8_t* raw_utf8b = u8R"(An unescaped \ character)"; // C++20 const char16_t* raw_utf16 = uR"(An unescaped \ character)"; const char32_t* raw_utf32 = UR"(An unescaped \ character)";
Разделитель — это определяемая пользователем последовательность до 16 символов, которая непосредственно предшествует открытию круглых скобок необработанного строкового литерала и сразу же следует за закрывающей скобкой. Например, в R"abc(Hello"\()abc" последовательность разделителей — abc , а содержимое строки — Hello"\( . Разделители можно использовать для различения необработанных строк, содержащих двойные кавычки и круглые скобки. Этот строковый литерал вызывает ошибку компилятора:
// meant to represent the string: )" const char* bad_parens = R"()")"; // error C2059
Однако ошибку можно устранить с помощью разделителя:
const char* good_parens = R"xyz()")xyz";
Вы можете создать необработанный строковый литерал, содержащий новую строку (а не экранированный символ) в источнике:
// represents the string: hello //goodbye const wchar_t* newline = LR"(hello goodbye)";
std::string литералы (C++14)
std::string литералы — это стандартные реализации определяемых пользователем литералы (см. ниже), представленные как "xyz"s (суффиксом s ). Такой строковый литерал создает временный объект типа std::string , std::wstring std::u32string или std::u16string в зависимости от указанного префикса. Если префикс не используется, как описано выше, создается. std::string L"xyz"s std::wstring создает объект . u"xyz"s создает std::u16string и U"xyz"s создает std::u32string.
//#include //using namespace std::string_literals; string str< "hello"s >; string str2< u8"Hello World" >; // Before C++20 u8string u8str2< u8"Hello World" >; // C++20 wstring str3< L"hello"s >; u16string str4< u"hello"s >; u32string str5< U"hello"s >;
Суффикс s можно также использовать в необработанных строковых литералах:
u32string str6< UR"(She said "hello.")"s >;
std::string литералы определяются в пространстве std::literals::string_literals имен в файле заголовка . Поскольку std::literals::string_literals и std::literals объявляются как встроенные пространства имен, std::literals::string_literals автоматически считается напрямую принадлежащим пространству имен std .
Размер строковых литерала
Для строк ANSI char* и других однобайтовых кодировок (но не UTF-8), размер (в байтах) строкового литерала — это число символов плюс 1 для завершающего символа NULL. Для всех других типов строк размер не связан строго с количеством символов. UTF-8 использует до четырех char элементов для кодирования некоторых единиц кода и char16_t wchar_t в кодировке UTF-16 может использовать два элемента (в общей сложности четыре байта) для кодирования одной единицы кода. В примере ниже показан размер расширенного строкового литерала в байтах.
const wchar_t* str = L"Hello!"; const size_t byteSize = (wcslen(str) + 1) * sizeof(wchar_t);
Обратите внимание, что strlen() и wcslen() не включайте размер завершающего символа NULL, размер которого равен размеру элемента типа строки: один байт в char* строке или char8_t* строке, два байта wchar_t* или char16_t* строки и четыре байта в char32_t* строках.
В версиях Visual Studio до Visual Studio 2022 версии 17.0 максимальная длина строкового литерала составляет 65 535 байт. Это ограничение применимо как к узким, так и к расширенным строковым литералам. В Visual Studio 2022 версии 17.0 и более поздних версиях это ограничение будет отменено, а длина строки ограничена доступными ресурсами.
Изменение строковых литерала
Так как строковые литералы (не включая std::string литералы) являются константами, пытаясь изменить их( например, str[2] = 'A' вызывает ошибку компилятора.
Только для систем Майкрософт
В Microsoft C++можно использовать строковый литерал для инициализации указателя на неконст char или wchar_t . Эта неконстантная инициализация разрешена в коде C99, но устарела в C++98 и удалена в C++11. Попытка изменить строку вызовет нарушение прав доступа, как показано в следующем примере:
wchar_t* str = L"hello"; str[2] = L'a'; // run-time error: access violation
Компилятор может вызвать ошибку при преобразовании строкового литерала в указатель неконстного символа при настройке /Zc:strictStrings параметра компилятора (отключить преобразование строковых литеральных типов). Мы рекомендуем использовать его для переносимого кода, соответствующего стандартам. Кроме того, рекомендуется использовать auto ключевое слово для объявления строковых инициализированных указателей, так как он разрешает правильный (const) тип. В следующем примере кода перехватывается во время компиляции попытка записать в строковый литерал:
auto str = L"hello"; str[2] = L'a'; // C3892: you cannot assign to a variable that is const.
В некоторых случаях идентичные строковые литералы могут быть объединены в пул для экономии места в исполняемом файле. При объединении строковых литералов в пулы компилятор делает так, что все ссылки на определенный строковый литерал указывают на одну и ту же область в памяти, вместо того чтобы каждая ссылка указывала на отдельный экземпляр строкового литерала. Чтобы включить пул строк, используйте параметр компилятора /GF .
Раздел , посвященный майкрософт , заканчивается здесь.
Сцепление смежных строковых литералов
Все смежные расширенные и узкие строковые литералы соединяются. Данное объявление:
char str[] = "12" "34";
идентично следующему объявлению:
char atr[] = "1234";
и следующему объявлению:
char atr[] = "12\ 34";
Использование внедренных шестнадцатеричных escape-кодов для задания строковых литералов может привести к непредвиденным результатам. В следующем примере выполняется попытка создать строковый литерал, содержащий символ ASCII 5, за которым следуют символы f, i, v и e:
"\x05five"
Фактический результат (шестнадцатеричное значение 5F) является кодом ASCII для символа подчеркивания, за которым следуют символы i, v и e. Чтобы получить правильный результат, можно использовать одну из следующих escape-последовательностей:
"\005five" // Use octal literal. "\x05" "five" // Use string splicing.
std::string литералы (и связанные std::u8string std::u16string , и std::u32string ) можно объединить с оператором + , определенным для basic_string типов. Эти литералы также можно соединить аналогично смежным строковым литералам. В обоих случаях кодировка строки и суффикс должны совпадать:
auto x1 = "hello" " " " world"; // OK auto x2 = U"hello" " " L"world"; // C2308: disagree on prefix auto x3 = u8"hello" " "s u8"world"z; // C3688, disagree on suffixes
Строковые литералы с универсальными именами символов
Машинные (не являющиеся необработанными) строковые литералы могут использовать универсальные имена символов для представления любого символа, при условии что универсальные имена можно кодировать как один или несколько символов в строковом типе. Например, универсальное имя символа, представляющее расширенный символ, не может быть закодировано в узкой строке с помощью кодовой страницы ANSI, но его можно закодировать в узких строках в некоторых многобайтовых кодовых страницах или в строках UTF-8 или в широкой строке. В C++11 поддержка Юникода расширяется типами char16_t* строк, char32_t* а C++20 расширяет его до char8_t типа:
// ASCII smiling face const char* s1 = ":-)"; // UTF-16 (on Windows) encoded WINKING FACE (U+1F609) const wchar_t* s2 = L" = \U0001F609 is ;-)"; // UTF-8 encoded SMILING FACE WITH HALO (U+1F607) const char* s3a = u8" = \U0001F607 is O:-)"; // Before C++20 const char8_t* s3b = u8" = \U0001F607 is O:-)"; // C++20 // UTF-16 encoded SMILING FACE WITH OPEN MOUTH (U+1F603) const char16_t* s4 = u" = \U0001F603 is :-D"; // UTF-32 encoded SMILING FACE WITH SUNGLASSES (U+1F60E) const char32_t* s5 = U" = \U0001F60E is B-)";
String в языке С: определение, типы, методы и использование

String в С — это определенный тип данных, который , по сути , является последовательностью различных символов, заключенных в «кавычки». Такой тип данных используется для написания каких-либо текстовых сообщений: имя, адрес, слова, предложения и др.
После подключения заголовочного файл а с о «строками» в С можно работать как с обычными переменными. Например, их можно объявлять и присваивать им значения:
std:: string auto(“AUDI“); //создаем переменную «auto» и присваиваем ей строковое значение «AUDI»
name = “VAZ“; //присваиваем переменной «auto» строковое значение «VAZ»
String в С может принимать любые символы, даже числа. Но если вписать в «строку» число, то оно оста н ется строкой и выполнять с ним арифметические действия не получится. С не преобразует число , записанное в «string» , в целочисленный тип данных, чтобы с ним можно было взаимодействовать как с числом.
Работа со string в Си
Строки можно выводить при помощи «cout» или «cin». Например, как работает «cout»:
int main()
std::string name(“Владимир“);
std::count < < “Меня зовут“ < < name;
return 0;
>
В результате выполнения программы мы получим: «Меня зовут Владимир».
Как работает «cin»:
int main()
std::cout < < “Введите ваше полное имя: “;
std::string myName;
std::cin > > myName
std::cout < < “Введите ваш возраст: “;
std::string myAge;
std::cin > > myAge;
std::cout « “ Ваше имя “ < < myName < < “ и ваш возраст “ < < myAge;
>
Результатом работы такой программы будет:
Введите ваше полное имя: «Владимир Мономах»
Введите ваш возраст: Ваше имя Владимир и ваш возраст Мономах
Вышло как-то не очень. Почему так? Оператор «>>» и «сin» работают немного по-другому. Оператор «>>» извлекает символы из входного потока, только до первого пробела, а остальные данные хранятся в «cin», пока не будут еще раз извлечены. Мы хотели извлечь полное имя в переменную «myName» при помощи оператора «>>», однако вместо всего имени «Владимир Мономах» мы получили только «Владимир», а вторым извлечением получили «Мономах». Если бы у нас было третье извлечение, тогда у нас был бы извлечен возраст, допустим , «30». Из этой ситуации есть выход.
Если необходимо извлекать все данные из входного потока, включая пробелы, тогда необходимо использовать функцию «std::getline()», которая несет в себе 2 аргумента: «std::cin» и «string». Вот как это выглядит:
int main()
std::cout < < “Введите ваше полное имя: “;
std::string myName;
std::getline(std::cin, myName);
std::cout < < “Введите ваш возраст: “;
std::string myAge;
std::getline(std::cin, myAge);
std::cout « “ Ваше имя “ < < myName < < “ и ваш возраст “ < < myAge;
>
Результатом такой программы будет:
Введите ваше имя: Владимир Мономах
Введите ваш возраст: 30
Ваше имя Владимир Мономах и ваш возраст 30
При такой реализации все будет работать как надо.
С вводом и выводом string в Си мы разобрались, но с о строками можно выполнять и другие манипуляции.
String в Си — это не только текст
- посимвольное сравнение при помощи операторов «==» или «!=»;
- лексикографическое сравнение при помощи операторов «», «=».
String в Си: методы
- Функция «size()». При помощи этой функции можно узнать длину строки.
- Функция «resize(n)». При помощи этой функции можно изменить длину строки, которая станет р а вняться «n».
- Функция «clear()». Данная функция полностью очищает строку и делает ее пустой.
- Функция «emp t y()». При помощи этой функции можно проверить string — является она пустой или нет.
- Функция «push_back(c)». При помощи этой функции в конец строки добавляется символ «с».
- Функция «append()». Эта функция способна добавить в конец строки не просто символ, а другую строку или фрагмент строки.
- Функция «erase(pos, cont)». При помощи этой функции можно удалить символы, начиная с индекса, указанного в «pos». «Cont» используется, чтобы обозначить количество символов, которые нужно удалить ; если не указать этот аргумент, тогда удалятся все символы до конца строки.
- Функция «substr(pos, cont)». При помощи этой функции можно извлечь подстроку из строки, начиная с индекса , указанного в «pos». «Сont» необходимо указать, если нужно извлечь определенное количество символов.
- Функция «replace(pos, cont)». Эта функция заменяет строку, кусочек строки или отдельный символ в строке на необходимое значение.
- Функция «find(str, pos)». При помощи этой функции можно искать вхождение одной строки в друг ую . Функция возвращает индекс первого символа в строке, где найдено вхождение.
Заключение
String в Си хоть и не являются встроенным типом данных, но очень многофункциональны и часто применяются в программировании. Поэтому при изучении Си или С++ обязательно нужно понимать , как можно взаимодействовать со строками или другими типами данных , — это является основой программирования на любом языке.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.