プロが教えるわが家の防犯対策術!

C言語習いたての者です。どうぞよろしくお願いします。

1~20の範囲内で数値を5回入力させ、入力順に画面に出力するプログラムを作りたいと思っています。

この中で、範囲外の数値か、入力済みの数値が入力された場合に、
それに応じたエラーメッセージを表示させ、再入力を要求する仕組みを
加えようと思い、
制御文を用いてどういうループにすればいいか考えているのですが、
思うような結果が返ってきません。

今まで私が考えていたループの構造としては、

int count = 0;<<ループ用カウンター宣言・初期化>>

if(<<入力された数値が指定範囲内の時>>)
{
_ for(<<countが範囲内かどうか>>)
_ {
__ if(<<入力された数値が入力済みではない時>>)
__ {
___ break;<<ループ終了。次の数値入力>>
__ }
__ <<数値重複用エラーメッセージ出力>>
_ }
_ break;<<ループ終了。次の数値入力>>
}
<<範囲外数値用エラーメッセージ出力>>


条件としては、
・配列と制御文を用いる
・標準ヘッダファイルは<stdio.h>のみを用いる

上記のループをどう修正したらいいか、を教えていただけるとうれしいです。

A 回答 (7件)

ざっと作ってみましたが、僕ならこう書きます。



int cnt;
int inp[5];

while( cnt < 5 ){
 入力
 inp[cnt] = 入力値
 if( 範囲外 ){
  エラーメッセージ
  continue
 }
 for( cnt まで ){
  if( 入力済み ){
   エラーメッセージ
   break
  }
 }
 if( 初入力 ) cnt++
}

実際には変数の初期化やフラグ等必要ですが。
参考まで。
    • good
    • 0

丸々答えてしまうわけにはいかないので、ロジックの骨組みだけ。



// 数字入力要求メッセージ
do
{
 // エラーフラグを0にする。
 // 数字を入力
 if( 数字が1~20の間ではない ) // (3)
 {
  // エラーメッセージ
  // エラーフラグを1にする。
  // 再入力要求メッセージ
 }
 else
 {
  for( i が 0~count-1 の間繰り返す ) // (2)
  {
   if( 今回入力された数字とi番目に入力された数字が等しい ) // (4)
   {
    // エラーメッセージ
    // エラーフラグを1にする。
    // 再入力要求メッセージ
    break;
   }
  }
 }
 if( エラーフラグが0 ) // (5)
 {
  count++;
  // 次の数字入力要求メッセージ
 }
}while( count<5 ); // (1)

といった感じのループ構造になると思われます。


 1)count個の数字を入力させるループ
 2)前回までに入力された全ての数字と今回入力された数字を比較するループ
の2つの繰り返しと、
 3)規定の範囲内(1~20)の数字であるかどうかで分岐
 4)○回目に入力された数字と今回入力された数字が等しいかどうかで分岐
の2つの判定、さらに
 5)3、4で共に大丈夫だった時には次の数字入力に進み、どちらかで駄目だった場合には今回の数字入力のまま
とする処理も必要になります。

上記ロジックには次の数字の入力なのか、再入力なのかのメッセージ分けなんかも含めてあります。
    • good
    • 0

がると申します。


んっと。まずポイントとしては。

要求仕様が
・1~20の範囲内で数値を5回入力させ、入力順に画面に出力する
とのことですが。この場合
・範囲外ならどうするか
を考えてみます。
・入力済みの数値が入力された場合に、それに応じたエラーメッセージを表示させ、再入力を要求する
とありますが、場合によっては
・間違いも1カウントとみなす
ケースもあるので。

まぁ今回は拝見している限り
・正しい入力が5回行われた時点で出力
であろうと予想されます。

ちょいと難しいかもしれませんが、ここはwhileループを使ったパターンを提示してみましょう。

int count = 0; /* 「5回入力したかどうか」を判定します */
int data[5]; /* データの格納に使います */
char cwk[1024]; /* 入力データをここで受け取ります */
int iwk; /* 入力されたデータを「数値として」受け止める作業用変数です */

