1

下面的代码给出了一个非常奇怪的结果:

#include <iostream>
#include <fstream>

using namespace std;

ifstream f("f1.in");
ofstream g("f1.out");
char sir[255];
int i;

char strlwr(char sir[]) //if void nothing changes
{
    int i = 0;

    for (i = 0; sir[i] != NULL; i++) {
        sir[i] = tolower(sir[i]);
    }

    return 0;  //if instead of 0 is 1 it will kinda work , but strlwr(sir) still needs to   be displayed
}

int main()
{
    f.get(sir, 255);
    g << sir << '\n'; // without '\n' strlwr will no more maters
    g << strlwr(sir);
    g << sir;
    return 0;
}

f1.in:

JHON HAS A COW

f1.out:

䡊乏䠠十䄠䌠坏 
桪湯栠獡愠挠睯

它仅在我仅使用 CAPS 时显示。
我在欧洲版 Ubuntu 14 上使用 Code::Blocks 13.12。
我很想知道为什么它会显示这一点。
我有兴趣知道它是否给你同样的东西。

4

1 回答 1

1

恭喜!你发现了mojibake!您的输出文本是 100% 正确的,但无论您使用什么查看它,都将其解释为 unicode。

如果将 unicode 输出转换为十六进制数值,问题就会变得清晰。(从这个 StackOverflow 答案中借用的代码。)

$ cat unicode.txt
䡊乏䠠十䄠䌠坏
桪湯栠獡愠挠睯

$ cat unicode.txt | while IFS= read -r -d '' -n1 c; do printf "%02X\n" "'$c"; done
484A
4E4F
4820
5341
4120
4320
574F
0A
686A
6E6F
6820
7361
6120
6320
776F
0A

第二个命令逐字符读取文件并以十六进制打印小端形式。每个字符是两个字节数据的原因是因为输入被理解为 UTF-16,即 2 字节编码。

如果您将十六进制输出重新解释为单字节 ASCII(并纠正字节顺序),您可以看到您的程序确实有效:

$ cat unicode.txt | while IFS= read -r -d '' -n1 c; do printf "%02X\n" "'$c"; done
484A ; JH
4E4F ; ON
4820 ;  H
5341 ; AS
4120 ;  A
4320 ;  C
574F ; OW
0A   ; \n
686A ; jh
6E6F ; on
6820 ;  h
7361 ; as
6120 ;  a
6320 ;  c
776F ; ow
0A   ; \n

要确定问题是您的 C++ 程序还是您的查看程序,请尝试运行以下命令xxd f1.out。如果它看起来像 ASCII,那是你的观看程序有问题。否则,这是您的程序的错误,您应该查看setlocale和/或以二进制模式打开输出文件。

无论哪种方式,您都应该更改g<<strlwr(sir);为 just strlwr(sir);。目前它正在向您的输出中添加一个 NULL 字节,这可能是无意的。

于 2014-10-29T17:55:51.643 回答