ページ 1 / 1
mbtowcが-1を返し続ける
Posted: 2011年11月20日(日) 02:17
by ISLe
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
と出力されます。
Re: mbtowcが-1を返し続ける
Posted: 2011年11月20日(日) 07:38
by beatle
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
Re: mbtowcが-1を返し続ける
Posted: 2011年11月20日(日) 07:45
by beatle
なんでこんな、状態を保存する仕様なのか考えました。恐らく、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
Re: mbtowcが-1を返し続ける
Posted: 2011年11月20日(日) 17:47
by ISLe
ありがとうございます。
そんな仕様になってたのですね。
「mbtowc() 関数のみが使用するシフト状態」というのは、(Shiftではない)JISコードの漢字IN/漢字OUTのようなものを想定しているのではないでしょうかね。
UTF-8はシフト状態に依存しないコードなのでこのように振る舞うのは不可思議に感じますね。
mbtowc(NULL, NULL, 0)はゼロ(シフト状態に依存しない)を返しますし。
本当にリードバイトなのかどうか判断できないような、と思ったのですが、考えてみたらどちらにしても正常な文字列を食わせないと正常に機能しないのでした。
となるとあとはCygwinと挙動が異なるのが問題ですが…
シフト状態に依存する文字コードに対応する予定はないので、毎度リセットで統一することにします。