配列の問題です

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あゆ

配列の問題です

#1

投稿記事 by あゆ » 9年前

C言語を初めて勉強していて、やっと配列のところまできました。配列を使ってキーボードから入力された整数を大きい順にソートするプログラムの課題が出たのですが、実行すると大きい順に並べ変わって出てきた数字が1つ少ない状態になってしまいます。いろいろ調べてバブルソートの考え方にたどり着いて書いてみたのですがうまくいきません。どこを直したらいいのか具体的に教えてほしいです。

コード:

#include <stdio.h>
#define NUM 10

int main(void)
{

	int n[NUM];		//NUM個の型を用意する
	int tmp;			//交換する際の一時代入につかう
	int i;			//繰り返し
	int t, s;		//比較の際つかう

	//数字を入力させる
	printf("%d個の整数を入力してください。\n",NUM);
	for (i = 0; i < NUM - 1; i++) {
		scanf_s("%d\n", &n[i]);
	}
	
	printf("\n大きい順に並べ替えます。\n\n");

	//forの二重ループ
	//1つめと2つめの数字を比較して大きい順にならべかえる
	//2つめと3つめの数字を比較して大きい順にならべかえる
	//(NUM-1)番目とNUM番目まで繰り返す

	for (t = 0; t < NUM; ++t)
		for (s = t + 1; s < NUM; ++s) {
			if (n[s] > n[t]) {
				tmp = n[s];			//変数tmpにn[s]を代入				
				n[s] = n[t];			//変数n[s]にn[t]を代入
				n[t] = tmp;			//変数n[t]にtmp(n[s])を代入
									//入れ替えの完了
			}
		}
	

	//大きい順に表示させる
	//forでNUM-1回繰り返す

	for (i = 0; i < NUM - 1; ++i) {
		printf("%d\n", n[i]);
	}

	return 0;

}
初心者でコメントがいろいろ入っていて見づらいと思いますがよろしくお願いします。

aridai1221
記事: 16
登録日時: 9年前

Re: 配列の問題です

#2

投稿記事 by aridai1221 » 9年前

後で私も一緒に考えさせていただきますが、
今、ぱっと見で思ったことを書かせていただきます。
あゆ さんが書きました:初心者でコメントがいろいろ入っていて見づらいと思いますがよろしくお願いします。
過剰なコメントも良くないこともありますが、
初心者ならコメントをたくさん書くことはいいと思います。
私も初心者なのですが、未知のフレームワークやライブラリを初めて触るときは
コメントを書いて学びんでいきます。

あと、表示部のコードですが、

コード:

//大きい順に表示させる
    //forでNUM-1回繰り返す
 
    for (i = 0; i < NUM - 1; ++i) {
        printf("%d\n", n[i]);
    }
これだと i が 0 から始まり、
NUM - 1 つまり 9 よりも小さい間ループするという条件なので
0, 1, 2, 3, 4, 5, 6, 7, 8 という値を取っていきます。
9という値はこの条件では取らないので
表示される数字が1つ少なくなるのだと思います。
最後に編集したユーザー aridai1221 on 2016年7月02日(土) 21:57 [ 編集 1 回目 ]

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 配列の問題です

#3

投稿記事 by みけCAT » 9年前

  • ソートはNUM個の要素を対象にしているのに、入出力はNUM-1個しかしていないので、仮に適切な入力が与えられたとしても、
    初期化されていない自動変数の値(不定)を使用し、未定義動作になります。
    NUM-1回ではなくNUM回繰り返すようにしてください。
  • 入力を正しく読み込めたかを確認するようにするといいでしょう。
  • 何も工夫せずに標準入力から読み込んでいるので、リダイレクトなどの条件によってはキーボードから読み込めません。
    キーボードからの入力に対応した端末プログラムを利用し、標準入力がキーボードに接続される条件で起動するようにするといいでしょう。
  • 処理系が//を用いたコメントに対応していない場合は、/* ~ */を用いたコメントに書き換えるか消すといいでしょう。
  • 処理系がscanf_sに対応していない場合は、scanfに置き換えるといいでしょう。
ちなみに、これはバブルソートではなく選択ソートですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

aridai1221
記事: 16
登録日時: 9年前

Re: 配列の問題です

#4

投稿記事 by aridai1221 » 9年前

あゆ さんが書きました:どこを直したらいいのか具体的に教えてほしいです。
具体的ではないですが、
直すべき場所はfor文の条件です。

