Jump to content

Обработка строк в C++

(Перенаправлено из String (C++) )

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

Поскольку первоначальные версии C++ имели только «низкоуровневые» функции и соглашения по обработке строк C , за прошедшие годы было разработано множество несовместимых проектов для классов обработки строк, которые до сих пор используются вместо std::string, и программистам C++ может потребоваться обработка нескольких соглашений в одном приложении.

The Тип std::string является основным строковым типом данных в стандарте C++ с 1998 года, но он не всегда был частью C++. От C C++ унаследовал соглашение об использовании строк с нулевым завершением , которые обрабатываются указателем на их первый элемент, а также библиотеку функций, которые манипулируют такими строками. В современном стандарте C++ строковый литерал, такой как «Привет» по-прежнему обозначает массив символов, завершающийся NUL. [ 1 ]

Использование классов C++ для реализации строкового типа дает несколько преимуществ автоматического управления памятью и снижает риск доступа за пределами границ. [ 2 ] и более интуитивный синтаксис для сравнения и конкатенации строк. Поэтому был большой соблазн создать такой класс. На протяжении многих лет разработчики приложений, библиотек и платформ C++ создавали свои собственные несовместимые представления строк, например, в библиотеке стандартных компонентов AT&T (первая такая реализация, 1983 г.). [ 3 ] или Тип CString в Microsoft MFC . [ 4 ] Пока std::string стандартизированные строки, устаревшие приложения по-прежнему часто содержат такие пользовательские типы строк, а библиотеки могут ожидать строки в стиле C, что делает «практически невозможным» избежать использования нескольких типов строк в программах на C++. [ 1 ] и требовать от программистов выбора желаемого строкового представления перед началом проекта. [ 4 ]

В ретроспективе истории C++ 1991 года его изобретатель Бьярн Страуструп назвал отсутствие стандартного строкового типа (и некоторых других стандартных типов) в C++ 1.0 худшей ошибкой, которую он допустил при его разработке; «Отсутствие таковых привело к тому, что все заново изобретали велосипед и к ненужному разнообразию в самых фундаментальных классах». [ 3 ]

Проблемы реализации

[ редактировать ]

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

string a = "hello!";
string b = a; // Copy constructor

фактически не копирует содержимое а к б ; вместо этого обе строки совместно используют свое содержимое, и счетчик ссылок на содержимое увеличивается. Фактическое копирование откладывается до тех пор, пока операция изменения, например добавление символа к любой строке, не приведет к различию содержимого строк. Копирование при записи может существенно повысить производительность кода, использующего строки (делая некоторые операции намного быстрее, а некоторые — намного медленнее). Хотя std::string больше не использует его, многие (возможно, большинство) альтернативных строковых библиотек по-прежнему реализуют строки с копированием при записи.

Некоторые реализации строк хранят 16-битные или 32-битные кодовые точки вместо байтов. Это было сделано для облегчения обработки текста в Юникоде . [ 5 ] Однако это означает, что преобразование в эти типы из std::string или из массивов байтов зависит от «локали» и может вызывать исключения. [ 6 ] переменной ширины Любые преимущества обработки 16-битных кодовых единиц исчезли, когда была введена кодировка UTF-16 (хотя преимущества все еще есть, если вам необходимо взаимодействовать с 16-битным API, таким как Windows). Qt QString является примером. [ 5 ]

Сторонние реализации строк также значительно различались по синтаксису извлечения или сравнения подстрок или выполнения поиска в тексте.

Стандартные типы строк

[ редактировать ]

The Класс std::string является стандартным представлением текстовой строки, начиная с C++98 . Класс предоставляет некоторые типичные операции со строками, такие как сравнение, конкатенация, поиск и замена, а также функцию получения подстрок . Ан std::string может быть создан из строки в стиле C, а строка в стиле C также может быть получена из нее. [ 7 ]

Отдельные единицы, составляющие строку, имеют тип char , как минимум (и почти всегда) по 8 бит каждый. В современном использовании это часто не «символы», а части многобайтовой кодировки символов, такой как UTF-8 .

Стратегия копирования при записи была намеренно разрешена первоначальным стандартом C++ для std::string, потому что это считалось полезной оптимизацией и использовалось почти во всех реализациях. [ 7 ] Однако были и ошибки, в частности Оператор[] возвращал неконстантную ссылку, чтобы упростить перенос манипуляций со строками на языке C (такой код часто предполагал один байт на символ, и поэтому это, возможно, было не очень хорошей идеей!) Это позволило использовать следующий код, который показывает, что он должен сделать копию, хотя почти всегда он используется только для проверки строки, а не для ее изменения: [ 8 ] [ 9 ]

  std::string original("aaaaaaa");
  std::string string_copy = original; // make a copy
  char* pointer = &string_copy[3]; // some tried to make operator[] return a "trick" class but this makes it complex
  arbitrary_code_here(); // no optimizations can fix this
  *pointer = 'b'; // if operator[] did not copy, this would change original unexpectedly

Это вызвало некоторые реализации [ который? ] отказаться от копирования при записи. Также было обнаружено, что накладные расходы в многопоточных приложениях из-за блокировки, необходимой для проверки или изменения счетчика ссылок, превышают накладные расходы на копирование небольших строк на современных процессорах. [ 10 ] (особенно для строк, меньших размера указателя). Оптимизация была окончательно запрещена в C++11 . [ 8 ] в результате чего даже прохождение std::string в качестве аргумента функции, а именно.

void print(std::string s) { std::cout << s; }

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

