Как узнать, имеет ли std :: string правильную кодировку? - PullRequest
0 голосов
/ 07 июня 2018

В моей программе я получаю значение std::string от другой функции, которая читает строки из разных источников, здесь строка всегда содержит не-ASCII символы.

Я отлаживаю программу с помощью Visual Studio.Иногда, когда содержимое строки выглядит корректно в отладчике VS , тогда следующий шаг в порядке (например, используйте эту строку в качестве каталога ввода и вывода).Но иногда содержимое строки выглядит некорректно , поэтому следующий шаг пошёл не так.

В настоящее время я использую QString в качестве моста для преобразования строки "incorect" в "правильную" строку, кодкак ниже.

// get string from somewhere else, sometimes correct sometimes incorrect
string str = getString(); 
QString strQ = QString::fromStdString(str);
str = string(strQ.toLocal8bit);

Но иногда str является «правильным» уже перед преобразованием, в этом случае, если я преобразовываю его с помощью приведенного выше кода, он идет не так.

Так что я предполагаю, что проблема здеськак я могу узнать, имеет ли std::string правильную кодировку?Потому что я не всегда могу судить об этом по глазам.

Да, кодирование - широко обсуждаемая тема переполнения стека, но я все еще не могу найти подходящее решение.

PS правильное строковое значение выглядит как 孙夏^4735 в VS отладчике, неправильное строковое значение выглядит как ????

1 Ответ

0 голосов
/ 07 июня 2018

Вы должны проверить, является ли строка уже в кодировке UTF-8.Что-то вроде следующего кода (никогда не проверял, используйте его для вдохновения).

#include <string>

enum DetectedCoding {ASCII, UTF8, OTHER};

DetectedCoding DetectEncoding(const std::string & s)
{
  const char * cs = s.c_str();
  DetectedCoding d = ASCII;
  while (*cs)
  {
    unsigned char b = (unsigned char)*(cs++);
    if (b & 0x80) { // not a plain ASCII character
      // if the string is already UTF8 encoded, then it must conform to a multibyte sequence standard. Let's verify it
      if (b < 0xC0) // first of all, b must start with 11
        return OTHER; //  no multibyte sequence starts with 10xxxxxx
      // now we expect a number of continuation bytes, depending on the number of ones following the 11
      size_t nCont = 0;
      if (b < 0xE0) // two bytes sequence: 110xxxxx 10xxxxxx
        nCont = 1;
      else if (b < 0xF0) // three bytes sequence: 1110xxxx 10xxxxxx 10xxxxxx
        nCont = 2;
      else if (b < 0xF8) // four bytes sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        nCont = 3;
      else if (b < 0xFC) // five bytes sequence: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        nCont = 4;
      else if (b < 0xFE) // six bytes sequence: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        nCont = 5;
      else
        return OTHER; //  no multibyte sequence starts with 1111111x
      while (nCont--)
        if (((unsigned char)*(cs++) & 0xC0) != 0xC0) // in case string ends, 0 is found so the following test prevents us from illegal memory access
          return OTHER; //  each continuation byte must starts with 10xxxxxx
      d = UTF8;
    }
  }
  return d;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...