【问题标题】:How do I reverse the order of characters in a text file in C++?如何在 C++ 中反转文本文件中的字符顺序?
【发布时间】:2020-01-15 22:44:17
【问题描述】:

我正在尝试编写一个小程序来反转文本文件中的字符顺序。它有效,但它奇怪地处理撇号和其他特殊字符。

这是我的代码:

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    

【问题讨论】:

标签: c++ text


【解决方案1】:

您的输入文件可能以多字节字符集编码。不过,它似乎不是 UTF-8,因为 在 UTF-8 中被编码为字节 E2 80 94,当用 Latin-1 解释时是 —,而 是用 UTF-8 编码的作为字节E2 80 99,当用Latin-1 解释时是’。不过,这不是您在输出中看到的。但症状相似。您正在按原样反转string 中的编码chars,这不适用于多字节编码。

要正确反转多字节编码字符串,您必须事先知道编码并根据该编码遍历字符串,提取编码单元的每个完整序列并将每个完整单元按原样保存到输出中,而不是按原样阅读和保存个人chars。 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,然后再将其编码保存为输出文件。

另外,如果您要按原样处理单个chars,以确保正确读取和写入原始chars,您应该以二进制模式打开文件,并使用未格式化的输入/输出操作(即,没有operator&gt;&gt;operator&lt;&lt;):

ifstream ifs(name, std::ios::binary);
if (!ifs) throw runtime_error("Couldn't open input file.");

ofstream ofs("output.txt", std::ios::binary);
if (!ofs) throw runtime_error("Couldn't open output file.");

// Note: there are easier ways to read a file into a std::string!
// See: https://stackoverflow.com/questions/116038/
string s;
for(char ch; ifs.get(ch);)
    s.push_back(ch);

reverse(s.begin(), s.end());

for(char ch: s)
    ofs.put(ch);
// alternatively:
// ofs.write(s.c_str(), s.size());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多