2

編集: 私はstdio.hとstdlib.hしか使用できません

charsで満たされたchar配列を繰り返し処理したいと思います。

ただし、ä、öのような文字は2倍のスペースを占め、2つの要素を使用します。これが私の問題の原因です。これらの特別な文字にアクセスする方法がわかりません。

私の例では、文字「ä」はhmm[0]とhmm[1]を使用します。

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

int main()
{
  char* hmm = "äö";

  printf("%c\n", hmm[0]); //i want to print "ä"

  printf("%i\n", strlen(hmm));

  return 0;
}

おかげで、添付のコードをEclipseで実行しようとしましたが、動作します。64ビットを使用し、「ä」には十分なスペースがあるためだと思います。strlenは、各「ä」が1つの要素としてのみカウントされることを確認します。だから私はどういうわけかそれを各文字にもっと多くのスペースを割り当てるように言うことができると思います(「ä」が収まるように)?

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

int main()
{
 char* hmm = "äüö";

  printf("%c\n", hmm[0]);
  printf("%c\n", hmm[1]);
  printf("%c\n", hmm[2]);

  return 0;
}
4

4 に答える 4

4

charは常に1バイトを使用しました。

あなたの場合、「ä」は1文字だと思います:間違っています。16進ビューアで.cソースコードを開くと、ファイルがUTF8でエンコードされているため、äが2文字を使用していることがわかります。

ここで問題は、ワイド文字を使用しますか?

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

int main()
{
    const wchar_t hmm[] = L"äö";

    setlocale(LC_ALL, "");
    wprintf(L"%ls\n", hmm);
    wprintf(L"%lc\n", hmm[0]);
    wprintf(L"%i\n", wcslen(hmm));

    return 0;
}
于 2012-12-29T16:43:00.370 に答える
2

データはマルチバイトエンコーディングです。したがって、文字列を分割するには、マルチバイト文字処理技術を使用する必要があります。例えば:

#include <stdio.h>
#include <string.h>
#include <locale.h>

int main(void)
{
    char* hmm = "äö";
    int off = 0;
    int len;
    int max = strlen(hmm);

    setlocale(LC_ALL, "");

    printf("<<%s>>\n", hmm);
    printf("%zi\n", strlen(hmm));

    while (hmm[off] != '\0' && (len = mblen(&hmm[off], max - off)) > 0)
    {
        printf("<<%.*s>>\n", len, &hmm[off]);
        off += len;
    }

    return 0;
}

私のMacでは、次のように生成されました。

<<äö>>
4
<<ä>>
<<ö>>

への呼びかけsetlocale()は非常に重要でした。en_US.UTF-8それがないと、プログラムは私のロケールではなく「C」ロケールで実行され、次のようにmblen()誤って処理されます。

<<äö>>
4
<<?>>
<<?>>
<<?>>
<<?>>

疑問符が表示されるのは、UTF-8端末に関する限り、印刷されるバイトが無効な1バイトであるためです。

benjarobin回答に示されているように、ワイド文字とワイド文字印刷を使用することもできます。

于 2012-12-29T17:08:04.970 に答える
1

これをドラッグして申し訳ありません。いくつかの問題を強調することが重要だと思いますが。私が理解しているように、OS-XにはデフォルトのOSコードページをUTF-8にする機能があるため、答えは主にWindowsに関するものであり、内部ではUTF-16を使用しており、デフォルトのACPコードページは指定されたOSリージョン。


まず、文字コード表を開いて、そのäöを見つけることができます

どちらもコードページ1252(西部)にあるため、これはMBCSの問題ではありません。MBCSの問題である可能性がある唯一の方法は、MBCS(Shift-JIS、Big5、韓国語、GBK)エンコーディングを使用してファイルを保存した場合です。


setlocale(LC_ALL、 "")を使用する答え

コマンドプロンプトウィンドウでäöが正しく表示されなかった理由についての洞察は得られません。

