• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:全角数字、アルファベット大小を認識させたいのですが上手くいきません)

全角数字、アルファベット大小を認識する方法とは?

このQ&Aのポイント
  • 入力文字列が、全角数字なのか、全角アルファベットなのか、或いはそれ以外なのかを判断する方法がわかりません。
  • 現在の「testfunc」では、全角数字と全角アルファベットの大文字のみを判断することができますが、全角アルファベットの小文字を判断することができません。
  • 全角アルファベットの小文字も認識するための方法を教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

ロケールとかの問題じゃない。根本から間違ってる。 a = c[0]; って書いてあると、まず、c[0]はintに拡張され、それからunsignedに変換され、aに代入される。 もしc[0]に「a」の第1バイトが入っているなら、c[0]は「charで-126」になる。16進数では「0x82」になる。 そして、それがintに拡張され「intで-126」になる。intが32ビットなら、16進数では「0xFFFFFF82」になる。これは「0x00000082」ではない。 そして次に、それがunsignedに変換される。16進数で「0xFFFFFF82」なので10進数では「4294967170」になる。これも当然「0x00000082」ではない。 最終的にaに代入されるのは「4294967170」であって、質問者さんが期待する「0x82」が代入される事は永久にない。 bについても同様の事が起きる。 結果、c[0]、c[1]の値とa、bの値は、以下のようになる。 c[0]の値      aの値 0x00~0x7F ⇒ 0x00000000~0x0000007F 0x80~0xFF ⇒ 0xFFFFFF80~0xFFFFFFFF c[1]の値      bの値 0x00~0x7F ⇒ 0x00000000~0x0000007F 0x80~0xFF ⇒ 0xFFFFFF80~0xFFFFFFFF さて、全角の「0」~「9」が来た時、aとbはどうなるだろう。 c[0]は0x82、c[1]は0x4F~0x58なので c[0]の値      aの値 0x80~0xFF ⇒ 0xFFFFFF80~0xFFFFFFFF c[1]の値      bの値 0x00~0x7F ⇒ 0x00000000~0x0000007F の変換が行われ aの値=0xFFFFFF82(4294967170) bの値=0x0000004F~0x00000058 となる。 これは if ((a >= 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 の条件を満たすので return 2; を実行する。 たぶん、最初、質問者さんは if ((a == 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 と書いて、return 2が実行されないから if ((a >= 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 って書いたんだと思う。でも、それは「大きな間違い」で、本当は if ((a == 0xffffff82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 って書かなきゃいけなかった。 今のまま if ((a >= 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 って書いてると、全角0~9以外の文字であっても、第1バイトが0x82~0xffで、第2バイトが0x4f~0x58の範囲なら、全部「全角0~9」と判断される筈。例えば「グケゲコゴサザシジス」とか「ОПРСТУФХЦЧ」とかも「全角0~9」って判断する。 さて、次。全角の「A」~「Z」が来た時、aとbはどうなるだろう。 c[0]は0x82、c[1]は0x60~0x7aなので c[0]の値      aの値 0x80~0xFF ⇒ 0xFFFFFF80~0xFFFFFFFF c[1]の値      bの値 0x00~0x7F ⇒ 0x00000000~0x0000007F の変換が行われ aの値=0xFFFFFF82(4294967170) bの値=0x00000060~0x0000007A となる。 これは if ((a >= 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 の条件は満たさないが if ((a >= 0x82) && ((b >= 0x60) && (b <= 0x9a))){//全角A~z の条件を満たすので return 1; を実行する。 さて、問題の「a」~「z」が来た時、aとbはどうなるだろう。 c[0]は0x82、c[1]は0x81~0x9bなので c[0]の値      aの値 0x80~0xFF ⇒ 0xFFFFFF80~0xFFFFFFFF c[1]の値      bの値 0x80~0xFF ⇒ 0xFFFFFF80~0xFFFFFFFF の変換が行われ aの値=0xFFFFFF82(4294967170) bの値=0xFFFFFF81~0x0000009B(4294967169~4294967195) となる。 これは if ((a >= 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 の条件も if ((a >= 0x82) && ((b >= 0x60) && (b <= 0x9a))){//全角A~z の条件も、どちらも満たさないので、 return 0; を実行する。 はい、もう何が悪いか判りましたね? 質問者さんが「charの値を、何もしないでunsignedに放り込んだのが悪い」のです。 最低限、以下の3つは覚えておこう。 「charの最上位ビットが1の値、つまり、0x80~0xFFは負数である」 「charを計算式に書くと、一旦、intにされ、負数は符号拡張される」 「charの0x82と、intの0x82(というか、0x00000082)は等しくない」 関数を以下のように直せば、動く筈。 int testfunc (char *c) { unsigned a, b; a = (unsigned)(c[0]) & 0x000000FFU;//上位バイト b = (unsigned)(c[1]) & 0x000000FFU;//下位バイト /******ちゃんと動かないからって無理やり動くようにした「(a >= 0x82」は愚かな修正なので「a == 0x82」に戻しておくこと!!!******/ if ((a == 0x82) && ((b >= 0x4f) && (b <= 0x58))){//全角0~9 return 2; /******ちゃんと動かないからって無理やり動くようにした「(a >= 0x82」は愚かな修正なので「a == 0x82」に戻しておくこと!!!******/ } else if ((a == 0x82) && ((b >= 0x60) && (b <= 0x9a))){//全角A~z return 1; } else { return 0; } } キャストと型変換の基本が理解出来てないので、2年くらい修行し直すこと。 ロケールがどうとかって、根本原因を読み取れない回答者さんが多過ぎ。書いてあるコード見れば「S-JISを想定している」くらいの事は読み取れるだろ。ロケールをどうこう言う前にさ。 (現代の若者って、こういう「相手が何を言いたいか」を読み取る能力が完璧に欠如してると思うが、どうだろう?) こういう回答をする回答者さん達って、質問者さんと同様、基本が出来てないんだろうな。

trjun09
質問者

お礼

>「charの0x82と、intの0x82(というか、0x00000082)は等しくない」 なるほど大きな誤解をしていました。 >キャストと型変換の基本が理解出来てないので、2年くらい修行し直すこと。 そうですね。2年くらい修行し直します。 ありがとうございました。

その他の回答 (2)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

char型が符号付きか符号無しかが処理系定義であることは、C言語をまともに勉強したものであれば知っていて当然のことです。OSが何であるかは関係なく、コンパイラとコンパイルオプションに依存します。 また、char型がint型と同じサイズである可能性も(どんなに確率が低くても)処理系が特定されない限り否定しきれません。 # どこかの会社の内製コンパイラかもしれませんし、シミュレーション環境やその他のインタープリタの可能性も否定しきれませんので。 さらに、一見シフトJISのように見えても、Big5のような類似のコードを使っている文字コードや特定の会社の内製文字コードの可能性も否定しきれませんし、TRONコードのようなものかもしれません。これらを決めうちにしているのか、ロケールに依存させるつもりなのかも、この関数を見ただけでは判断不能です。 勝手に決めつけるのは簡単ですが、正確な回答は正確な質問からしか(偶然を除いて)出てきません。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

環境やロケールに依存しない方法はありません。 環境およびロケールを明確にしてください。

trjun09
質問者

補足

情報が足りなかったようで申し訳ありません。 Windows XPで、ShiftJisの文字を認識させようとしています。

関連するQ&A