C ++ Unicode латинский символ заменить? - PullRequest
0 голосов
/ 23 января 2020

Начиная с текста, содержащего такие символы, как \u00f9, \u00a0, \u00e8 Я хотел бы заменить их эквивалентами ascii ù, è, et c.

Существует моя текущая реализация, которая по какой-то причине каждый то и дело удаляются фрагменты других слов, и я не понимаю, почему:

pos1 = str2.find("\\u00a0");
pos2 = str2.find("\\u00");
pos3 = str2.find("\\u20");
pos4 = str2.find("\\r\\n");
while (pos1 != std::string::npos)
{
    str2.replace(pos1, 6, "");
    pos1 = str2.find("\\u00a0");
}
while (pos2 != std::string::npos)
{
    str2.replace(pos2, 6, "?");
    pos2 = str2.find("\\u00");
}
while (pos3 != std::string::npos)
{
    str2.replace(pos3, 6, "?");
    pos3 = str2.find("\\u20");
}
while (pos4 != std::string::npos)
{
    str2.replace(pos4, 2, "\n");
    pos4 = str2.find("\\r\\n");
}

, и есть пример текста:

William Shakespeare \u00e8 stato un drammaturgo e poeta inglese, considerato come il pi\u00f9 importante scrittore in inglese e generalmente ritenuto il pi\u00f9 eminente drammaturgo della cultura occidentale.\u00a0\r\n

1 Ответ

0 голосов
/ 24 января 2020

Одна проблема, которую я вижу, состоит в том, что \u... последовательности символов всегда состоят из 6 символов, но вы ищете только и заменяете 4 символа, оставляя остальные 2 символа в строке.

Кроме того, вы ищете все последовательности заранее, но при этом вы не принимаете во внимание, что любые замены, сделанные pos1 l oop, сделают недействительными pos2, pos3 и pos4. Тогда любые замены, сделанные pos2 l oop, сделают недействительными pos3 и pos4. И так далее.

Я бы предложил совершенно другую стратегию разбора:

#include <string>
#include <sstream>
#include <iomanip>

...

auto pos = str2.find('\\');
char ch;

while (pos != std::string::npos)
{
    if (++pos == str2.size())
        break;

    switch (str2[pos])
    {
        case 'r':
            ch = '\r';
            str2.replace(pos-1, 2, &ch, 1);
            /* or:
            str2.replace(--pos, 2, "");
            */
            break;

        case 'n':
            ch = '\n';
            str2.replace(pos-1, 2, &ch, 1);
            break;

        case 't':
            ch = '\t';
            str2.replace(pos-1, 2, &ch, 1);
            break;

        case '\\':
            ch = '\\';
            str2.replace(pos-1, 2, &ch, 1);
            break;

        case 'u': {
            std::istringstream iss(str2.substr(pos+1, 4));
            unsigned short u;
            if (!(iss >> std::hex >> u)) {
                ch = '?';
            }
            else
            {
                switch (u)
                {
                    case 0x2019:
                        ch = '\'';
                        break;
                    ...
                    default:
                        if (u <= 256)
                            ch = static_cast<char>(u);
                        else
                            ch = '?';
                        break;
                 }
            }
            str2.replace(pos-1, 6, &ch, 1);
            break;
        }
    }

    pos = str2.find('\\', pos);
}

Live Demo

...