
現在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言語がとても面倒なのはすごく分かっておりますが、勉強なので・・・。
丁寧にソースを含めての説明本当にありがとうございました。
もし可能でしたら、
>理由は後述します。
の理由を教えていただけないでしょうか?
しばらく質問は締め切らずに置いておくので・・・

No.1
- 回答日時:
比較はあってるんじゃないですかね?
やってみていないので、そちらでprintfしてみて出れば正しいと思います。
しかしelseの中のif文が何かおかしい気がします。
ifで条件分岐しているのにもかかわらずその後の処理が書かれていないのでは?
たしか{}でくくられていなければ次の一文が実行されるはずですが、その知識が正しければ次々と条件に一致するとそれぞれの下のif文を繰り返して、全ての条件をクリアすればreturn 1になるはずです。(違ったらすいません)
ですがstr[i]の値的に同時に全ての条件を満たすことはないと思われます。
簡単な方法はそれぞれのif文の後にreturn 1;を書いてあげることですかね。
プログラムとしてどうかと思いますが・・・
回答にならなくてすいません。
デバッグしてみたら、「(str[i] != 0x82)」が一致しないんです・・・。
if文についての指摘は回答者様の言われるとおりですね・・・orz
まだまだ初心者なもので失礼いたしました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C# 浮動小数の数値文字列化 1 2022/04/18 15:15
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
”123456”といった整数を文字列...
-
C言語について
-
プログラミング 文字入力のエラ...
-
C言語のステップ数をカウントす...
-
sscanfとscanfの違いがよくわか...
-
VBで全角文字の上位コードを...
-
C言語の初心者です。これを実行...
-
至急お願いします
-
cプログラミングについて
-
C言語 空白の行(改行のみ)が...
-
C言語 strlen 再入力を促す
-
文字列から数字への変換
-
Cプログラムでの標準入力から...
-
switchの使い方を教えてください。
-
文字列の問題
-
プログラムのことで
-
文字列を特定の全角文字で区切...
-
メニューバーでクリックした個...
-
C++でランレングス符号化のプロ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringのFindで文字列検索を行...
-
fgetsで拾われる改行文字を削除...
-
sscanfとscanfの違いがよくわか...
-
反転した数値を表示させるやり方
-
charと%c , %s の関係について
-
fgets関数を使用したときの文字...
-
Cで「大文字、小文字の判定」は...
-
strstrを利用しない文字列検索...
-
文字列中に含まれる文字の個数...
-
C言語のステップ数をカウントす...
-
itoaわかりません
-
C++
-
C/C++言語で日本語処理
-
C言語 空白の行(改行のみ)が...
-
CStringについて
-
小文字のみを数える方法
-
教えていただけませんか?C言語...
-
ブランクのチェック
-
str[j++]の意味
-
初歩的なプログラムなんですが...
おすすめ情報