コマンドプロンプトは、独自のコードページ、つまりOEMコードページを使用します。これは、文字コード表で利用可能な次の(OEM)コードページへの参照です。

コマンドプロンプトに移動して次のコマンド (Chcp)を入力すると、コマンドプロンプトが使用している現在のOEMコードページが表示されます。

setlocal(LC_ALL、 "")を使用したMicrosoftのドキュメントに従って、次の動作について詳しく説明します。

setlocale(LC_ALL、 "");
ロケールをデフォルトに設定します。これは、オペレーティングシステムから取得したユーザーデフォルトのANSIコードページです。

chcpを使用して必要なコードページを渡すことにより、これを手動で行うことができます。次に、アプリケーションを実行すると、テキストが完全に正常に出力されます。

マルチバイト文字セットの問題である場合は、他の問題の全リストがあります

MBCSでは、文字は1バイトまたは2バイトでエンコードされます。2バイト文字では、最初のバイト、つまり「リードバイト」は、それと次のバイトの両方が1文字として解釈されることを示します。最初のバイトは、リードバイトとして使用するために予約されたコードの範囲から取得されます。どのバイト範囲をリードバイトにすることができるかは、使用しているコードページによって異なります。たとえば、日本のコードページ932はリードバイトとして0x81から0x9Fの範囲を使用しますが、韓国のコードページ949は別の範囲を使用します。

状況を見ると、長さは2ではなく4でした。ファイル形式はUTF-8で保存されていると言えます(実際にはUTF-16で保存できますが、より早く問題が発生する可能性があります。後でコンパイラで)。0〜127のASCII範囲内にない文字を使用しています。UTF-8はUnicodeコードポイントを2バイトにエンコードしています。コンパイラはファイルを開き、デフォルトのOSコードページまたはANSI Cを想定しています。文字列を解析するとき、コンパイラは文字列をANSIC文字列1バイト=1文字として解釈します。

この問題を解決するには、WindowsでUTF-8文字列をUTF-16に変換し、wprintfで出力します。現在、Ascii /MBCSstdio関数のネイティブUTF-8サポートはありません。

デフォルトのOSコードページがUTF-8であるMacOS-Xの場合、よりエレガントであるため、この問題に対するJonathanLefflerのソリューションに従うことをお勧めします。後でWindowsに移植する場合は、次の例を使用して、UTF-8からUTF-16への文字列を変換する必要があります。

どちらのソリューションでも、ASCIIより上の文字を正しく印刷するには、コマンドプロンプトのコードページをオペレーティングシステムのコードページに変更する必要があります。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <locale>

// File saved as UTF-8, with characters outside the ASCII range
int main()
{
    // Set the OEM code page to be the default OS code page
    setlocale(LC_ALL, "");

    // äö reside outside of the ASCII range and in the Unicode code point Western Latin 1
    // Thus, requires a lead byte per unicode code point when saving as UTF-8
    char* hmm = "äö";

    printf("UTF-8 file string using Windows 1252 code page read as:%s\n",hmm);
    printf("Length:%d\n", strlen(hmm));

    // Convert the UTF-8 String to a wide character
    int nLen = MultiByteToWideChar(CP_UTF8, 0,hmm, -1, NULL, NULL);
    LPWSTR lpszW = new WCHAR[nLen];
    MultiByteToWideChar(CP_UTF8, 0, hmm, -1, lpszW, nLen);

    // Print it
    wprintf(L"wprintf wide character of UTF-8 string: %s\n", lpszW); 

    // Free the memory
    delete[] lpszW;

    int c = getchar();
    return 0;
}


UTF-8 file string using Windows 1252 code page read as:äö
Length:4
wprintf wide character of UTF-8 string: äö
于 2012-12-30T07:17:47.333 に答える
0

コマンドプロンプトのフォント/コードページをチェックして、OSのシングルバイトエンコーディングを表示できることを確認します。コマンドプロンプトには、テキストエディタとは異なる独自のコードページがあります。

于 2012-12-29T16:48:12.210 に答える