iswprint, iswglyph で「♪」や「√」が 0 になる

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
wchar_t

iswprint, iswglyph で「♪」や「√」が 0 になる

#1

投稿記事 by wchar_t » 5年前

Win10 MSVC2017を使っています。ワイド文字の判定で困っているのですが、
iswprint で音符記号「♪」やルート記号「√」などが false と判定されてしまいます。
では iswglyph なのかとも思いましたが、これでも false 判定されます。
♪にしろ√にしろ、文字としての形を持っているので iswprint や iswglyph は true になるものと期待していたのですが…
「コントロール文字ではなく、空白でもない」という意味で
!iswcntrl(x) && !iswspace(x)
で判断するしかないのでしょうか?

コード:

#include <iostream>
int main()
{
	std::cout << iswprint(L'♪') << " " << iswgraph(L'♪') << std::endl; // 「おんぷ」
	std::cout << iswprint(L'√') << " " << iswgraph(L'√') << std::endl; // 「るーと」
	// ここで
	// 1 1
	// 1 1
	// と出力されることを期待しているが、
	// 0 0
	// 0 0
	// になってしまう
	return 0;
}

wchar_t

Re: iswprint, iswglyph で「♪」や「√」が 0 になる

#2

投稿記事 by wchar_t » 5年前

すみません、補足説明です。何を判定したいかというと、
「文字としての形を持っているかです」
例えば紙に印刷したときに、1ドットでもインクを使うなら True である という認識です。
例外は半角or全角スペースのみです

アバター
あたっしゅ
記事: 663
登録日時: 13年前
住所: 東京23区
連絡を取る:

Re: iswprint, iswglyph で「♪」や「√」が 0 になる

#3

投稿記事 by あたっしゅ » 5年前

https://msdn.microsoft.com/ja-jp/librar ... 2147217396
isprint、iswprint - MSDN(ja)

isprint、iswprint が有効なのは「 0 ~ 0xFF の範囲」、ということが、書いてある気がする。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

wchar_t

Re: iswprint, iswglyph で「♪」や「√」が 0 になる

#4

投稿記事 by wchar_t » 5年前

なるほど、よく見ると確かに書いてありますね。

iswspace だと全角スペースとかも判別してくれますから、
当然 iswprint や iswgraph も同様にascii 範囲外の文字についても判別してくれるものと
思い込んでいました。

ありがとうございました。

かずま

Re: iswprint, iswglyph で「♪」や「√」が 0 になる

#5

投稿記事 by かずま » 5年前

Ubuntu 16.04.6 LTS, g++ 5.4.0 では、次のように書くと期待通り
すべての結果が 1 になります。

コード:

#include <iostream>

int main()
{
	std::setlocale(LC_CTYPE, "");
	std::cout << iswprint(L'♪') << " " << iswgraph(L'♪') << std::endl;
	std::cout << iswprint(L'√') << " " << iswgraph(L'√') << std::endl;
	return 0;
}
ただし、setlocale を削除するか、あるいはそれと同等の
setlocale(LC_CTYPE, "C"); にすると、結果はすべて 0 になります。

Windows では、isw~ が期待通りに動かないようなので、
次のように GetStringTypeW を使って、isW~ を作ればよいでしょう。

コード:

#include <windows.h>
#include <iostream>

int isWprint(wchar_t wc)
{
	WORD t;
	GetStringTypeW(CT_CTYPE1, &wc, 1, &t);
	return (t & C1_DEFINED) && !(t & C1_CNTRL);
}

int isWgraph(wchar_t wc)
{
	WORD t;
	GetStringTypeW(CT_CTYPE1, &wc, 1, &t);
	return (t & C1_DEFINED) && !(t & C1_CNTRL) && !(t & C1_SPACE);
}

int main()
{
	std::cout << isWprint(L'♪') << " " << isWgraph(L'♪') << std::endl;
	std::cout << isWprint(L'√') << " " << isWgraph(L'√') << std::endl;
	return 0;
}
GetStringTypeW の機能を調べるために次のようなプログラムを
書いてみました。

コード:

#include <windows.h> // GetStringTypeW
#include <stdio.h>   // printf
#include <locale.h>  // setlocale

void show(wchar_t wc)
{
	static char *s[] = {
		"upper", "lower", "digit", "space", "punct",
		"cntrl", "blank", "xdigit", "alpha", "defined"
	};
	WORD t;
	GetStringTypeW(CT_CTYPE1, &wc, 1, &t);
	printf("  %04x '%lc' %02x [", wc, wc, t);
	for (int i = 10; --i >= 0; )
		if (t & 1<<i) printf(" %s", s[i]);
	printf(" ]\n");
}

int main(void)
{
	setlocale(LC_CTYPE, "");

	show(L'\0');
	show(L'A'); show(L'z'); show(L'9'); show(L' '); show(L':');
	show(L'\a'); show(L'\t');
	show(L'♪'); show(L'√'); show(L' '); show(L'ぁ'-1);
	show(L'A'); show(L'z'); show(L'9'); show(L';');
}
GetStringTypeW は locale には影響されませんが、
printf で "%lc" を使うために setlocale を呼び出しています。

実行結果

コード:

  0000 ' ' 220 [ defined cntrl ]
  0041 'A' 381 [ defined alpha xdigit upper ]
  007a 'z' 302 [ defined alpha lower ]
  0039 '9' 284 [ defined xdigit digit ]
  0020 ' ' 248 [ defined blank space ]
  003a ':' 210 [ defined punct ]
  0007 '' 220 [ defined cntrl ]
  0009 '        ' 268 [ defined blank cntrl space ]
  266a '♪' 200 [ defined ]
  221a '√' 200 [ defined ]
  3000 ' ' 248 [ defined blank space ]
  3040 '' 00 [ ]
  ff21 'A' 381 [ defined alpha xdigit upper ]
  ff5a 'z' 302 [ defined alpha lower ]
  ff19 '9' 284 [ defined xdigit digit ]
  ff1b ';' 210 [ defined punct ]

wchar_t

Re: iswprint, iswglyph で「♪」や「√」が 0 になる

#6

投稿記事 by wchar_t » 5年前

GetStringTypeW という関数は知りませんでした。
これを使えば期待していたことができますね。
サンプルプログラムまでつけていただいて
どうもありがとうございました!

返信

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