トップ回答者
Visual C++ 2010で、isspace関数を使うと、実行時エラーが発生します。

質問
-
こんにちは。
現在、Windows7で、Visual C++ 2010 Expressを使っています。Borland C++ CompilerなどのC++コンパイラを使って、
EXEプログラムをビルドしていた時は、
isspace関数は、ctype.hをインクルードすると使えていました。
ところが、isspace関数を使うプログラムを、Visual C++ 2010 Expressでビルドし、
[Ctrl]+[F5]とタイプして実行してみると、エラーが発生します。
その時に現れるウィンドウは、下記のURLの通りです。
https://skydrive.live.com/#cid=3B9CFAE284919667&id=3B9CFAE284919667%2115561
どうやら、
(unsigned)(c + 1) <= 256)
は、isctype.cというファイルの56行目の
_ASSERTE((unsigned)(c + 1) <= 256);
という行の事を指しているようなのですが、
_ASSERTE が何者なのかが分かりませんでした。以上の件について何かご存知の方がいらっしゃれば、是非教えて頂きたいと思います。
では、よろしくお願い致します。
回答
-
問題は解決したようですが、根本の原因を理解できていないように思います。
Visual C++の文字の型としてはchar、wchar_t、TCHARの3種類があります。C++ の文字セットとその中のTchar.h における汎用テキストのマッピング辺りを読み理解することをお勧めします。
isspace()は過去との互換性のため引数がchar型ではなくint型になっており、またchar→int、wchar_t→int、TCHAR→intいずれも暗黙の型変換が可能なため、間違った文字型を渡してもコンパイラーが警告を出すことができません。そのために実行時エラーとなります。
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
char 型(0 - 255)の範囲外の値を渡していないか確認してください。
(あとは、wchar_t バージョン(iswspace) と使い分けあたりかな)- 編集済み AzuleanMVP, Moderator 2012年11月24日 10:32
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
使い方の誤りです。
http://msdn.microsoft.com/ja-jp/library/y13z34da%28v=vs.100%29.aspx
CRT デバッグ ライブラリを使用すると、isspace は EOF ではないパラメーターまたは 0 ~ 0xFF の範囲にないパラメーターを渡された場合に CRT アサートを表示します。CRT デバッグ ライブラリ以外で使用する場合、isspace はパラメーターを配列のインデックスとして使用し、パラメーターが EOF ではない場合、または 0 ~ 0xFF の範囲にない場合に未定義の結果を返します。
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
isspace関数には、char型変数しか渡していないので、
char型の罠にはまっている気がします。
以下のようなコードを書いていませんか?
#include <cctype> int main() { char c = 0x80; std::isspace(c); }
isspace()関数はEOFを受けられるようにint型を引数に取ります。
また、Visual C++のchar型は符号付きです。
従って、char型の値を渡そうとすると、int型へ拡張されて0xffffff80~0x0000007fへと変換されます。
このため、「_ASSERTE((unsigned)(c + 1) <= 256)」に引っかかることになります。
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
先に挙げたページをよく読んでください。
プログラムで扱っている文字・文字列で使用されているエンコーディング・文字コードは何ですか? 文字コードが違えば判定式も異なり、当然ながらそれは使用する関数も異なります。
- TCHAR向けの_istspace()
- マルチバイト文字を含まないchar向けのisspace()
- マルチバイト文字を含むchar向けの_ismbcspace()
- UNICODEを格納するwchar_t向けのiswspace()
の4つが挙げられています。isspace()を使うなら全角文字を含んでいてはいけません。
-
文字コードがUnicodeではないのに、iswspace関数が使えたのはどうしてなのかわからないですが、
マルチバイト文字の1バイトを格納するchar型変数に対しては、iswspace関数を使えばよいようです。
「偶然」使えたにすぎませんので、文字のエンコーディングがわかっている場合は、そのエンコーディングに対応した関数を使用すべきです。そうしないと、また原因不明なエラーの元になります。
> マルチバイト文字の1バイトを格納するchar型変数に対しては、iswspace関数を使えばよいようです。
この部分に関してchar型を使用しているのであれば、佐祐理さんが上で例に挙げているように
マルチバイト文字を含むchar向けの_ismbcspace()
を使用すべきで、
UNICODEを格納するwchar_t向けのiswspace()
は使用すべきではありません。
すべての返信
-
char 型(0 - 255)の範囲外の値を渡していないか確認してください。
(あとは、wchar_t バージョン(iswspace) と使い分けあたりかな)- 編集済み AzuleanMVP, Moderator 2012年11月24日 10:32
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
使い方の誤りです。
http://msdn.microsoft.com/ja-jp/library/y13z34da%28v=vs.100%29.aspx
CRT デバッグ ライブラリを使用すると、isspace は EOF ではないパラメーターまたは 0 ~ 0xFF の範囲にないパラメーターを渡された場合に CRT アサートを表示します。CRT デバッグ ライブラリ以外で使用する場合、isspace はパラメーターを配列のインデックスとして使用し、パラメーターが EOF ではない場合、または 0 ~ 0xFF の範囲にない場合に未定義の結果を返します。
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
御回答ありがとうございます。
isspace関数には、char型変数しか渡していないので、
「EOF ではないパラメーターまたは 0 ~ 0xFF の範囲にないパラメーター」
は、渡していないはずなのですが、なぜか「CRT アサート」が表示されているようです。
どうしてもエラーが取り除けないので、以下のような関数で代用しておきました。bool my_isspace(char ch){
if(ch==' ' || ch=='\n' || ch=='\r' || ch=='\t' || ch=='\v'){
return true;
}
else{
return false;
}
} -
問題は解決したようですが、根本の原因を理解できていないように思います。
Visual C++の文字の型としてはchar、wchar_t、TCHARの3種類があります。C++ の文字セットとその中のTchar.h における汎用テキストのマッピング辺りを読み理解することをお勧めします。
isspace()は過去との互換性のため引数がchar型ではなくint型になっており、またchar→int、wchar_t→int、TCHAR→intいずれも暗黙の型変換が可能なため、間違った文字型を渡してもコンパイラーが警告を出すことができません。そのために実行時エラーとなります。
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
isspace関数には、char型変数しか渡していないので、
char型の罠にはまっている気がします。
以下のようなコードを書いていませんか?
#include <cctype> int main() { char c = 0x80; std::isspace(c); }
isspace()関数はEOFを受けられるようにint型を引数に取ります。
また、Visual C++のchar型は符号付きです。
従って、char型の値を渡そうとすると、int型へ拡張されて0xffffff80~0x0000007fへと変換されます。
このため、「_ASSERTE((unsigned)(c + 1) <= 256)」に引っかかることになります。
- 回答としてマーク 佐伯玲 2012年12月4日 4:36
-
Visual C++の文字の型としてはchar、wchar_t、TCHARの3種類があります。C++ の文字セットとその中のTchar.h における汎用テキストのマッピング辺りを読み理解することをお勧めします。
原因が分かりました。
全角文字の1バイト目を読み込むときに、isspace関数に渡す値が
「-126」となっていて、これが原因で、
「_ASSERTE((unsigned)(c + 1) <= 256)」
に引っかかったようです。
isspace関数の代わりに、iswspace関数を使うと、
エラーが出なくなったことから考えると、
全角文字の一部を、変数に格納する事がある場合は、
char型ではなくて、whar_t型の変数を使わなくてはならないという事なのでしょうか?
- 編集済み kei-k0625 2012年11月25日 20:36
-
先に挙げたページをよく読んでください。
プログラムで扱っている文字・文字列で使用されているエンコーディング・文字コードは何ですか? 文字コードが違えば判定式も異なり、当然ながらそれは使用する関数も異なります。
- TCHAR向けの_istspace()
- マルチバイト文字を含まないchar向けのisspace()
- マルチバイト文字を含むchar向けの_ismbcspace()
- UNICODEを格納するwchar_t向けのiswspace()
の4つが挙げられています。isspace()を使うなら全角文字を含んでいてはいけません。
-
文字コードがUnicodeではないのに、iswspace関数が使えたのはどうしてなのかわからないですが、
マルチバイト文字の1バイトを格納するchar型変数に対しては、iswspace関数を使えばよいようです。
「偶然」使えたにすぎませんので、文字のエンコーディングがわかっている場合は、そのエンコーディングに対応した関数を使用すべきです。そうしないと、また原因不明なエラーの元になります。
> マルチバイト文字の1バイトを格納するchar型変数に対しては、iswspace関数を使えばよいようです。
この部分に関してchar型を使用しているのであれば、佐祐理さんが上で例に挙げているように
マルチバイト文字を含むchar向けの_ismbcspace()
を使用すべきで、
UNICODEを格納するwchar_t向けのiswspace()
は使用すべきではありません。
-
こんにちは、kei-k0625 さん
フォーラムオペレータの佐伯 玲 です。その後の状況はいかがでしょうか?
さて、MSDN フォーラムではご質問が解決した際にそれに至る情報に「回答としてマーク」して頂くようにお願いさせていただいております。
マークが付くことによりそのご質問が解決してスレッドとして区切りがついたことやタイトルの問いに対する答えがスレッドに存在していることを表します。フォーラムでは質問が解決した後もタイトルを見て同じように疑問を持たれた方等がその後は質問をせずとも回答がついているスレッドを見れば参考に出来るようにすることも目的としています。
また、kei-k0625 さんの最後のご返信後にもCatTail さんから追加の情報も寄せられているのでご確認の上、解決に至った場合には過去の情報を含め「回答としてマーク」をお願いいたします。
「回答としてマーク」はスレッド内で複数の返信につける事が可能です。今回は一旦私のほうで参考になると思われる情報に「回答としてマーク」をさせていただきました。
宜しくお願い致します。
__________________________
日本マイクロソフト株式会社 フォーラム オペレータ 佐伯 玲- 編集済み 佐伯玲 2012年12月4日 4:35