• 締切済み

do while文の条件

do while文の条件にprintfを使う場合、これはありなんでしょうか? 内容:0が入力されていたら、whileのprintfを実行してからdoに戻る。0以外ならprintfを実行しないで処理を抜ける。 int i; do { printf("0以外の数字を入力してください。\n"); scanf("%d",&i); }while(i == 0 && printf("まじめに入力してください。\n"));

みんなの回答

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

whileの式でメッセージ出力等を行わせるのであれば、次のような方法もあります。これならそんなに違和感はないかと思います。 int check(int condition) {  if (condition)   printf("まじめに入力してください。\n");  return condition; } int main(void) {  int i;  ...  do  {   printf("0以外の数字を入力してください。\n");   scanf("%d", &i);  } while(check(i == 0));  ... } やろうとしていることは結局同じですが、printfの返却値を条件判断に使っていないので、十分使い物になるかと思います。(しかも、エラー検出時の処理を変更するのも簡単です) このように1回関数を介せば、whileの条件式に副作用を持たせても問題ないと思います。

noname#16765
質問者

お礼

確かに関数に分けたら見た目的には問題なさそうですね。 ですがやっぱし変な思いつき(条件にprintfをいれる)は実行しないほうがいいみたいですね。

すると、全ての回答が全文表示されます。
  • fruipa
  • ベストアンサー率38% (14/36)
回答No.6

「あり」か「なし」かは場合によります。 実験が目的の場合や、自分一人がメンテし一生他人に見せない場合ならありです。 でも、もしあなたが私の部下で、製品向けにこのコードを書いたら、間違いなく説教です。(笑) > do while文の条件にprintfを使う場合・・・ まず、このコードの場合、do whileの条件式の中に書かれてはいますが、 printfを条件の意味で使ってませんから!!

noname#16765
質問者

お礼

お返事ありがとうございます。 私もいろいろなことを考えていたらなんとなく思いついちゃっただけですから 「while文の条件ではないよな」とかも思ったりしたので、それがいけるのかも聞きたかったのです。 みなさんの返答は予想通りといったところでした。 もちろん100%使う気はありません。

すると、全ての回答が全文表示されます。
  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.5

非数字、0 0 0 123と空白で区切られた数字の問題から、fgets()を使い、sscan()で読み取ったほうがよいと思います。do-whileや、goto文より、この例の場合条件に適合したら、break分を使ったほうが素直な表現になるのではないでしょうか? #include <stdio.h> int main(void) { int i; char buf[BUFSIZ]; while(1) { printf("0以外の数字を入力してください。\n"); if(fgets(buf, BUFSIZ, stdin) != 0 && sscanf(buf, "%d",&i) == 1 && i != 0) break; printf("まじめに入力してください。\n"); } printf("i = %d\n", i); return(0); }

noname#16765
質問者

お礼

自分もあなたの回答が一番すっきりしてて合っていると思います。 しかし、私が聞きたかったことは「while文などに条件以外をいれることはやってもいいのか」などだったのです。 前もってそこを強調しといたほうがよかったですね。 あとどうでもいいことでしょうが、printfの返り値はなんの役に立つのでしょう? これ以外もう思いつきません・・・

すると、全ての回答が全文表示されます。
  • galluda
  • ベストアンサー率35% (440/1242)
回答No.4

