マルチバイトの変換後出力が一文字だけになってしまう

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ぷぷぷジューシー
記事: 28
登録日時: 3年前
住所: アンドロメダ銀河系のどこかに住んでいる

マルチバイトの変換後出力が一文字だけになってしまう

#1

投稿記事 by ぷぷぷジューシー » 3年前

url解析機を作っていてワイド文字に変換した方がアジア系の言語が扱えると聞いたのでマルチバイトを一時的にワイド文字に変換して操作した結果をマルチバイトに変換するという機能です
しかしuchar.hライブラリーを試しに使って引っ掛かりましたそれはprintfで出力してもwしか出力しません。
"wwゴリラハローC言語を丸々を出力するにはどうすればいいのでしょうか
環境は os :windows 10, cコンパイラー: MinGW-W64(8.1.0), ライブラリ: uchar.h, stdio.h, limits.h, stdlib.h
現在参考にしているリンク先https://www.ibm.com/support/knowledgece ... m#mbrtoc32
https://www.ibm.com/support/knowledgece ... 2rtomb.htm
*下のコードが質問に該当するコード

コード:

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

int main(void)
{
    char input[] = "wwゴリラハローC言語";
    char output[MB_LEN_MAX+1];
    char32_t inp32b;
    size_t mbfuncerror;

    mbfuncerror = mbrtoc32(&inp32b, input, (int)(MB_LEN_MAX + 1), NULL);
    if (mbfuncerror < 0){
      printf("変換に失敗しました mbrtoc32()\n");
      printf("エラーコード%d\n", mbfuncerror);
    }

    printf("%d\n",mbfuncerror);
    
    mbfuncerror = c32rtomb(output, inp32b, NULL);
    if (mbfuncerror < 0){
      printf("変換に失敗しました c32rtomb()\n");
      printf("エラーコード%d\n", mbfuncerror);
    }

    output[(int)(sizeof(output))] = '\0';

    printf("%s\n", output);
}
面倒なことはCGo使おう!

Meta3

Re: マルチバイトの変換後出力が一文字だけになってしまう

#2

投稿記事 by Meta3 » 3年前

char output[MB_LEN_MAX + 1];
のMB_LEN_MAX がマルチバイト1文字を表すのに必要なバイト数(の最大値 =5)だからではないですか

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: マルチバイトの変換後出力が一文字だけになってしまう

#3

投稿記事 by みけCAT » 3年前

mbrtoc32 | Programming Place Plus C言語編 標準ライブラリのリファレンス
c32rtomb | Programming Place Plus C言語編 標準ライブラリのリファレンス
これらは「文字」を変換する関数であるため、1文字しか変換しません。
文字列全体を変換するには、最後まで1文字すつ変換するのがいいでしょう。

また、ぷぷぷジューシーさんのコードには、他にも
  • printf()に不適切なデータを渡している(%dはint型のデータを要求するが、渡しているmbfuncerrorはsize_t型)
  • 配列の範囲外に書き込んでいる(outputにはsizeof(output)要素しかない)
という問題があります。

さらに、Wandboxで試したところ、
setlocale()関数でロケールを設定しないとエラーになりました。
実行時の文字コードをUTF-8に(-fexec-charset=utf-8 オプション)しないとエラーになるかもしれません。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uchar.h>
#include <limits.h>
#include <locale.h>

int main(void)
{
    char input[] = "wwゴリラハローC言語";
    int input_done, input_left;
    char output[MB_LEN_MAX+1];
    char32_t inp32b[128];
    int inp32b_count;
    size_t mbfuncerror;
    int i;

    setlocale(LC_CTYPE, "");

    input_done = 0;
    input_left = strlen(input);
    inp32b_count = 0;
    while (input_left > 0) {
        mbfuncerror = mbrtoc32(&inp32b[inp32b_count], input + input_done, input_left, NULL);
      if (mbfuncerror > input_left){
        printf("変換に失敗しました mbrtoc32()\n");
        printf("エラーコード%d\n", (int)mbfuncerror);
        return 1;
      }

      printf("%d\n",(int)mbfuncerror);
      input_done += mbfuncerror;
      input_left -= mbfuncerror;
      inp32b_count++;
    }

    for (i = 0; i < inp32b_count; i++) {
      mbfuncerror = c32rtomb(output, inp32b[i], NULL);
      if (mbfuncerror == (size_t)-1){
        printf("変換に失敗しました c32rtomb()\n");
        printf("エラーコード%d\n", (int)mbfuncerror);
        return 1;
      }

      output[mbfuncerror] = '\0';

      printf("%s", output);
    }
    putchar('\n');
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ぷぷぷジューシー
記事: 28
登録日時: 3年前
住所: アンドロメダ銀河系のどこかに住んでいる

Re: マルチバイトの変換後出力が一文字だけになってしまう

#4

投稿記事 by ぷぷぷジューシー » 3年前

Meta3 さんが書きました:
3年前
char output[MB_LEN_MAX + 1];
のMB_LEN_MAX がマルチバイト1文字を表すのに必要なバイト数(の最大値 =5)だからではないですか
Meta3 さん回答ありがとうございます。

<code>てことはchar output[MB_LEN_MAX * 5];</code>いいのかな?
みけCAT さんが書きました:
3年前
これらは「文字」を変換する関数であるため、1文字しか変換しません。
文字列全体を変換するには、最後まで1文字すつ変換するのがいいでしょう。
みけCA さん 回答ありがとうございます。
わざと配列にし、for などでなんやかんや実装した方がいいのか
面倒なことはCGo使おう!

返信

“C言語何でも質問掲示板” へ戻る