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

おめでとう!モジバケを発見しました!出力テキストは 100% 正しいですが、それをどのように表示しても Unicode として解釈されます。

Unicode 出力を 16 進数の数値に変換すると、問題が明確になります。(この StackOverflow answerから借用したコード。)

$ 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

2 番目のコマンドは、ファイルを 1 文字ずつ読み取り、リトル エンディアン形式を 16 進数で出力します。各文字が 2 バイトのデータである理由は、入力が 2 バイトのエンコーディングである UTF-16 であると認識されるためです。

代わりに 16 進出力を 1 バイト 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 に答える