アドレスを使った関数の質問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
MILE
記事: 2
登録日時: 7年前

アドレスを使った関数の質問

#1

投稿記事 by MILE » 7年前

現在、選択ソートを行うソースコードを作成しております。
今回はアドレスの方を入れ替えて昇順(降順)に入れ替えるプログラムを作っています。
しかし、アドレスが上手く渡されないのか、このコードを使用するとエラーが発生してしまいます。
調べてみたところ、selection_sort関数にアドレスしか渡せておらず、配列の数字が読み込めてないのが原因だったようです。
どのように変えれば配列も読み込んでくれるのでしょうか?

OS:Windows 10
環境:Visual Studio C++2017

始めて掲示板を使用するので不備などが多いかもしれませんがよろしくお願いします。

コード:


#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LIST 1
#define MIN_LIST 2

int nyuryoku(const int minimum, const int maximum);		//入力する関数
void selection_sort(int *list[], int num, int choose);	//選択ソート
void swap(int *x, int *y);								//入れ替え関数

int main(void) {

	int num;		//個数
	int *list;		//リスト
	int i, j;
	int max, min;	//最高値・最低値
	int max_or_min;
	Student *student;

	printf("選択ソートのプログラム\n");
	printf("リストに入れる個数を入力してください\n");
	printf("3~20まで有効です\n");
	num = nyuryoku(3, 20);

	//容量を確保
	list = (int*)malloc(sizeof(int) * num);

	if (list == NULL || student == NULL) {
		printf("エラーが発生したので至急終了します\n");
		_getch();
		return 0;
	}

	printf("ソートする数字を入力してください\n");
	printf("1~100まで有効です\n");

	for (i = 0; i < num; i++) {
		printf("%d個目の数字:", i + 1);
		list[i] = nyuryoku(1, 100);
	}

	printf("どちらにソートするか選択してください");
	printf("1:低い順 2:高い順");
	max_or_min = nyuryoku(MAX_LIST, MIN_LIST);	//1か2で選択してもらう

	//ここの時にアドレス渡しにミスがあり、selection_sort関数でエラーが発生する
	printf("\nソート中です\n");
	selection_sort(&list, num, max_or_min);		//選択ソート

	printf("ソート完了\n");
	for (i = 0; i < num; i++) {
		printf("%d\n", list[i]);
	}

	_getch();
	return 0;
}

int nyuryoku(const int minimum, const int maximum) {

	int suuti;
	char buf[100];

	do {
		fgets(buf, sizeof(buf), stdin);
		sscanf_s(buf, "%d", &suuti);

		if (!(minimum <= suuti && suuti <= maximum)) {
			printf("規定内の数値ではありません 入力し直しをお願いします");
		}
	} while (!(minimum <= suuti && suuti <= maximum));
	return suuti;
}

void selection_sort(int *list[], int num, int choose) {

	int i, j;
	int min, max;

	for (i = 0; i < num - 1; i++) {
		min = *list[i];
		max = *list[i];
		for (j = i + 1; j < num; j++) {
			if (min > *list[j] && choose == MAX_LIST)		//ここでlist[1]等を行うと終了する
				min = *list[j];
			else if (max < *list[j] && choose == MIN_LIST)
				max = *list[j];
		}
		if (min != *list[i] && choose == MAX_LIST) {
			swap(&(*list[i]), &(*list[j - 1]));
		}
		else if (max != *list[i] && choose == MIN_LIST) {
			swap(&(*list[i]), &(*list[j - 1]));
		}
	}
}

void swap(int *x, int *y) {
	int swap;
	
	swap = *x;
	*x = *y;
	*y = swap;
}

かずま

Re: アドレスを使った関数の質問

#2

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

このコードを参考にして、修正してください。

コード:

#include <stdio.h>

void print(int *list, int n)
{
	for (int i = 0; i < n; i++) printf(" %d", list[i]);
	putchar('\n');
}

void print2(int *list[], int n)
{
	for (int i = 0; i < n; i++) printf(" %d", &list[i]);
	putchar('\n');
}

int main(void)
{
	int list[4] = { 3, 1, 4, 2 };
	print(list, 4);
	print2(&list, 4);
}
何が間違っていたのか説明できますか?

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: アドレスを使った関数の質問

#3

投稿記事 by usao » 7年前

selection_sort関数の第1引数の型をそうする理由がよくわかりませんが……
とりあえずその型の場合,selection_sort関数内の

コード:

 *list[i]
みたいな記述は全て

コード:

(*list)[i]
という形に書くのが正解なのではないかと思います.(演算子の優先度的な意味で)

かずま

Re: アドレスを使った関数の質問

#4

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

すみません。print2 のコードが間違っていました。