大丈夫です。
ちょっと考えたら分かります。

ちょっと直したら
あゆさんのコード
ちゃんと動作しましたよ :)

あゆ

Re: 配列の問題です

#5

投稿記事 by あゆ » 9年前

みなさんのアドバイス通りにforのところをいじってみたのですが、うまく作動してくれません・・・。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 配列の問題です

#6

投稿記事 by みけCAT » 9年前

あゆ さんが書きました:みなさんのアドバイス通りにforのところをいじってみたのですが、うまく作動してくれません・・・。
もし直してほしいのであれば、そのコードを提示していただけますか?
入力と期待する出力のデータもあると嬉しいです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

あゆ

Re: 配列の問題です

#7

投稿記事 by あゆ » 9年前

コード:

#include <stdio.h>
#define NUM 10

int main(void)
{

	int n[NUM - 1];	//(NUM-1)個の型を用意する
	int tmp;			//交換する際の一時代入につかう
	int i;			//繰り返し
	int t, s;		//比較の際つかう

	//数字を入力させる
	printf("%d個の整数を入力してください。\n",NUM);
	for (i = 0; i < NUM; i++) {
		scanf_s("%d\n", &n[i]);
	}
	
	printf("\n大きい順に並べ替えます。\n\n");

	//forの二重ループ
	//1つめと2つめの数字を比較して大きい順にならべかえる
	//2つめと3つめの数字を比較して大きい順にならべかえる
	//(NUM-1)番目とNUM番目まで繰り返す

	for (s = 0; s < NUM; s++)
		for (t = s + 1; t < NUM; t++) {
			if (n[t] > n[s]) {
				tmp = n[t];			//変数tmpにn[s]を代入				
				n[t] = n[s];			//変数n[s]にn[t]を代入
				n[s] = tmp;			//変数n[t]にtmp(n[s])を代入
									//入れ替えの完了
			}
		}
	

	//大きい順に表示させる
	//forで(NUM-1)回繰り返す

	for (i = 0; i < NUM; i++) {
		printf("%d\n", n[i]);
	}

	return 0;

}
入力する数字は何でもいいです。
出力が上から順番に大きくなっていてほしいです。

このコードにすると入力が11個
出力が10個になってしまいます。

コード:

//数字を入力させる
	printf("%d個の整数を入力してください。\n",NUM);
	for (i = 0; i < NUM - 1; i++) {
		scanf_s("%d\n", &n[i]);
	}
ここを書き換えると入力は10個になるのですが、出力が9個の並べ替えと最後にマイナスのついた入力していない数が出てきてしまいます。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 配列の問題です

#8

投稿記事 by みけCAT » 9年前

入力の書式の%dの後に\nがあるので、10個目の数字を入力した後、次の空白でない文字またはEOFまで読み込む仕様になっています。
「自然」な挙動にするためには、この\nを消してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 配列の問題です

#9

投稿記事 by かずま » 9年前

[quote="あゆ" id=3,18149,138739]

コード:

	int n[NUM - 1];	//(NUM-1)個の型を用意する
元は NUM だったものを NUM - 1 に変更した理由を説明してください。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 配列の問題です

#10

投稿記事 by みけCAT » 9年前

あゆ さんが書きました:

コード:

	int n[NUM - 1];	//(NUM-1)個の型を用意する

コード:

	//数字を入力させる
	printf("%d個の整数を入力してください。\n",NUM);
	for (i = 0; i < NUM; i++) {
		scanf_s("%d\n", &n[i]);
	}
(NUM-1)個しか用意していないのにNUM個も入力させてはいけません。範囲外への書き込みが発生した場合、未定義動作になります。
あゆ さんが書きました:

コード:

	//forの二重ループ
	//1つめと2つめの数字を比較して大きい順にならべかえる
	//2つめと3つめの数字を比較して大きい順にならべかえる
	//(NUM-1)番目とNUM番目まで繰り返す
「nつめとn+1つめの数字」とり「nつめとn+1つめ以降の数字」の方が正確ですね。
あゆ さんが書きました:

コード:

	//大きい順に表示させる
	//forで(NUM-1)回繰り返す

	for (i = 0; i < NUM; i++) {
		printf("%d\n", n[i]);
	}
コメントは(NUM-1)回なのに、コードはNUM回なので、矛盾しています。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る