Строки (C++/CX)

Текст в среда выполнения Windows представлен в C++/CX классом Platform::String. Platform::String Class Используйте при передаче строк обратно и обратно в методы в классах среда выполнения Windows или при взаимодействии с другими компонентами среда выполнения Windows через границу двоичного интерфейса приложения (ABI). Platform::String Class предоставляет методы для некоторых типичных операций над строками, но он является полнофункциональным классом строки. При разработке модуля в C++ используйте стандартные строковые типы C++ (такие как wstring ) для сложной обработки строк и преобразуйте конечный результат в тип Platform::String^ , прежде чем передать его открытому интерфейсу или получить его из такого интерфейса. Операция преобразования между типом wstring или wchar_t* и типом Platform::Stringпроста и эффективна.

Быстрая передача

В некоторых случаях компилятор может удостовериться, что есть возможность безопасно создать экземпляр класса Platform::String или передать объект String функции, не копируя основные данные строки. Эти операции называются быстрой передачей , и их выполнение прозрачно.

Создание строк

Значение объекта String — неизменяемая (доступная только для чтения) последовательность символов char16 (16-разрядных символов Юникода). Поскольку объект String является неизменяемым, присвоение нового строкового литерала переменной String фактически заменяет исходный объект String новым объектом String . При операции объединения исходный объект String разрушается, и создается новый объект.

Литералы

Символ-литерал — это символ, заключенный в одиночные кавычки, а строка-литерал — это последовательность символов, заключенная в двойные кавычки. Если для инициализации переменной String^ используется литерал, компилятор предполагает, что литерал состоит из символов char16 . Таким образом, нет необходимости указывать перед литералом модификатор строки "L" или заключать литерал в макрос _T() или TEXT() . Дополнительные сведения о поддержке Юникода в C++ см. в разделах Unicode Programming Summary.

В следующем примере показаны различные способы создания объектов String .

// Initializing a String^ by using string literals
String^ str1 = "Test"; // ok for ANSI text only. uses current code page
String^ str2("Test");
String^ str3 = L"Test";
String^ str4(L"Test");


//Initialize a String^ by using another String^
String^ str6(str1);
auto str7 = str2;

// Initialize a String from wchar_t* and wstring
wchar_t msg[] = L"Test";
String^ str8 = ref new String(msg);
std::wstring wstr1(L"Test");
String^ str9 = ref new String(wstr1.c_str());
String^ str10 = ref new String(wstr1.c_str(), wstr1.length());

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

Класс String предоставляет методы и операторы для объединения и сравнения строк и других простейших операций со строками. Для более сложных манипуляций со строками используйте функцию-член String::Data() для получения значения объекта String^ в виде объекта const wchar_t*. Затем с помощью этого значения инициализируйте класс std::wstring, имеющий более богатый набор функций по обработке строк.


 // Concatenation 
 auto str1 = "Hello" + " World";
 auto str2 = str1 + " from C++/CX!";    
 auto str3 = String::Concat(str2, " and the String class");
 
 // Comparison
 if (str1 == str2) { /* ... */ }
 if (str1->Equals(str2)) { /* ... */ }
 if (str1 != str2) { /* ... */ }
 if (str1 < str2 || str1 > str2) { /* ... */};
 int result = String::CompareOrdinal(str1, str2);
 
 if(str1 == nullptr) { /* ...*/};
 if(str1->IsEmpty()) { /* ...*/};

// Accessing individual characters in a String^
 auto it = str1->Begin();
 char16 ch = it[0];

Преобразование строк

Объект Platform::String может содержать только символы char16 или символ NULL . Если приложению нужно работать с 8-разрядными символами, используйте string::D ata для извлечения текста в виде const wchar_t*. Затем можно воспользоваться соответствующими функциям Windows или стандартной библиотеки для выполнения операций с данными и преобразовать их обратно в объект wchar_t* или wstring, из которого можно создать новый объект Platform::String.

В приведенном ниже фрагменте кода демонстрируется, как преобразовать переменную String^ в переменную wstring и обратно. Дополнительные сведения об операциях со строками, используемых в этом примере, см. в разделе basic_string::replace.

// Create a String^ variable statically or dynamically from a literal string. 
String^ str1 = "AAAAAAAA";

// Use the value of str1 to create the ws1 wstring variable.
std::wstring ws1( str1->Data() ); 
// The value of ws1 is L"AAAAAAAA".

// Manipulate the wstring value.
std::wstring replacement( L"BBB" );
ws1 = ws1.replace ( 1, 3, replacement );
// The value of ws1 is L"ABBBAAAA".

// Assign the modified wstring back to str1. 
str1 = ref new String( ws1.c_str() ); 

Длина строки и значения NULL внутри строк

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

Объект Platform::String может содержать значения NULL внутри строки, но только если они получены в результате операции объединения. Значения NULL внутри строки не поддерживаются в строковых литералах, поэтому из нельзя использовать для инициализации объектов Platform::Stringтаким способом. Значения NULL в объектах Platform::String игнорируются при отображении строки, например когда она присваивается свойству TextBlock::Text . Когда строковое значение возвращается свойством Data , значения NULL внутри строки удаляются.

StringReference

В некоторых случаях код (a) получает std::wstring или wchar_t строковый литерал или L", и просто передает его другому методу, который принимает String^ в качестве входного параметра. Если исходный строковый буфер остается допустимым и не изменяется до возвращения результата функцией, строку wchar_t* или строковый литерал можно преобразовать в Platform::StringReference, а затем передать вместо Platform::String^. Это допустимо, поскольку в StringReference имеется определенное пользователем преобразование в тип Platform::String^. Благодаря StringReference можно избежать создания дополнительной копии строковых данных. В циклах, включающих передачу большого количества строк или передачу очень длинных строк, с помощью StringReferenceможно теоретически добиться значительного выигрыша в производительности. Но поскольку StringReference фактически занимает исходный строковый буфер, необходимо соблюдать осторожность, чтобы не повредить память. Не следует передавать StringReference в асинхронный метод, если нет гарантии, что исходная строка будет находиться в области видимости, когда выполнение метода закончится. При инициализации String^ из StringReference происходит принудительное выделение памяти и копирование содержимого строки, если имеется второй оператор присваивания. В этом случае выигрыш в производительности StringReferenceтеряется.

Обратите внимание, что StringReference является типом класса стандартного языка C++, а не ссылочным классом; его нельзя использовать в определяемых пользователем открытых интерфейсах ссылочных классов.

В следующем примере показано, как использовать StringReference.

void GetDecodedStrings(std::vector<std::wstring> strings)
{
    using namespace Windows::Security::Cryptography;
    using namespace Windows::Storage::Streams;

    for (auto&& s : strings)
    {
        // Method signature is IBuffer^ CryptographicBuffer::DecodeFromBase64String (Platform::String^)
        // Call using StringReference:
        IBuffer^ buffer = CryptographicBuffer::DecodeFromBase64String(StringReference(s.c_str()));

        //...do something with buffer
    }
}