Тип string visual studio
В языке C++ для удобной работы со строками есть класс string, для использования которого необходимо подключить заголовочный файл string.
Строки можно объявлять и одновременно присваивать им значения:
string S1, S2 = "Hello";
Строка S1 будет пустой, строка S2 будет состоять из 5 символов.
К отдельным символам строки можно обращаться по индексу, как к элементам массива или C-строк. Например S[0] - это первый символ строки.
Для того, чтобы узнать длину строки можно использовать метод size() строки. Например, последний символ строки S это S[S.size() - 1 ].
Строки в языке C++ могут
Конструкторы строк
Строки можно создавать с использованием следующих конструкторов:
string() - конструктор по умолчанию (без параметров) создает пустую строку.
string(string & S) - копия строки S
string( size_t n, char c) - повторение символа c заданное число n раз.
string(size_t c) - строка из одного символа c .
string(string & S, size_t start, size_t len) - строка, содержащая не более, чем len символов данной строки S , начиная с символа номер start .
Конструкторы можно вызывать явно, например, так:
В этом примере явно вызывается конструктор string для создания строки, состоящей из 10 символов 'z' .
Неявно конструктор вызывается при объявлении строки с указанием дополнительных параметров. Например, так:
Подробней о конструкторах для строк читайте здесь.
Ввод-вывод строк
Строка выводится точно так же, как и числовые значения:
Для считывания строки можно использовать операцию ">>" для объекта cin:
В этом случае считывается строка из непробельных символов, пропуская пробелы и концы строк. Это удобно для того, чтобы разбивать текст на слова, или чтобы читать данные до конца файла при помощи while (cin >> S) .
Можно считывать строки до появления символа конца строки при помощи функции getline. Сам символ конца строки считывается из входного потока, но к строке не добавляется:
Арифметические операторы
Со строками можно выполнять следующие арифметические операции:
= - присваивание значения.
+= - добавление в конец строки другой строки или символа.
+ - конкатенация двух строк, конкатенация строки и символа.
== , != - посимвольное сравнение.
< , > , <= , >= - лексикографическое сравнение.
То есть можно скопировать содержимое одной строки в другую при помощи операции S1 = S2, сравнить две строки на равенство при помощи S1 == S2, сравнить строки в лексикографическом порядке при помощи S1 < S2, или сделать сложение (конкатенацию) двух строк в виде S = S1 + S2.
Подробней об операторах для строк читайте здесь.
Методы строк
У строк есть разные методы, многие из них можно использовать несколькими разными способами (с разным набором параметров).
Рассмотрим эти методы подробней.
Метод size() возращает длину длину строки. Возвращаемое значение является беззнаковым типом (как и во всех случаях, когда функция возращает значение, равное длине строке или индексу элемента - эти значения беззнаковые). Поэтому нужно аккуратно выполнять операцию вычитания из значения, которое возвращает size(). Например, ошибочным будет запись цикла, перебирающего все символы строки, кроме последнего, в виде for (int i = 0; i < S.size() - 1; ++i).
Кроме того, у строк есть метод length(), который также возвращает длину строки.
Подробней о методе size.
resize
S.resize(n) - Изменяет длину строки, новая длина строки становится равна n. При этом строка может как уменьшится, так и увеличиться. Если вызвать в виде S.resize(n, c) , где c - символ, то при увеличении длины строки добавляемые символы будут равны c.
Подробней о методе resize.
clear
S.clear() - очищает строчку, строка становится пустой.
Подробней о методе clear.
empty
S.empty() - возвращает true, если строка пуста, false - если непуста.
Подробней о методе empty.
push_back
S.push_back(c) - добавляет в конец строки символ c, вызывается с одним параметром типа char.
Подробней о методе push_back.
append
Добавляет в конец строки несколько символов, другую строку или фрагмент другой строки. Имеет много способов вызова.
S.append(n, c) - добавляет в конец строки n одинаковых символов, равных с. n имеет целочисленный тип, c - char.
S.append(T) - добавляет в конец строки S содержимое строки T. T может быть объектом класса string или C-строкой.
S.append(T, pos, count) - добавляет в конец строки S символы строки T начиная с символа с индексом pos количеством count.
Подробней о методе append.
erase
S.erase(pos) - удаляет из строки S с символа с индексом pos и до конца строки.
S.erase(pos, count) - удаляет из строки S с символа с индексом pos количеством count или до конца строки, если pos + count > S.size().
Подробней о методе erase.
insert
Вставляет в середину строки несколько символов, другую строку или фрагмент другой строки. Способы вызова аналогичны способам вызова метода append, только первым параметром является значение i - позиция, в которую вставляются символы. Первый вставленный символ будет иметь индекс i, а все символы, которые ранее имели индекс i и более сдвигаются вправо.
S.insert(i, n, c) - вставить n одинаковых символов, равных с. n имеет целочисленный тип, c - char.
S.insert(i, T) - вставить содержимое строки T. T может быть объектом класса string или C-строкой.
S.insert(i, T, pos, count) - вставить символы строки T начиная с символа с индексом pos количеством count.
Подробней о методе insert.
substr
S.substr(pos) - возвращает подстроку данной строки начиная с символа с индексом pos и до конца строки.
S.substr(pos, count) - возвращает подстроку данной строки начиная с символа с индексом pos количеством count или до конца строки, если pos + count > S.size().
Подробней о методе substr.
replace
Заменяет фрагмент строки на несколько равных символов, другую строку или фрагмент другой строки. Способы вызова аналогичны способам вызова метода append, только первыми двумя параметрами являются два числа: pos и count. Из данной строки удаляется count символов, начиная с символа pos, и на их место вставляются новые символы.
S.replace(pos, count, n, c) - вставить n одинаковых символов, равных с. n имеет целочисленный тип, c - char.
S.replace(pos, count, T) - вставить содержимое строки T. T может быть объектом класса string или C-строкой.
S.replace(pos, count, T, pos2, count2) - вставить символы строки T начиная с символа с индексом pos количеством count.
Подробней о методе replace.
Ищет в данной строке первое вхождение другой строки str. Возвращается номер первого символа, начиная с которого далее идет подстрока, равная строке str. Если эта строка не найдена, то возвращается константа string::npos (которая равна -1, но при этом является беззнаковой, то есть на самом деле является большим безннаковым положительным числом).
Если задано значение pos, то поиск начинается с позиции pos, то есть возращаемое значение будет не меньше, чем pos. Если значение pos не указано, то считается, что оно равно 0 - поиск осуществляется с начала строки.
S.find(str, pos = 0) - искать первое входение строки str начиная с позиции pos. Если pos не задано - то начиная с начала строки S.
S.find(str, pos, n) - искать в данной строке подстроку, равную первым n символам строки str. Значение pos должно быть задано.
Подробней о методе find.
rfind
Ищет последнее вхождение подстроки ("правый" поиск). Способы вызова аналогичны способам вызова метода find.
Подробней о методе rfind.
find_first_of
Ищет в данной строке первое появление любого из символов данной строки str. Возвращается номер этого символа или значение string::npos.
Если задано значение pos, то поиск начинается с позиции pos, то есть возращаемое значение будет не меньше, чем pos. Если значение pos не указано, то считается, что оно равно 0 - поиск осуществляется с начала строки.
S.find_first_of(str, pos = 0) - искать первое входение любого символа строки str начиная с позиции pos. Если pos не задано - то начиная с начала строки S.
find_last_of
Ищет в данной строке последнее появление любого из символов данной строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
Подробней о методе find_last_of.
find_first_not_of
Ищет в данной строке первое появление символа, отличного от символов строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
find_last_not_of
Ищет в данной строке последнее появление символа, отличного от символов строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
c_str
Возвращает указать на область памяти, в которой хранятся символы строки, возвращает значение типа char*. Возвращаемое значение можно рассматривать как C-строку и использовать в функциях, которые должны получать на вход C-строку.
2. Какие модули (библиотеки) нужно подключить, чтобы использовать возможности класса string в MS Visual Studio C++?
Чтобы использовать возможности класса string в MS Visual Studio (C++), нужно подключить библиотеку <string> и пространство имен std .
3. Каким образом осуществляется объявление переменной типа string ? Примеры
Объявление переменной типа string осуществляется точно так же как и обычной переменной. Возможный вариант объявления с одновременной инициализацией.
4. Какие преимущества и недостатки дает использование класса string в сравнении с типом char* ?
Создание нового типа string было обусловлено недостатками работы с строками символов, который демонстрировал тип char* . В сравнении с типом char* тип string имеет следующие основные преимущества:
- возможность обработки строк стандартными операторами C++ ( = , + , = = , <> и т.п.). Как известно, при использовании типа char* даже наиболее простые операции со строками выглядели сложно и требовали написания чрезмерного программного кода;
- обеспечение лучшей надежности (безопасности) программного кода. Например, при копировании строк, тип string обеспечивает соответствующие действия, которые могут возникнуть в случае, если строка-источник имеет больший размер чем строка-приемник;
- обеспечение строки, как самостоятельного типа данных. Объявление типа string как строки есть единым для всех переменных в программе, которая обеспечивает непротиворечивость данных.
Основным недостатком типа string в сравнении с типом char* , есть замедленная скорость обработки данных. Это связано с тем, что тип string – это, фактически, контейнерный класс. А работа с классом требует дополнительной реализации программного кода, который, в свою очередь занимает лишнее время.
5. Какие операторы можно использовать с объектами класса string ?
Класс string есть удобен тем, что позволяет удобно манипулировать строками, используя стандартные (перегруженные) операторы.
С объектами класса string можно использовать нижеследующие операторы
Пример, который демонстрирует использование вышеприведенных операторов
6. Содержит ли класс string конструкторы?
Как и любой класс, класс string имеет ряд конструкторов. Основные из них следующие:
7. Примеры инициализации с помощью конструкторов
Ниже приведены примеры инициализации переменных типа string
8. Присваивание строк. Функция assign() . Примеры
Чтобы присвоить одну строку другой, можно применить один из двух методов:
Функция assign() имеет несколько перегруженных реализаций.
Первый вариант – это вызов функции без параметров
В этом случае происходит простое присваивание одной строки другой.
Второй вариант позволяет копировать заданное количество символов из строки:
- s – объект, из которого берется исходная строка;
- st – индекс (позиция) в строке, из которой начинается копирование num символов;
- num – количество символов, которые нужно скопировать из позиции st ;
- size_type – порядковый тип данных.
Третий вариант функции assign() копирует в вызывающий объект первые num символов строки s :
Ниже приведен пример с разными реализациями функции assign() .
Пример.
9. Объединение строк. Функция append() . Пример
Однако, функция append() хорошо подходит, если нужно добавлять часть строки.
Функция имеет следующие варианты реализации:
Пример. Демонстрация работы функции append() .
10. Вставка символов в строке. Функция insert() . Пример
Чтобы вставить одну строку в заданную позицию другой строки нужно использовать функцию insert() , которая имеет несколько вариантов реализации.
Первый вариант функции позволяет вставить полностью всю строку s в заданную позицию start вызывающей строки (вызывающего объекта):
Второй вариант функции позволяет вставить часть (параметры insStart , num ) строки s в заданную позицию start вызывающей строки:
В вышеприведенных функциях:
- s – строка, которая вставляется в вызывающую строку;
- start – позиция в вызывающей строке, из которой осуществляется вставка строки s ;
- insStart – позиция в строке s , из которой происходит вставка;
- num – количество символов в строке s , которые вставляются с позиции insStart .
11. Замена символов в строке. Функция replace() . Пример
Функция replace() выполняет замену символов в вызывающей строке. Функция имеет следующие варианты реализации:
В первом варианте реализации вызывающая строка заменяется строкой s . Есть возможность задать позицию ( start ) и количество символов ( num ) в вызывающей строке, которые нужно заменить строкой s .
Второй вариант функции replace() отличается от первого тем, что позволяет заменять вызывающую строку только частью строки s . В этом случае задаются два дополнительных параметра: позиция replStart и количество символов в строке s , которые образуют подстроку, которая заменяет вызывающую строку.
Пример. Демонстрация работы функции replace() .
12. Удаление заданного количества символов из строки. Функция erase() . Пример
Для удаления символов из вызывающей строки используется функция erase() :
- index – индекс (позиция), начиная из которой нужно удалить символы в вызывающей строке;
- num – количество символов, которые удаляются.
Пример.
13. Поиск символа в строке. Функции find() и rfind() . Примеры
В классе string поиск строки в подстроке можно делать двумя способами, которые отличаются направлением поиска:
- путем просмотра строки от начала до конца с помощью функции find() ;
- путем просмотра строки от конца к началу функцией rfind() .
Прототип функции find() имеет вид:
- s – подстрока, которая ищется в строке, что вызывает данную функцию. Функция осуществляет поиск первого вхождения строки s . Если подстрока s найдена в строке, что вызвала данную функцию, тогда возвращается позиция первого вхождения. В противном случае возвращается -1;
- start – позиция, из которой осуществляется поиск.
Прототип функции rfind() имеет вид:
- s – подстрока, которая ищется в вызывающей строке. Поиск подстроки в строке осуществляется от конца к началу. Если подстрока s найдена в вызывающей строке, то функция возвращает позицию первого вхождения. В противном случае функция возвращает -1;
- npos – позиция последнего символа вызывающей строки;
- start – позиция, из которой осуществляется поиск.
Пример 1. Фрагмент кода, который демонстрирует результат работы функции find()
Пример 2. Демонстрация работы функции rfind() .
14. Сравнение частей строк. Функция compare() . Пример
Но если нужно сравнить часть одной строки с другой, то для этого предусмотрена функция compare() .
Прототип функции compare() :
- s – строка, которая сравнивается с вызывающей строкой;
- start – позиция (индекс) в строке s , из которой начинается просмотр символов строки для сравнения;
- num – количество символов в строке s , которые сравниваются с вызывающей строкой.
Функция работает следующим образом. Если вызывающая строка меньше строки s , то функция возвращает -1 (отрицательное значение). Если вызывающая строка больше строки s , функция возвращает 1 (положительное значение). Если две строки равны, функция возвращает 0.
Пример. Демонстрация работы функции compare() :
Функция объявлена с модификатором const . Это означает, что функция не может изменять вызывающий объект (строку).
Пример 1. Преобразование типа string в const char * .
Пример 2.
Ниже продемонстрирован перевод строки из string в тип System::String для отображения его в элементе управления типа Label для приложений типа Windows Forms Application .
16. Как определить длину строки типа string ? Функция length()
Для определения количества символов в строке используется функция length() без параметров.
Так что же такое string
Строка является ссылочным типом
Строка является неизменяемой
Никак невозможно изменить содержимое созданной строки, по крайней мере в безопасном (safe) коде и без рефлексии. Поэтому вы при изменении строк изменяете не сами строки, а значения переменных, указывающих на строки. Например, код s = s.Replace ("foo", "bar"); не изменяет содержимое строки s, которое было до вызова метода Replace — он просто переназначает переменную s на новообразованную строку, которая является копией старой за исключением всех подстрок «foo», заменённых на «bar».
Строка может содержать значение null
Строка переопределяет оператор равенства ==
При вызове оператора == для определения равенства двух строк происходит вызов метода Equals , который сравнивает именно содержимое строк, а не равенство ссылок. К примеру, выражение "hello".Substring(0, 4)=="hell" возвратит true , хотя ссылки на строки по обеих сторонах оператора равенства разные (две ссылки ссылаются на два разных строковых экземпляра, которые, при этом, содержат одинаковые значения). Вместе с тем необходимо помнить, что равенство значений, а не ссылок происходит только тогда, когда оба операнда на момент компиляции являются строго строковым типом — оператор равенства не поддерживает полиморфизм. Поэтому если хотя бы один из сравниваемых операндов будет иметь тип object , к примеру (хотя внутренне и будет оставаться строкой), то будет выполнено сравнение ссылок, а не содержимого строк.
Интернирование
Литералы
- \' — одинарная кавычка, используется для объявления литералов типа System.Char
- \" — двойная кавычка, используется для объявления строковых литералов
- \\ — обратный слеш
- \0 — null-символ в Юникоде
- \a — символ Alert (№7)
- \b — символ Backspace (№8)
- \f —смена страницы FORM FEED (№12)
- \n — перевод строки (№10)
- \r — возврат каретки (№13)
- \t — горизонтальная табуляция (№9)
- \v — вертикальная табуляция (№11)
- Uxxxx — символ Юникода с шестнадцатеричным кодом xxxx
- \xn[n][n][n] — символ Юникода с шестнадцатеричным кодом nnnn, версия предыдущего пункта с переменной длиной цифр кода
- \Uxxxxxxxx — символ Юникода с шестнадцатеричным кодом xxxxxxxx, используется для вызова суррогатных пар.
Строки и отладчик
Учитывая такую путаницу, я пришел к выводу, что при отладке подозрительных строк их следует рассматривать множеством способов, дабы исключить все недоразумения. Я предлагаю использовать приведённый ниже метод, который будет печатать содержимое строки в консоль «правильным» способом. В зависимости от того, какое приложение вы разрабатываете, вы можете вместо вывода в консоль записывать строки в лог-файл, отправлять в трассировщики, выводит в модальном Windows-окне и т.д.
Использование памяти и внутренняя структура
Кодировки строк
Если вы не знакомы с кодировками символов и Юникодом, пожалуйста, прочтите сначала мою статью о Юникоде (или её перевод на Хабре).
Региональные и интернациональные странности
Некоторые странности в Юникоде ведут к странностям при работе со строками и символами. Большинство строковых методов зависимы от региональных настроек (являются culture-sensitive — регионально-чувствительными), — другими словами, работа методов зависит от региональных настроек потока, в котором эти методы выполняются. Например, как вы думаете, что возвратит этот метод "i".toUpper() ? Большинство скажут: «I», а вот и нет! Для турецких региональных настроек метод вернёт "İ" (код U+0130, описание символа: «Latin capital I with dot above»). Для выполнения регионально-независимой смены регистра вы можете использовать свойство CultureInfo.InvariantCulture и передать его как параметр в перегруженную версию метода String.ToUpper , которая принимает CultureInfo .
Есть и другие странности, связанные со сравнением и сортировкой строк, а также с нахождением индекса подстроки в строке. Некоторые из этих операций регионально-зависимы, а некоторые — нет. Например, для всех регионов (насколько я могу видеть) литералы «lassen» и «la\u00dfen» (во втором литерале шестнадцатеричным кодом указан символ «S острое» или «эсце́т») определяются как равные при передачи их в методы CompareTo или Compare , но вот если передать их в Equals , то будет определено неравенство. Метод IndexOf будет учитывать эсцет как «ss» (двойное «s»), но вот если вы используете одну из перегрузок CompareInfo.IndexOf , где укажете CompareOptions.Ordinal , то эсцет будет обработан правильно.
Microsoft опубликовала некоторые рекомендации касательно обработки строк, и хотя они датируются 2005-м годом, их всё ещё сто́ит прочесть.
Довольно большое количество задач, которые могут встретиться при разработке приложений, так или иначе связано с обработкой строк - парсинг веб-страниц, поиск в тексте, какие-то аналитические задачи, связанные с извлечением нужной информации из текста и т.д. Поэтому в этом плане работе со строками уделяется особое внимание.
Создание строк
Создавать строки можно, как используя переменную типа string и присваивая ей значение, так и применяя один из конструкторов класса String:
Конструктор String имеет различное число версий. Так, вызов конструктора new String('a', 6) создаст строку "aaaaaa". И так как строка представляет ссылочный тип, то может хранить значение null.
Строка как набор символов
Так как строка хранит коллекцию символов, в ней определен индексатор для доступа к этим символам:
Применяя индексатор, мы можем обратиться к строке как к массиву символов и получить по индексу любой из ее символов:
Используя свойство Length , как и в обычном массиве, можно получить длину строки.
Основные методы строк
Основная функциональность класса String раскрывается через его методы, среди которых можно выделить следующие:
Compare : сравнивает две строки с учетом текущей культуры (локали) пользователя
CompareOrdinal : сравнивает две строки без учета локали
Contains : определяет, содержится ли подстрока в строке
Concat : соединяет строки
CopyTo : копирует часть строки, начиная с определенного индекса в массив
EndsWith : определяет, совпадает ли конец строки с подстрокой
Format : форматирует строку
IndexOf : находит индекс первого вхождения символа или подстроки в строке
Insert : вставляет в строку подстроку
Join : соединяет элементы массива строк
LastIndexOf : находит индекс последнего вхождения символа или подстроки в строке
Replace : замещает в строке символ или подстроку другим символом или подстрокой
Важными словами в этих описаниях являются идентификатор и дескриптор. Идентификатор — это понятное имя, присвоенное типу, который можно переопределить. Дескриптор — это предопределенный фиксированный идентификатор, который имеет особое значение для компилятора.
Поэтому в большинстве случаев разумно ожидать, что обе версии будут ссылаться на global: System.String, и их можно будет использовать взаимозаменяемо. Доказательство этому можно увидеть в примере фрагмента кода:
public static string string1 = "Created using string";
public static String string2 = "Created using String";
При компиляции на языке-посреднике обе переменные описываются одинаковым способом.
IL_0000: ldstr "Created using string" IL_0005: stsfld string WorkerSDKOnConsole.Program::string1
IL_000a: ldstr "Created using String" IL_000f: stsfld string WorkerSDKOnConsole.Program::string2
Рекомендации
string cheese = “cheddar”;
string petrol = string.Format(“Type: !”, unleaded);
Visual Studio также рекомендует такой вариант как часть правила IDE0049: «Используйте дескрипторы языка вместо дескрипторов среды для ссылки на типы»:
Проблема со String
// String - целое int String = 5;
int output = String + 10; // Valid code >
// String - объект StringBuilder: var String = new System.Text.StringBuilder();`
>
Поэтому невозможно предположить значение идентификатора String без полного понимания контекста кодовой базы. У дескриптора string этой проблемы нет. Попытка переопределить String таким же образом, как указано выше, попросту не будет компилироваться.
Контраргументы
Конечно, имеется ряд контраргументов, о которых также стоит упомянуть:
Выводы
Таким образом, и string, и String совершенно допустимы, и в большинстве случаев будут работать одинаково. Решение по использованию также может зависеть от существующих рекомендаций по написанию кода от проекта или команды. Однако в целом рекомендуется по возможности использовать дескриптор string.
Приложение: типы
Как упоминалось в начале этой статьи, существует множество других типов данных с дополнительными именами, которые можно найти в таблицах ниже.
Читайте также: