アプリ版:「スタンプのみでお礼する」機能のリリースについて

質問は2つあります。
(1)
scanf関数を使って、
時給:
と表示されたところに一文字打ち込み、数字以外ならばもう一度
時給:
と表示されるプログラムを作りたいです。
以下のプログラムなら、
isdigit関数は数字を渡せば0以外の数を返す(真)から、
while文の条件式(偽)のようにすれば、

・数字を一文字うちこめばwhile文の条件式にあてはまらない、すなわち下のプログラムではisdigit(payment) != 0
となり、return 0;
が実行され、プログラムが終わる

・数字以外を一文字打ち込めばwhile文の条件式が真となり、printf関数とscanf関数が実行されて入力待ち状態になる

と思ったのですが、どうやら違うようです。実際には
・数字一文字打てばまた入力待ちになる
・数字以外を一文字打てば永遠にprintf関数とscanf関数が実行される
のはなぜでしょうか。

#include <stdio.h>
#include <ctype.h>

int main(void){

int payment;

do{
printf("時給[円]:");
scanf("%d",&payment);
} while (isdigit(payment) ==0) ;

return 0;

}

(2)
実際には、一文字の制限なく、数字以外の何かを入力したら、再び入力待ちになるプログラムを作りたいのですが、これはどうしたらいいのでしょうか。
つまり
時給:
のところに数字以外ならまた
時給:
となるようにしたいのです。お願いします。

A 回答 (4件)

(2) はとりあえず条件をはっきりさせるところからスタートだね. 例えば


・「20x」という入力に対してどうする?
・「20 x」という入力に対してはどうする?
・「-3.6」は?
とか, 悩みだすと難しい.
    • good
    • 0

>実際には、一文字の制限なく、数字以外の何かを入力したら、再び入力待ちになるプログラムを作りたいのですが、これはどうしたらいいのでしょうか。



こっち回答していませんでしたな。
まぁ、やることは同じなんですが。

char Input[20];
int i, loopend;

do
{
 printf("時給:");
 scanf("%s", Input);
 loopend = 1;
 for(i = 0;Input[i] != '\0';i++)
 {
  if(isdigit(Input[i]) == 0)
   loopend = 0;
 }
} while(loopend == 0);


みたいな。
# scanf()がエラーになっていないかの確認をした方がよかったり、バッファオーバーランしないように対策が必要だったり…と他にもありますけどね。
    • good
    • 0

>・数字一文字打てばまた入力待ちになる



既に回答されているように「数値」として処理される為、「数字」ではないのでisdigit()が偽を返します。
ので、ループ抜けられません。

>・数字以外を一文字打てば永遠にprintf関数とscanf関数が実行される

数字ではなかったので、scanf()が数値に変換不可能でエラーを返します。
その際、標準入力には「数字以外」が残ったままになります。
で、paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。
  :
paymentの値は変わらないのでisdigit()が偽を返しループ継続します。
ループでもう一度scanf()がコールされたので標準入力のバッファの先頭にある文字を読み込んで数値変換を試みようとします。
が、やはり数字ではないのでそのままバッファに残してエラーを返却します。

Ctrl+Cなどで停止させるまで、愚直に繰り返します。


こういう場合、"%d"でうけるのではなく、"%s"で文字列として受け取って、その後で変換可能か処理する。
というのが一般的でしょう。
    • good
    • 0

>scanf("%d",&payment);



この場合、paymentには文字ではなく数値が入ってます。
"%d"の意味とscanfの戻り値について調べ直しましょう。

例えば標準入力から 9 を入力した場合、

payment = 9;

をしたのと同じです。
isdigit()などで検査できるのは文字ですので

payment = '9';

の状態でないと検査できません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!