/* メイン処理 開始 */
while(1) { /* 無限ループを書くときの定番のような書き方です */
 while(1) { /* ここは「正しいデータを受け取るための」ループです */
  /* 入力データを受け取る */
  fgets(cwk, sizeof(cwk), stdin); /* 入力をscanfなんかで受け取っては絶対にだめ!! */
  /* 入力データは「文字」なので、「数値」に変換 */
  /* 本当は事前にisdigitとかすると丁寧なのですが、文字なら0になるので今回は略 */
  iwk = atoi(cwk);
  /* データが「正しければ」ループを抜ける */
  if (iwkに正しいデータが入っている) {
   break;
  }
  /* エラーメッセージを出力する */
  puts("");
 } /* このループを抜けた時点で「正しい数値データがiwkに入っている」はずです */

 /* まずデータを格納 */
 data[i] = iwk;
 /* カウンタをインクリメント */
 i ++;
 /* 終わり? */
 if (countが五回(以上)なら) {
  break;
 }
}
/* 最後に、data配列の内容を順次出力する */
printf


ーー
こんな感じでどうでしょうか?
わざと数箇所、穴埋めのようにあけてますので、頑張って埋めてみてください。
    • good
    • 0

この場合は、for文よりもwhile(do while)文を使うほうがよいと思います。


理由は、「間違っているときに再入力させる」というところからです。
while文で入力値が間違っていないときはcountを++して次に進む、
間違っているときはcountを++しないで"continue"という使い方をすればいいと思います。

後はみなさんの回答を見れば理解できると思います。がんばってください。
    • good
    • 0

皆さんwhileを大外に使っていらっしゃいますが大外に


for(count = 0; count < 5; ++count)
とする方法もあるかと思います。
この場合continueなどを使うとカウントが変になるので
入力と値のチェックをwhileの中に入れ込んであげるとすっきりします。

while(1){
 入力
 if(範囲外){その旨のメッセージ}
 else if(重複){その旨のメッセージ}
 else break;
}
のような形です。

重複チェックを関数にくくりだすとこう書けますが、できない場合は分岐が若干入り組んでしまうかもしれません。

私の回答は5回という回数の部分を重視しています。KXWonderfulさん、galludaさん、Chronos198さん、ttyp03さんとは着目点がずれていますし、入れ子が深くなる傾向があるかもしれません。
    • good
    • 0

「5回入力する」ということですから, #5 のように


for (int count = 0; count < 5; ++count) {
}
という構造が外にある方が自然ですね.

あと「1~20 の範囲内」をどのように解釈するかが問題のあやとして残りますが, これを「1~20 の範囲にある整数」と解釈してよいのであれば「当該整数が既に入力されているかどうか」を表すフラグとして配列を使うのがきれいでよいかと.

数値の入力は fgets と sscanf の組合せ?
    • good
    • 0

こんばんわ



既に、解決しているかどうか、分かりませんが、とりあえず、回答させていただきます・・・(^^;;

最初に、上記の例を見て思ったのですが、if 文で、条件が揃わなかった時には、else 文が必要です。下記の例で言うと、条件がXの時には、処理Aが実行され、それ以外では、処理Bが、実行されます。

if(<<条件がX>>)
{
 <<処理A>>
}
else
{
 <<処理B>>
}

crusader さんの例を変更するとすると、下記の様になると思います。

int count = 0;<<ループ用カウンター宣言・初期化>>

for(<<countが範囲内かどうか>>)
{
 <<入力>>
 if(<<入力された数値が指定範囲内の時>>)
 {
  if(<<入力された数値が入力済みではない時>>)
  {
    <<配列[count]に入力された数値を保存>>
    <<表示A:配列[count]>>
    <<countをインクリメントする>>
  }
  else
  {
    <<数値重複用エラーメッセージ出力>>
  }
 }
 else
 {
   <<範囲外数値用エラーメッセージ出力>>
 }
}

//表示B
for(<<count を初期化して、countが範囲内実行する>>))
{
 <<配列[count] を表示>>
}

入力順に表示する方法が、入力された直後に、表示するのであれば、表示Aを。
データーが全部揃った後に、表示するのであれば、表示Bを、実行してください(^^

また、上記の for(<<countが範囲内かどうか>>) は、while(<<countが範囲内かどうか>>) と書いても、同じ結果が得られます。

蛇足ですが・・・

for( ; ; )
{
 <<処理>>
}



while(true)
{
 <<処理>>
}

は、同じく無限ループになります(^^

個人的には、break 文は、for文、while文から、抜けてしまうので、初心者の方には、余りお勧めしません(^^;;
    • good
    • 0

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