mbtowcが-1を返し続ける

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

mbtowcが-1を返し続ける

#1

投稿記事 by ISLe » 14年前

Ubuntu 11.10のgcc 4.6.1でのことです。
mbtowcが-1を返すと以後ずっと-1を返すのです。
何か内部状態をクリアする方法が用意されているのでしょうか。
バグっぽいですけど。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
int main(void)
{
	char mb[3];
	setlocale(LC_CTYPE, "");
	/* UTF-8で'あ' */
	mb[0] = 0xe3;
	mb[1] = 0x81;
	mb[2] = 0x82;
	puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
	puts(mbtowc(NULL, mb, 2) > 0 ? "OK" : "NG");
	puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
	return 0;
}
Ubuntu 11.10のgcc 4.6.1では
OK
NG
NG
と出力されました。
Cygwinのgcc 4.5.3では
OK
NG
OK
と出力されます。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: mbtowcが-1を返し続ける

#2

投稿記事 by beatle » 14年前

Ubuntu 11.04 gcc 4.6.1 で同じ結果になりました。
mbtowcの第2引数(const char *)をNULLにして呼び出すと、「mbtowc() 関数のみが使用するシフト状態は初期状態に 戻される」そうです。
参考:http://linuxjm.sourceforge.jp/html/LDP_ ... owc.3.html

コード:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
int main(void)
{
    char mb[3];
    setlocale(LC_CTYPE, "");
    /* UTF-8で'あ' */
    mb[0] = 0xe3;
    mb[1] = 0x81;
    mb[2] = 0x82;
    puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
    puts(mbtowc(NULL, mb, 2) > 0 ? "OK" : "NG");
    puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
    mbtowc(NULL, NULL, 0);
    puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
    return 0;
}
結果
OK
NG
NG
OK

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: mbtowcが-1を返し続ける

#3

投稿記事 by beatle » 14年前

なんでこんな、状態を保存する仕様なのか考えました。恐らく、2回目以降の呼び出しに、続きの文字列を指定できるようにしているのでしょう。
例えばfgetsを使う場合、行の最後まで読み取れない場合がありますが、そのような場合も、続くfgetsの呼び出しで残った文字列を取得し、
そのままmbtowcに渡せば正しい結果になりますね。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
int main(void)
{
    char mb[3];
    setlocale(LC_CTYPE, "");
    /* UTF-8で'あ' */
    mb[0] = 0xe3;
    mb[1] = 0x81;
    mb[2] = 0x82;
    puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
    puts(mbtowc(NULL, mb, 2) > 0 ? "OK" : "NG");
    puts(mbtowc(NULL, mb + 2, 1) > 0 ? "OK" : "NG");
    puts(mbtowc(NULL, mb, 3) > 0 ? "OK" : "NG");
    return 0;
}
結果
OK
NG
OK
OK

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: mbtowcが-1を返し続ける

#4

投稿記事 by ISLe » 14年前

ありがとうございます。
そんな仕様になってたのですね。


「mbtowc() 関数のみが使用するシフト状態」というのは、(Shiftではない)JISコードの漢字IN/漢字OUTのようなものを想定しているのではないでしょうかね。
UTF-8はシフト状態に依存しないコードなのでこのように振る舞うのは不可思議に感じますね。
mbtowc(NULL, NULL, 0)はゼロ(シフト状態に依存しない)を返しますし。

本当にリードバイトなのかどうか判断できないような、と思ったのですが、考えてみたらどちらにしても正常な文字列を食わせないと正常に機能しないのでした。

となるとあとはCygwinと挙動が異なるのが問題ですが…
シフト状態に依存する文字コードに対応する予定はないので、毎度リセットで統一することにします。

閉鎖

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