dポイントプレゼントキャンペーン実施中!

次のような問題があって、プログラミングしてみたのですが、
コンパイルすると永久ループになってしまいます。
また、入力されるはずの整数が表示されません。
どうすればよいか教えていただけると助かります。
よろしくお願いします。

整数を順番に入力し、負の数が入力されたら、それまでに入力された非負の整数を、 入力された順番とは逆に全角空白で区切って出力するプログラムを作成しなさい。
自動評価の都合上、上記以外は表示しないこと。なお、入力は最大10回とする。

【0 1 2 3 4 -1 が入力された場合の表示例】
4 3 2 1 0      

**************************************
#include <stdio.h>

int main(void) {
int num[10];
int n;

for(n=1;n<11;n++){
printf("整数入力:¥n");
scanf ("%d", &num[n]);
if(num[n]<0){
for(n=10;n>0;n--){
printf("%d ",num[n]);
}
}
}
}

A 回答 (8件)

ついでなのでもう一言。



こういう場合、「どうすれば良いか」を聞くより、「なぜこうなるか(無限ループしてしまうのか)」を理解する方がはるかに大切です。
No.3 で指摘されていますが。

そして、それは、「使っている変数を書き出して、プログラムを一行ずつ追いかけて、変数がどう変わり、どういう順序で処理されるか」と(No.4 では「頭で考えれば分かると書かれていますが)「紙に書き出してみれば」わかります。

実際、No.1 の回答へのお礼で
「ループを分離してすっきりしてわかりやすくなりました」と書かれていますが、元のプログラムは、単に「すっきりしていない、わかりにくい」だけではなく、明らか無限ループするプログラムです。
わかりにくいプログラムがわかりやすくなったというだけではないのです。

それは、慣れた人から見ると、「このプログラムはひどい」というレベルの間違いですが、プログラムを書き始めた人が、問題文を読みながら、(本当は、「設計」という行為が入るのだが)一行ずつ組み立てると、「まあ、やってしまうかもしれないな」というプログラムです。

ですから、なぜ、最初のプログラムが無限ループになるのか、理解しないでおくと、「初心者がやってしまいがちなとんでもないプログラム」という状態から抜け出すのにかなり苦労することになります。

※まあ、紙に書き出さなくても、「デバッガ」の使い方を覚えて、実行をトレースしてみるのも、役に立つと思います。
    • good
    • 1

Cに特有な話があるのでひとつだけ。



まず、for は、
for (i = 0; i < 10; i++)
というパターンで使われることが多いのですが、for自体は、「(たとえば)10回繰り返す」ということを表現するだけのものではありません。

あくまでも、for(式1; 式2; 式3) ということで、

1)ループに先立って、式1 を実行する
2)式2が成立していたら、ループの処理を行う
3)ループの処理が1回分終わったら、式3を実行する。
4) 2) に帰る

という処理をするものです。
だから、
for(i = 0; i < 10; i++)
が、
1) 最初に i に 0 を代入し、
2) i < 10 が成立している間ループを繰り返し
3) ループが終わるごとに i++ を実行する
という意味になるのです。

for(n--; n>=0 ; n--)
の、式1,式2,式3がどれになるか確認して、どういう処理をするのか、確かめてみてください。

for の 式1は、必ず代入という決まりはないです。
    • good
    • 0

>結果表示のループのn--を何もしない。

にするとどうなるのか…。

微妙に判りにくいかな。

for(n--; n>=0 ; n--){

for(; n>=0 ; n--){
にしてみる。
for(n = 9; n>=0 ; n--){
にしてみる。
# 10ではないので注意。
for(n = 0; n>=0 ; n--){
にしてみる。
for(n = 0; n < 10 ; n++){
にしてみる。
などなど……。
    • good
    • 0

>最初の入力値が入るのはどうしてか教えていただけますか?


>はじめから1引くと、最初の値が消えてしまうのではと思うのですが。

最初の入力値ってなんです?
最初の値が消えるってのもなんのこと言ってます?

頭の中で実行(中の動作を想定)でききないなら、あらゆるところにprintf()などで変数の値を出力するいわゆるprintfデバッグをするか、
デバッガのステップ実行で1つずつ追いかけてみたらどうですか。


int num[10], n, i;

for(n = 0; n < 10; n++) {
 printf("\n n = %d/num[]=", n);
 for(i = 0;i < 10;i++) printf("%d ", num[i]);
 printf("\n");
 scanf("%d", &num[n]);
 printf("\n num[]=");
 for(i = 0;i < 10;i++) printf("%d ", num[i]);
 printf("\n");
 if (num[n] < 0) {
  break;
 }
}
printf("\n loop-end\n n = %d/num[]=", n);
for(i = 0;i < 10;i++) printf("%d ", num[i]);
printf("\n");
for(n--; n>=0 ; n--){
 printf(" num[%d]=%d", n, num[n]);
}


こんな感じですかね。
scanf()で値を入れる前後でnの値とnum[]配列の全部を表示します。
で、ループを抜けた後でもnの値とnum[]配列の全部を、結果表示のループ中もnの値を出力します。
# num配列は未初期化なんでscanf()で値を取り込んでいない箇所の値は不定値(プロセス起動ごとに値が変わるかも知れない)になります。
# 最初のループの前に特定の値にしておくといいかと。
結果表示のループのn--を何もしない。にするとどうなるのか…。
とかいろいろ変更してみるといいでしょう。
    • good
    • 0

実際にそのプログラムを頭の中で動かせばわかるはずです.

    • good
    • 0

「どうすればよいか」の前に「どうしてそうなるのか」を理解してください.

この回答への補足

以下のようなプログラムもありました。
そこで、2つめのfor文で、
初期値が n--なのに、
最初の入力値が入るのはどうしてか教えていただけますか?
はじめから1引くと、最初の値が消えてしまうのではと思うのですが。
よろしくお願いします。

#include <stdio.h>

int main(void){
int num[10], n;

for (n = 0; n < 10; n++) {
scanf("%d", &num[n]);
if (num[n] < 0) {
break;
}
}
for(n--; n>=0 ; n--){
printf(" %d",num[n]);
}
}

補足日時:2013/11/20 20:47
    • good
    • 0

というわけで、



#include <stdio.h>

int main(void)
{
int num[10], n;

for (n = 0; n < 10; n++) {
printf("整数入力:¥n");
scanf("%d", &num[n]);
if (num[n] < 0) {
break;
}
}

while (n--) {
printf("%d%s", num[n], (n == 0) ? "" : " ");
}
return 0;
}
    • good
    • 0

>コンパイルすると永久ループ



「実行すると」ですね?

さて、

>int num[10];

このように定義した配列で、有効な添字は0~9の10個です。
num[10]
の10とは、num[10]にアクセスできる、という意味ではありません。
領域を0から9までの10個確保する、という意味です。

ところが、

>for(n=1;n<11;n++){
>for(n=10;n>0;n--){

nが10の場合があるため、配列の定義範囲外の領域へアクセスしようとしています。
まずは、ここを修正してみてはどうでしょうか。

また、for文によるループの仕方も正しくないように見えます。
入力するループと逆順に出力するループを入れ子にするのではなく、
完全に分離してみてはどうでしょうか。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ループを分離してみました。
このほうがすっきりしてわかりやすくなりました。
nの範囲も修正してみました。
ありがとうございました。

お礼日時:2013/11/20 20:39

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