void print(const std::string& s) { std::cout << s; }

В C++17 добавлен новый string_view класс [ 11 ] это всего лишь указатель и длина данных, доступных только для чтения, что делает передачу аргументов намного быстрее, чем в любом из приведенных выше примеров:

void print(std::string_view s) { std::cout << s; }
...
  std::string x = ...;
  print(x); // does not copy x.data()
  print("this is a literal string"); // also does not copy the characters!
...

Пример использования

[ редактировать ]
#include <iostream>
#include <iomanip>
#include <string>

int main() {
    std::string foo = "fighters";
    std::string bar = "stool";
    if (foo != bar) std::cout << "The strings are different!\n";
    std::cout << "foo = " << std::quoted(foo)
              << " while bar = " << std::quoted(bar);
}
[ редактировать ]

std::string — это определение типа для конкретного экземпляра std::basic_string Класс шаблона . [ 12 ] Его определение можно найти в Заголовок <строка> :

using string = std::basic_string<char>;

Таким образом строка обеспечивает Функциональность Basic_string для строк, имеющих элементы типа чар . Есть аналогичный класс std::wstring , который состоит из wchar t и чаще всего используется для хранения UTF-16 текста в Windows и UTF-32 на большинстве Unix-подобных платформ. Однако стандарт C++ не налагает на эти типы никакой интерпретации как кодовых точек или кодовых единиц Юникода и даже не гарантирует, что wchar_t содержит больше бит, чем чар . [ 13 ] Чтобы устранить некоторые несовместимости, возникающие в результате wchar_t , в C++11 добавлены два новых класса: std::u16string и std::u32string (составленный из новых типов char16_t и char32_t ), которые представляют собой заданное количество бит на единицу кода на всех платформах. [ 14 ] В C++11 также добавлены новые строковые литералы из 16-битных и 32-битных «символов» и синтаксис для помещения кодовых точек Юникода в строки с нулевым завершением (стиль C). [ 15 ]

А Basic_string гарантированно будет специализироваться для любого типа с char_traits, сопровождающая его. Начиная с C++11, только чар , wchar_t , char16_t и char32_t . Необходимо реализовать специализации [ 16 ]

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

Дизайн std::string был приведен в качестве примера монолитного проектирования Хербом Саттером , который считает, что из 103 функций-членов класса в C++98 71 можно было бы отделить без потери эффективности реализации. [ 17 ]

  1. ^ Jump up to: а б Сикорд, Роберт С. (2013). Безопасное программирование на C и C++ . Аддисон-Уэсли. ISBN  9780132981972 .
  2. ^ Уаллин, Стив (2003). Практическое программирование на C++ . О'Рейли.
  3. ^ Jump up to: а б Страуструп, Бьярн (1993). История C++: 1979–1991 (PDF) . Учеб. Конференция ACM по истории языков программирования.
  4. ^ Jump up to: а б Солтер, Николас А.; Клепер, Скотт Дж. (2005). Профессиональный С++ . Джон Уайли и сыновья. п. 23. ISBN  9780764589492 .
  5. ^ Jump up to: а б Бланшетт, Жасмин; Саммерфилд, Марк (2008). Программирование GUI на C++ с помощью Qt4 . Пирсон Образование. ISBN  9780132703000 .
  6. ^ «Класс wstring_convert» . docs.microsoft.com . 3 августа 2021 г. Проверено 26 декабря 2021 г.
  7. ^ Jump up to: а б Мейерс, Скотт (2012), Эффективный STL , Аддисон-Уэсли, стр. 64–65, ISBN  9780132979184
  8. ^ Jump up to: а б Мередит, Алисдер; Бём, Ганс; Кроул, Лоуренс; Димов, Петр (2008). «Модификации параллельной обработки базовой строки» . ISO/IEC JTC 1/SC 22 /WG 21 . Проверено 19 ноября 2015 г.
  9. ^ «21334 — Отсутствие безопасности потоков, совместимой с Posix, в STD::basic_string» .
  10. ^ Саттер, Херб (1999). «Оптимизации, которых нет (в многопоточном мире)» . Журнал пользователей C/C++ . 17 (6).
  11. ^ «std::basic_string_view – cppreference.com» . ru.cppreference.com . Проверено 23 июня 2016 г.
  12. ^ «Справочник по C++ для Basic_string» . Cppreference.com . Проверено 11 января 2011 г.
  13. ^ Гиллам, Ричард (2003). Демистификация Unicode: Практическое руководство программиста по стандарту кодирования . Аддисон-Уэсли Профессионал. п. 714. ИСБН  9780201700527 .
  14. ^ «Документ C++11 N3336» . Открытые стандарты . Язык программирования C++, Библиотечная рабочая группа. 13 января 2012 года . Проверено 2 ноября 2013 г.
  15. ^ Страуструп, Бьярне (2013). Язык программирования C++ . Эддисон Уэсли. п. 179. Архивировано из оригинала 25 ноября 2015 года . Проверено 24 ноября 2015 г.
  16. ^ «char_traits — Справочник по C++» . Проверено 1 августа 2015 г.
  17. ^ Саттер, Херб. «Монолиты «Не натянуты» » . gotw.ca. ​Проверено 23 ноября 2015 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 3ccd9a8313f73533da20691a07640bdd__1714288980
URL1:https://arc.ask3.ru/arc/aa/3c/dd/3ccd9a8313f73533da20691a07640bdd.html
Заголовок, (Title) документа по адресу, URL1:
C++ string handling - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)