![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
現在C言語を勉強しております。
そこで、キーボードから入力された文字列のチェックを行う関数を作成したいのですが、実装方法が分かりません・・・。
以下に仕様と私の作成したソースを貼ります。
【許可する文字】は、
全角のひらがな
全角の英語(大文字も小文字もOK)
全角の数字
です。
チェックする関数を作成したいのですが、以下ではうまくいかず・・・
教えてくださいorz
比較の仕方がおかしいのかな・・・とは思っているんですが。
関数は、引数として渡された文字列に許可以外の文字が含まれている場合は1を、そうでなければ0を返す、という仕様にしたいです。
int checkName(char *str)
{
int i;
for(i = 0; str[i] != '\n'; i++){
/* 奇数バイトをチェック */
if(str[i] != 0x82){
return 1;
}else{
i++;
/* ひらがな以外の場合 */
if(str[i] < 0xa0 && str[i] > 0xf1)
/* 英語(大文字)以外の場合 */
if(str[i] < 0x60 && str[i] > 0x79)
/* 英語(小文字)以外の場合 */
if(str[i] < 0x81 && str[i] > 0x9a)
/* 数字の場合 */
if(str[i] < 0x50 && str[i] > 0x58)
/* 許可する文字に該当しなかった場合は1を返す */
return 1;
}
}
return 0;
}
上記ソースの「(str[i] != 0x82)」は比較の仕方としておかしいでしょうか?
以上、よろしくお願いいたします。
No.5ベストアンサー
- 回答日時:
読み直してみたら、かなり意味不明な文章だったかも。
No4と合わせて、長々とした文章で申し訳ありません。
コメント頂ける場合は、No4かNo5のどちらか、より参考になった方にだけ書いて下されば結構ですので。
No4を要約すると0x82がunsigned intだったと仮定した時、解決方法は3通りあるという事です。
1:if(str[i] != 0xffffff82)
とても強引な解決策です。これ10進で表すと-126ではなく、4294967170と比較するという意味になります。
そしてchar型の0x82をunsigned intすると、4294967170になると言う事でもあります。
(C言語の規格に疎いので断定は出来ないのですけど、ya-chaさんの環境でも同じ値になると思われます)
2:if((unsigned char)str[i] != 0x82)
ya-chaさんの解法です。
3通りの中で一番スマートな解法です。
仮にstr[i]をunsigned intにキャストしても、0x00000082→0x82ですから、結果として希望通りの動作になります。
文字コードにマイナスは必要ないわけですから、unsignedにするのが無難というか、常識な様な気がしますね。
(私もそこら辺を意識した事はないのですけど)
3:if(str[i]) != (char)0x82)
これでも正常に動作します。この場合0x82は-126です。
解法2の場合、変数をunsigned charで宣言すればキャストの必要はありません。
しかし、この解法はchar型の変数と比較する事を前提にしてますので、(char)0x82は必須です。
ですので、可読性だけでなく処理速度面でみても解法2に劣ります。
何度も丁寧にご解説いただきありがとうございます。
お礼も遅くなりまして申し訳ございません。
引数をunsigned charにすることで解決出来、動作も確認済みです。
本当にありがとうございました。
No.4
- 回答日時:
言葉が足りない上に余計なお節介までしてしまいました。
もう本当すいません、いろいろと。
>ちなみに私の環境だと、str[0]はffffff82と表示されました。
後述とはこれの事です。
それと今気づいたんですけど、
>if(str[i] != 0x82)
この0x82って、少なくとも符号なしですよね。
と言う事は、10進で表すとこうなります。(str[i]=0x82)
if(-126 != 130){}
そして私の環境の場合0x82はunsigned intと予想され、str[i]は暗黙的にunsigned intにキャストされます。
つまり、str[i]はこう変換されるはずです。
0x82 → 0xffffff82(-126なのでfで埋める)
というわけで、どちらにしろ思い通りに動作しないという事になりそうですね。
逆に考えると、こうやっても良いはずです。
if(str[i] != (char)0x82){} ←0x82じゃなくてstr[i]の方に合わせなさい
No.3
- 回答日時:
if(str[i] != 0xffffff82)と書く事で、マッチする可能性があります。
理由は後述します。
そこまで原因が絞れていれば、printfを書けば確認出来ますよ。
for(i = 0; str[i] != '\n'; i++){
printf("%x\n",str[i]); ←ここにprintfを挟む
/* 奇数バイトをチェック */
if(str[i] != 0x82){
ちなみに私の環境だと、str[0]はffffff82と表示されました。
if(str[0] == 0x82)と試しみると、やっぱりマッチしません。
if(str[0] == 0xffffff82)でマッチしました。
ところで話は変わりますが。
Cで文字列を扱うのは、かなり現実的ではないと思います。
一度C#かjavaを経験されてみると、Cがどれだけ面倒くさくて分かりづらい事か分かると思います。
極力Cで記述したいのでしたら、私の場合は文字列の処理のみC++で組みますね。
参考URL:http://programmer-toy-box.sblo.jp/article/163816 …
ご回答ありがとうございます。
charをunsignedに変更して比較することで解決出来ました。
(よく理由はわかってないですが・・・orz)
javaは経験あります。
C言語がとても面倒なのはすごく分かっておりますが、勉強なので・・・。
丁寧にソースを含めての説明本当にありがとうございました。
もし可能でしたら、
>理由は後述します。
の理由を教えていただけないでしょうか?
しばらく質問は締め切らずに置いておくので・・・
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_04.png?e8efa67)
No.1
- 回答日時:
比較はあってるんじゃないですかね?
やってみていないので、そちらでprintfしてみて出れば正しいと思います。
しかしelseの中のif文が何かおかしい気がします。
ifで条件分岐しているのにもかかわらずその後の処理が書かれていないのでは?
たしか{}でくくられていなければ次の一文が実行されるはずですが、その知識が正しければ次々と条件に一致するとそれぞれの下のif文を繰り返して、全ての条件をクリアすればreturn 1になるはずです。(違ったらすいません)
ですがstr[i]の値的に同時に全ての条件を満たすことはないと思われます。
簡単な方法はそれぞれのif文の後にreturn 1;を書いてあげることですかね。
プログラムとしてどうかと思いますが・・・
回答にならなくてすいません。
デバッグしてみたら、「(str[i] != 0x82)」が一致しないんです・・・。
if文についての指摘は回答者様の言われるとおりですね・・・orz
まだまだ初心者なもので失礼いたしました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・「I love you」 をかっこよく翻訳してみてください
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・昔のあなたへのアドバイス
- ・かっこよく答えてください!!
- ・あなたが好きな本屋さんを教えてください
- ・スタッフと宿泊客が全員斜め上を行くホテルのレビュー
- ・【大喜利】【投稿~8/27】 こんなガソリンスタンド二度と来るか!なぜそう思った?
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・【お題】動物のキャッチフレーズ
- ・【お題】甲子園での思い出の残し方
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・「それ、メッセージ花火でわざわざ伝えること?」
- ・自分用のお土産
- ・人生で一番お金がなかったとき
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・ちょっと先の未来クイズ第1問
- ・ゴリラ向け動画サイト「ウホウホ動画」にありがちなこと
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
sscanfとscanfの違いがよくわか...
-
CStringのFindで文字列検索を行...
-
C言語 空白の行(改行のみ)が...
-
itoaわかりません
-
ある文字列で2回目3回目に出現...
-
C言語のステップ数をカウントす...
-
aから始まりzzzzで終わるために...
-
ブランクのチェック
-
文字列の途中に「0」がある場...
-
エディットボックスに入力され...
-
2進数から10進数へ変換プログラム
-
C言語で16進数文字列から16進数...
-
charと%c , %s の関係について
-
fgets関数を使用したときの文字...
-
大文字の文字列→小文字の文字列
-
全角文字のチェック
-
小文字のみを数える方法
-
putsとputcharの違い?
-
2÷3などの余りについて
-
DWORDの実際の型は何でしょうか
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringのFindで文字列検索を行...
-
sscanfとscanfの違いがよくわか...
-
fgets関数を使用したときの文字...
-
charと%c , %s の関係について
-
反転した数値を表示させるやり方
-
strstrを利用しない文字列検索...
-
C言語 空白の行(改行のみ)が...
-
C言語、単語ごとに改行したい
-
itoaわかりません
-
C言語のステップ数をカウントす...
-
fgetsで拾われる改行文字を削除...
-
C言語で16進数文字列から16進数...
-
Cで「大文字、小文字の判定」は...
-
CStringについて
-
C言語の課題です
-
文字列中に含まれる文字の個数...
-
単語数のカウントについて
-
文の意味
-
fgetsでバッファ残留文字列を無...
-
putsとputcharの違い?
おすすめ情報