2016-11-14 27 views
4

printfがワイド文字(wchar_t)でどのように機能するのかを理解しようとしています。printfでワイド文字を表示する

サンプル1:

#include <stdio.h> 
#include <stdlib.h> 

int  main(void) 
{ 
    wchar_t  *s; 

    s = (wchar_t *)malloc(sizeof(wchar_t) * 2); 
    s[0] = 42; 
    s[1] = 0; 
    printf("%ls\n", s); 
    free(s); 
    return (0); 
} 

出力:

* 

すべてがここに罰金です:私のキャラクター(*)が正しくあり

私は、次のコードサンプルを作りました表示されます。

サンプル2:

他の種類の文字を表示したかったのですが、私のシステムでは、wchar_tは4バイトでエンコードされているようです。 、s[0](0xC389、201のために(参照、前のリンクを) É

#include <stdio.h> 
#include <stdlib.h> 

int  main(void) 
{ 
    wchar_t  *s; 

    s = (wchar_t *)malloc(sizeof(wchar_t) * 2); 
    s[0] = 0xC389; 
    s[1] = 0; 
    printf("%ls\n", s); 
    free(s); 
    return (0); 
} 

しかし、この時間は、私は「エンコーディング」セクションから多くの値を試みた出力がない。だから私は、次の文字を表示しようとしました0xC9)...しかし、私はÉ文字を表示することはありません。私も%lsの代わりに%Sで試しました。

このようにprintfを呼び出そうとすると:printf("<%ls>\n", s)唯一の文字が表示されます'<'、表示が切り捨てられます。

なぜこの問題がありますか?どうすればいいですか?

+0

2つの要素の配列を宣言する代わりに動的に割り当てる理由はありますか? –

+0

'scanf("%1ls ")' a '"É "'を読んで、 'printf("%lX \ n "、(unsigned long)s [0])'の値を報告してください。 – chux

+0

@chux 'printf("%ld \ n "、(unsigned long int)L'É ');'私に '201'を与えます。 – vmonteco

答えて

4

なぜこの問題がありますか?

errnoと戻り値printfを必ず確認してください!

#include <stdio.h> 
#include <stdlib.h> 
#include <wchar.h> 

int main(void) 
{ 
    wchar_t *s; 
    s = (wchar_t *) malloc(sizeof(wchar_t) * 2); 
    s[0] = 0xC389; 
    s[1] = 0; 

    if (printf("%ls\n", s) < 0) { 
     perror("printf"); 
    } 

    free(s); 
    return (0); 
} 

出力を参照してください:

$ gcc test.c && ./a.out 
printf: Invalid or incomplete multibyte or wide character 

すべての

ファーストを修正する方法、CプログラムのデフォルトのロケールがCある(またPOSIXとして知られている)ASCIIのみです。 setlocale、具体的にはsetlocale(LC_ALL,"")への通話を追加する必要があります。

LC_ALL,LC_CTYPEまたはLANGの環境変数で、空白の場合にUTF-8を許可するように設定されていない場合は、明示的にロケールを選択する必要があります。ほとんどのシステムでsetlocale(LC_ALL, "C.UTF-8")が動作します - Cが標準であり、UTF-8サブセットCが一般的に実装されています。

#include <stdio.h> 
#include <stdlib.h> 
#include <locale.h> 
#include <wchar.h> 

int main(void) 
{ 
    wchar_t *s; 
    s = (wchar_t *) malloc(sizeof(wchar_t) * 2); 
    s[0] = 0xC389; 
    s[1] = 0; 

    setlocale(LC_ALL, ""); 

    if (printf("%ls\n", s) < 0) { 
     perror("printf"); 
    } 

    free(s); 
    return (0); 
} 

出力を参照してください:wchar_tは(例えばUTF-32など)ワイド文字ではなく、このようなUTF-などのマルチバイト文字を(表すので、間違った文字をプリントアウトする理由

$ gcc test.c && ./a.out 
쎉 

理由があります8)。 wchar_tはGNU Cライブラリでは常に32ビットですが、C標準ではそのようにする必要はありません。あなたはUTF-32BEエンコーディング(すなわち0x000000C9)を使用して文字を初期化する場合、それは正しく出力し:

#include <stdio.h> 
#include <stdlib.h> 
#include <locale.h> 
#include <wchar.h> 

int main(void) 
{ 
    wchar_t *s; 
    s = (wchar_t *) malloc(sizeof(wchar_t) * 2); 
    s[0] = 0xC9; 
    s[1] = 0; 

    setlocale(LC_ALL, ""); 

    if (printf("%ls\n", s) < 0) { 
     perror("printf"); 
    } 

    free(s); 
    return (0); 
} 

出力:あなたも経由LC(ロケール)の環境変数を設定することができ

$ gcc test.c && ./a.out 
É 

注意コマンドライン:

$ LC_ALL=C.UTF-8 
$ ./a.out 
É 
3

シングルバイトエンコーディング方式であるUTF-8をマルチバイトエンコーディングとしてエンコードしようとしているという問題が1つあります。 UTF-8では、普通のcharを使用します。

はまた、あなたがマルチバイト型にUTF-8シーケンスを結合しようとするので、あなたはendianness(バイト順)の問題(メモリ0xC389にその順序で、0x890xC3として格納される可能性があります)を持っていることに注意してください。 そしてコンパイラがあなたの番号をも符号拡張します(sizeof(wchar_t) == 4で、デバッガでs[0]を見ると0xFFFFC389かもしれません)。

もう1つの問題は、印刷に使用する端末またはコンソールです。たぶんUTF-8や他のエンコーディングをサポートしていないのでしょうか?

関連する問題