Ciągi (C++/CX)
Tekst w środowisko wykonawcze systemu Windows jest reprezentowany w języku C++/CX przez klasę Platform::String. Użyj metody Platform::String Class
podczas przekazywania ciągów do metod w klasach środowisko wykonawcze systemu Windows lub podczas interakcji z innymi składnikami środowisko wykonawcze systemu Windows w granicach interfejsu binarnego aplikacji (ABI). Udostępnia Platform::String Class
metody dla kilku typowych operacji ciągów, ale nie jest przeznaczony do bycia w pełni funkcjonalna klasa ciągów. W module języka C++ użyj standardowych typów ciągów języka C++, takich jak wstring dla dowolnego znaczącego przetwarzania tekstu, a następnie przekonwertuj wynik końcowy na Platform::String^ przed przekazaniem go do lub z interfejsu publicznego. Konwersja między elementami wstring
i wchar_t*
i Platform::String
jest łatwa i wydajna.
Szybkie przekazywanie
W niektórych przypadkach kompilator może sprawdzić, czy może bezpiecznie skonstruować Platform::String
element lub przekazać element String
do funkcji bez kopiowania danych ciągów bazowych. Takie operacje są nazywane szybkim przekazywaniem i są wykonywane w sposób niewidoczny.
Konstrukcja ciągów
Wartość String
obiektu jest niezmienną sekwencją char16
(tylko do odczytu) znaków (16-bitowych Unicode). String
Ponieważ obiekt jest niezmienny, przypisanie nowego literału ciągu do String
zmiennej faktycznie zastępuje oryginalny String
obiekt nowym String
obiektem. Operacje łączenia obejmują zniszczenie oryginalnego String
obiektu i utworzenie nowego obiektu.
Literały
Znak literału jest znakiem ujętym w pojedynczy cudzysłów, a ciąg literału to sekwencja znaków ujęta w podwójny cudzysłów. Jeśli używasz literału do inicjowania zmiennej String^, kompilator zakłada, że literał składa się z char16
znaków. Oznacza to, że nie trzeba poprzedzać literału modyfikatorem ciągu "L" ani ująć literału w makro _T() ani TEXT(). Aby uzyskać więcej informacji na temat obsługi języka C++ dla formatu Unicode, zobacz Podsumowanie programowania Unicode.
W poniższym przykładzie przedstawiono różne sposoby konstruowania String
obiektów.
// 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());
Operacje obsługi ciągów
Klasa String
udostępnia metody i operatory do łączenia, porównywania ciągów i innych podstawowych operacji ciągów. Aby wykonać bardziej rozbudowane manipulowanie ciągami, użyj String::Data()
funkcji składowej, aby pobrać wartość String^
obiektu jako const wchar_t*
. Następnie użyj tej wartości, aby zainicjować std::wstring
element , który zapewnia zaawansowane funkcje obsługi ciągów.
// 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];
Konwersje ciągów
Znak Platform::String
może zawierać tylko char16
znaki lub NULL
znak. Jeśli aplikacja musi pracować z 8-bitowymi znakami, użyj ciągu::D ata , aby wyodrębnić tekst jako const wchar_t*
. Następnie możesz użyć odpowiednich funkcji systemu Windows lub funkcji biblioteki standardowej, aby wykonywać operacje na danych i konwertować je z powrotem na wchar_t*
ciąg lub, którego można użyć do utworzenia nowego Platform::String
elementu .
Poniższy fragment kodu pokazuje, jak przekonwertować zmienną String^
na zmienną i z zmiennej wstring
. Aby uzyskać więcej informacji na temat manipulowania ciągami używanymi w tym przykładzie, zobacz 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() );
Długość ciągu i osadzone wartości NULL
Ciąg ::Length zwraca liczbę znaków w ciągu, a nie liczbę bajtów. Znak null zakończenia nie jest zliczany, chyba że jawnie określisz go podczas tworzenia ciągu za pomocą semantyki stosu.
Obiekt Platform::String
może zawierać osadzone wartości NULL, ale tylko wtedy, gdy wartość NULL jest wynikiem operacji łączenia. Osadzone listy NUL nie są obsługiwane w literałach ciągu; w związku z tym nie można użyć osadzonych list NUL w ten sposób, aby zainicjować Platform::String
element . Osadzone wartości NULL w obiekcie Platform::String
są ignorowane, gdy ciąg jest wyświetlany, na przykład gdy jest przypisany do TextBlock::Text
właściwości. Osadzone listy NUL są usuwane, gdy wartość ciągu jest zwracana przez Data
właściwość .
CiągReference
W niektórych przypadkach kod (a) odbiera ciąg std::wstring lub wchar_t ciąg lub literał ciągu L"" i po prostu przekazuje go do innej metody, która przyjmuje ciąg^ jako parametr wejściowy. Tak długo, jak oryginalny bufor ciągu pozostaje prawidłowy i nie mutuje przed zwróceniem funkcji, można przekonwertować wchar_t*
ciąg lub literał ciągu na platform::StringReference i przekazać go zamiast Platform::String^
. Jest to dozwolone, ponieważ StringReference
ma zdefiniowaną przez użytkownika konwersję na Platform::String^
. Za pomocą StringReference
polecenia można uniknąć tworzenia dodatkowej kopii danych ciągu. W pętlach, w których przekazujesz dużą liczbę ciągów lub podczas przekazywania bardzo dużych ciągów, możesz potencjalnie osiągnąć znaczną poprawę wydajności przy użyciu polecenia StringReference
. Ale ponieważ StringReference
zasadniczo pożycza oryginalny bufor ciągów, musisz użyć skrajnej opieki, aby uniknąć uszkodzenia pamięci. Nie należy przekazywać StringReference
elementu do metody asynchronicznej, chyba że oryginalny ciąg ma być w zakresie, gdy ta metoda zwróci wartość . Ciąg^ zainicjowany z parametru StringReference wymusi alokację i kopię danych ciągu, jeśli wystąpi druga operacja przypisania. W takim przypadku utracisz korzyści z wydajności programu StringReference
.
Należy pamiętać, że StringReference
jest standardowym typem klasy C++, a nie klasą ref, nie można jej używać w publicznym interfejsie zdefiniowanych klas ref.
W poniższym przykładzie pokazano, jak używać metody 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
}
}