簡體   English   中英

帶有非ASCII字符的反向字符串

[英]Reverse string with non-ASCII characters

我想用特殊字符更改字符串中的順序,如下所示:

ZAŻÓŁĆGĘŚLĄJAŹŃ

ŃŹAJĄŁŚĘGĆŁÓŻAZ

我嘗試使用std :: reverse

std::string text("ZAŻÓŁĆ GĘŚLĄ JAŹŃ!");
std::cout << text << std::endl;
std::reverse(text.rbegin(), text.rend());
std::cout << text << std::endl;

但輸出顯示:

ZAŻÓŁĆGĘŚLĄJAŹŃ!

!\\203Ź\\ 305AJ \\ 204 \\ 304L \\232Ř\\ 304G \\206āœû\\ 305AZ < - 反向弦

所以我嘗試“手動”:

std::string text1("ZAŻÓŁĆ GĘŚLĄ JAŹŃ!");
std::cout << text1 << std::endl;
int count = (int) floorf(text1.size() /2.f);
std::cout << count  << "  " << text1.size() << std::endl;

unsigned int maxIndex = text1.size() - 1;
for (int i = 0; i < count ; i++)
{
    char tmp = text1[i];
    text1[i] = text1[maxIndex];
    text1[maxIndex] = tmp;
    maxIndex--;
}
std::cout << text1 << std::endl;

但在這種情況下,我在text1.size()中遇到問題,因為每個特殊字符都被計算兩次:

ZAŻÓŁĆGĘŚLĄJAŹŃ!

13 27 < - 第二個數字是text1.size()

!\\203Ź\\ 305AJ \\ 204 \\ 304L \\232Ř\\ 304G \\206āœû\\ 305AZ

如何用特殊字符反轉字符串的正確方法?

您的代碼確實正確地反轉了字符串中的字節,這里沒有任何錯誤。 但問題是你的編譯器存儲了你的文字字符串“ZAŻÓŁĆGĘŚLĄJAŹŃ!” 采用UTF-8編碼。

並且UTF-8將除了匹配ASCII的字符之外的所有字符存儲為可變長度的字節序列 這意味着一個char (一個字節)不再是一個字符,因此反轉char現在與反轉字符不同。

為了實現您的目標,您至少有兩個選擇:

  1. 使用一些utf-8庫,它可以讓你迭代字符而不是字節。 一個例子是http://utfcpp.sourceforge.net/
  2. 不知何故(這在很大程度上取決於您正在使用的編譯器和操作系統)切換到具有恆定字符長度的utf-32編碼,並且具有良好的舊的常量字符大小字符串,而沒有所有這些瘋狂的變量字符大小的麻煩。

UPD:一個很好的鏈接: http//www.joelonsoftware.com/articles/Unicode.html

您可以自己編寫reverseUt8函數代碼:

std::string getMultiByteReversed(char ch1, char ch2)
{  
   if (ch == '\xc3') // most utf8 characters
      return std::string(ch1)+ std::string(ch2);
   } else {
      return std::string(ch1);
   }
}

std::string reverseMultiByteString(const std::string &s)
{
    std::string result;
    for (std::string::reverse_iterator it = s.rbegin(); it != s.rend(); ++it) {
       std::string reversed;
       if ( (it+1) != rbegin() && (reversed = getMultiByteReversed(*it, *it+1) ) {
          result += reversed;
          ++it;
       } else {
          result += *it;
       }
  }
  return result;
}

您可以在http://www.utf8-chartable.de/查找utf8代碼

這里有幾個問題。 答案很復雜,可能完全取決於您要做的事情。

首先是(如其他答案所述)如果您的字符串是UTF-8編碼,則一個Unicode代碼點可能包含多個字節。 如果你只是反轉字節,你將打破UTF-8編碼。 對此最簡單(但不一定是最好的)修復是將字符串轉換為UTF-32並反轉32位代碼點而不是字節。

下一個問題是單個字素可能包含多個Unicode代碼點。 例如,“é”可以編碼為兩個代碼點U + 0065,后跟U + 0301。 如果顛倒這些順序,那將打破它,因為組合字符U + 301現在將與不同的基本字符相關聯。 所以“神奇寶貝”逆轉這種方式會變成“noḿekoP”,重音超過“m”而不是“e”。

現在你可能會認為你可以通過首先將字符串規范化為組合形式來解決這個問題。 然而,這有其自身的問題,因為並非每個字形都可以由單個代碼點表示。 例如,加拿大標志表情符號(🇨🇦)由代碼點U + 1F1E8表示,后跟代碼點U + 1F1E6。 它沒有單一的代碼點。 如果您反轉其代碼點,則會獲得Ascension Island(🇦🇨)的標記。

然后你就有了基於上下文改變形式的語言,而且我對處理這些語言還不太了解。

它可能更接近您想要反轉字形集群 請參閱UAX29:Unicode文本分段

你嘗試過逐個交換字符嗎? 例如,如果字符串長度為奇數,則將第一個字符與最后一個字符交換,將第二個字符與第二個字符交換,直到中間字符為左。 如果字符串lengt是偶數,則將1st替換為last,將2nd替換為second last,直到兩個中間字符都被交換。 這樣,字符串就會反轉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM