Как изменить порядок символов в текстовом файле в C ++? - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь написать небольшую программу, меняющую порядок символов в текстовом файле. Это работает, но странно обрабатывает апострофы и другие специальные символы.

Вот мой код:

ifstream ifs {name};
if(!ifs) throw runtime_error("Couldn't open input file.");

ofstream ofs{"output.txt"};
if(!ofs) throw runtime_error("Couldn't open output file.");

string s;
for(char ch; ifs.get(ch);)
    s.push_back(ch);

reverse(s.begin(), s.end());
for(char ch: s)
    ofs << ch;

Пример ввода:

And—which is more—you’ll be a Man, my son!

Пример вывода:

!nos ym ,naM a eb llôÄ‚uoyîÄ‚erom si hcihwîÄ‚dnA    

1 Ответ

1 голос
/ 16 января 2020

Ваш входной файл, вероятно, закодирован в многобайтовой кодировке. Это, по-видимому, не UTF-8, поскольку кодируется в UTF-8 как байты E2 80 94, то есть — при интерпретации в Latin-1, а кодируется в UTF-8. в байтах E2 80 99, что ’ при интерпретации в Latin-1. Это не то, что вы видите в своей продукции, хотя. Но симптом похож. Вы переворачиваете закодированные char s в string как есть, что не будет работать для многобайтовой кодировки.

Чтобы правильно перевернуть многобайтовую кодированную строку, вы должны знать кодирование заранее и прохождение по строке на основе этой кодировки, извлечение каждой целой последовательности закодированных блоков и сохранение каждого целого блока как есть на выходе, а не чтение и сохранение отдельных char s как есть. std::reverse() не может помочь вам в этом, если вы не используете итераторы, которые умеют читать и записывать эти целые единицы.

Если вы знаете кодировку заранее, вам может повезти с использованием std::wifstream / std::wofstream вместо этого, где они imbue() 'с подходящим std::locale для кодирования. Затем используйте std::wstring вместо std::string. Однако, по крайней мере, на Windows, где std::wstring использует UTF-16, у вас все еще есть проблема работы с последовательностями из нескольких единиц (хотя и реже, если вы не имеете дело с восточноазиатскими языками). Таким образом, вам может потребоваться преобразовать декодированный вход UTF-16 в UTF-32 перед выполнением реверсирования (тогда вам придется иметь дело с кластерами графических кодов с несколькими кодовыми точками), затем преобразовать UTF-32 в UTF-16, а затем сохранить его в кодированном виде. выходной файл.

Кроме того, если вы собираетесь обрабатывать отдельные char s как есть, чтобы обеспечить правильное чтение и запись необработанных char s, вы должны открыть файлы в двоичном режиме. и используйте неформатированные операции ввода / вывода (ie, нет operator>> или operator<<):

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...