がると申します。 do-whileを使うという条件に合致していないので恐縮ですが。 例えばこんなやり方もあります。 C++なので、もしC言語でやられているのであれば若干改変が必要になるかと思われますが。 ーー // 数字かどうか判定 bool is_digits(const string& s) { bool ret = true; int c; unsigned char *buf = (unsigned char *)s.c_str(); while( (c = buf[0]) != '\0') { // buf ++; if ((isdigit(c)) == 0) { if ( ('\r' != c)&&('\n' != c) ) { ret = false; break; } } } return ret; } int i; while(1) { // printf("0以外の数字を入力してください。\n"); // 入力処理 string s = XXX; // 入力文字列が数字かどうか判定 if (is_digits(s)) { // 文字列を数値に変換 i = atoi(s.c_str()); // 0以外(正常な入力)ならwhileループを抜ける if (0 != i) { break; } } // else // 入力がおかしいので再度入力を促す printf("まじめに入力してください。\n") } // この時点でiには有効な数値が入っている ーー こんな感じでしょうか。 ちなみに誰も指摘していないので一応。 まず、記述されていたコードだと「数字以外が入力された場合」に対応できていません。 このあたりは面倒でもちゃんと一度チェックを入れておいたほうがより安全かと思います。 とりあえず、大雑把ではありますがis_digitsという関数を別途付記してみました。 もう一つ。scanfはあまり使わないほうがよいです。どんな入力が来るかわからないものに対して使うには、ちょっと危険なので。 細かく考えるといろいろ問題もあるのですが、入力の文字数など制限できて比較的楽に取得できるのはfgetsです。 fgetsは、例えばこんな風に使います。 // まず、格納用バッファ領域を用意します。 unsigned char cwk[64]; // stdinから読み込みを行います(サイズに-1してるのはNULL文字分を考慮しているため) fgets(cwk, sizeof(cwk) - 1, stdin); // 変数sに代入します。 string s = cwk; fgetsの場合、文字列の最後に改行まで入ってしまうのですが。取り合えずatoiで潰せるので無視しています(丁寧に処理する場合、fgetsの直後に「文字列末尾の改行コードを取り除く」処理を加えてください)。 また、is_digits関数も、今回用に「改行コードを無視する」ロジックを追加しています。 大雑把ですが、なにか参考にでもなれば幸いです。

noname#16765
質問者

お礼

こういった書き方もあるんですね・・・ >>記述されていたコードだと「数字以外が入力された場合」に・・・ あっ・・・、間違えて「数字を入力」になってる! うわぁ、気付かなかった。 ご指摘ありがとうございます。 まぁ、それはともかく fgetsなどのsdio.hの中にある関数は私も使ったことはあります。 これは一例として書いたので、使い慣れてるscanfのほうで書きました。

すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

文法上には可能ですし、動作的にも問題ありません。 printfの返却値は、成功時には出力文字数であり、失敗時にはEOFですから、今回の場合は常に真になります。 ただ、やはり普通の書き方ではありませんし、お勧めすることはできません。こうした異常時の処理は、繰返し文を使うより、gotoで処理した方がむしろすっきりする場合があります。 retry:  printf("0以外の数字を入力してください。\n");  scanf("%d", &i);  if (i == 0)  {   printf("まじめに入力してください。\n");   goto retry;  } まあ、gotoを使うと、脊椎反射的に反対する人もいるので、それらの人たちを説得する自信がなければ、この方法も避けた方が無難かもしれません。

noname#16765
質問者

お礼

>>成功時には出力文字数であり、失敗時にはEOFですから、今回の場合は常に真になります 自分もこれなら意図したとおりに動くとは思ったのですが見栄えとかその他もろもろが駄目だろうと思っていたので、もっといい違うやり方がないか考えてみます。 >>gotoで処理した方がむしろすっきりする場合があります。 私はgoto関係は使う気にはなれません。いろいろ問題あるみたいですし・・・

すると、全ての回答が全文表示されます。
回答No.2

とりあえず動くとは言えこの書き方は無しかと。 理由はprintf()の戻り値の意味がdo-while文の条件式の意図するところと異なるからです。 printf()が正常に動作しなかったとき0を入力してもdo-while文を抜けてしまう事が考えられます。

noname#16765
質問者

お礼

やっぱし無理ですか 転送バイト数と書いていたので、やめといたほうがいいかなとは自分でも思っていました。 ここは無難にif文で表示するのが一番ですかね?

すると、全ての回答が全文表示されます。
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.1

もちろんありです。文法上問題がある(=コンパイルでエラーになる)のでない限り、どんな書き方も許されます。 ただ、それが分かりやすい表現かどうかはまた別問題ですが。

すると、全ての回答が全文表示されます。

関連するQ&A