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::Stringjest ł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::wstringelement , 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::Stringelementu .

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::Stringelement . 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
    }
}