コード:

printf(" %d", &list[i]); を
printf(" %d", *list[i]); に訂正し、
さらに、usaoさんの修正方法がうまく行くことを示すために
print3() を追加します。

#include <stdio.h>

void print(int *list, int n)
{
	for (int i = 0; i < n; i++) printf(" %d", list[i]);
	putchar('\n');
}

void print2(int *list[], int n)
{
	for (int i = 0; i < n; i++) printf(" %d", *list[i]);
	putchar('\n');
}

void print3(int (*list)[], int n)
{
	for (int i = 0; i < n; i++) printf(" %d", (*list)[i]);
	putchar('\n');
}

int main(void)
{
	int list[4] = { 3, 1, 4, 2 };
	print(list, 4);
	print3(&list, 4);  // これは正常に実行できるので先に実行
	print2(&list, 4);  // これはエラーになります。
}

MILE
記事: 2
登録日時: 7年前

Re: アドレスを使った関数の質問

#5

投稿記事 by MILE » 7年前

ただいま検証したところ、print3の記述だとエラーが出て検証することができませんでした 申し訳ないです…
(*list)に関しては修正したらひとまず成功しました
というより、この記述選択ソート事態のコードがミスっていて昇順(降順)になっていませんね…大変申し訳ありませんでした
ご質問にお答えいただきありがとうございました
まだまだ実力不足ではありますが、よろしくお願いいたします

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: アドレスを使った関数の質問

#6

投稿記事 by usao » 7年前

オフトピック

コード:

文中に [i] って書くと斜体になっちゃう罠

かずま

Re: アドレスを使った関数の質問

#7

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

MILE さんが書きました:
7年前
ただいま検証したところ、print3の記述だとエラーが出て検証することができませんでした 申し訳ないです…
(*list)に関しては修正したらひとまず成功しました
というより、この記述選択ソート事態のコードがミスっていて昇順(降順)になっていませんね…大変申し訳ありませんでした

エラーが出るのは、print3 ではなく、print2 ですね。

また、配列を関数に渡すのは、print3 の (*list) でもできるけど、
通常は print のようにするのだということは理解されていますか?

選択ソート自体のコードミスは認められたようですが、
それはもう解決済みなのでしょうか?

参考までに、私のコードを示しますが、これは模範解答ではありません。

コード:

#include <stdio.h>  // fgets, sscanf, printf, puts

#define SIZE 20

void swap(int *x, int *y) { int t = *x; *x = *y; *y = t; }

void selection_sort(int *a, int n, int ascending)
{
	for (int i = 0; i < n - 1; i++)
		for (int j = i + 1; j < n; j++)
			if (ascending ? a[i] > a[j] : a[i] < a[j]) swap(a + i, a + j);
}

int input(int a, int b)
{
	char buf[100];
	while (fgets(buf, sizeof buf, stdin)) {
		int n;
		if (sscanf(buf, "%d", &n) == 1 && n >= a && n <= b) return n;
		printf("規定内の数値ではありません。再入力をお願いします: ");
	}
	return -1;
}

int main(void)
{
	int a[SIZE], n;

	printf("選択ソートのプログラム\n"
		"リストに入れる個数を入力してください\n" "3~%dが有効です: ", SIZE);
	n = input(3, SIZE);
	if (n < 0) return puts("入力エラー"), 1;
	puts("ソートする数字を入力してください\n" "1~100まで有効です");
	for (int i = 0; i < n; i++)
		printf("%d個目の数字:", i + 1), a[i] = input(1, 100);
	printf("どちらにソートするか選択してください。1:昇順 2:降順 ");
	selection_sort(a, n, input(1, 2) == 1);
	for (int i = 0; i < n; i++)
		printf("%d\n", a[i]);
}
selection_code の中の if 文ですが、おそらく、
こんな書き方をする人はほとんどいないと思います。
普通は次のように書くでしょう。

コード:

			if (ascending) {
				if (a[i] > a[j]) swap(&a[i], &a[j]);
			}
			else {
				if (a[i] < a[j]) swap(&a[i], &a[j]);
			}
また、selection_sort自体、もう少し効率の良い書き方もできます。

コード:

void selection_sort(int *a, int n, int ascending)
{
	for (int i = 0; i < n - 1; i++) {
		int k = i;
		for (int j = i + 1; j < n; j++)
			if (ascending ? a[k] > a[j] : a[k] < a[j]) k = j;
		swap(a + i, a + k);
	}
}
j のループで何度も swap を呼び出すよりも、k = j; という単純な
処理で済まし、swap を呼ぶのは一度だけとしています。

問題を解くのに、解は一つではありません。いろいろ考えてみましょう。

返信

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