ポインタを使った配列を関数に受け渡す方法について

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

ポインタを使った配列を関数に受け渡す方法について

#1

投稿記事 by gumi » 6年前

メイン関数で、乱数を格納した配列を作り、その配列をsort関数で昇順に並び替えし手出力したいのですが、
以下コードでは、エラーが出てしまいます。

どこを直せばよいのか、ご教示いただけますと幸いです。

binarysearch.c:4:18: error: expected ‘)’ before ‘int’
void sort(_data, int n)
^
binarysearch.c: In function ‘main’:
binarysearch.c:44:3: warning: implicit declaration of function ‘sort’ [-Wimplicit-function-declaration]
sort(*data, n);

コード:

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

void sort(*_data, int n)
{
	int i, j, tmp;
	
	for (i = 0; i < 5; i++)
	{
		for (j = i; j < 5; j++)
			{
				if (_data[i] > _data[j])
					{
						tmp = _data[i];
						_data[i] = _data[j];
						_data[j] = tmp;
					}
			}
			printf("%d ", _data[i]);
	}

}

int main(void)
{
	int *data;
	int n,i;
	printf("配列の要素数を決めてください:");
	scanf("%d", &n);

	data =(int *)malloc(n * sizeof(int));

	printf("ランダムに数を出力します:\n");

	for (i = 0; i < n; i++)
	{
		int num;
		num = rand() % 101;
		data[i] = num;
	}

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

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

Re: ポインタを使った配列を関数に受け渡す方法について

#2

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

  • 4行目の第一引数でポインタが指す型が抜けている。*_dataではなくint *_dataなどとする。
  • 44行目でポインタを渡すべき第一引数に整数を渡している。*dataではなくdataとする。
  • sort関数において、渡される要素数?nが処理に反映されていない。8行目と10行目の5をnとする。
という修正をするといいと思います。
また、
  • 29行目で、scanfの戻り値が1か(正常に読み込めたか)および読み込んだnの値が有効か(例えば、正か)をチェックするようにする。
  • 31行目またはその直後で、mallocが成功したか(返り値がNULLでないか)をチェックするようにする。
  • (44行目のsort関数の呼び出しを41行目(ループの前)に移動する。)
  • (srand関数をプログラムの最初で用い、なるべく毎回違う乱数が出力されるようにする。)
という修正もした方がいい気がします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

gumi

Re: ポインタを使った配列を関数に受け渡す方法について

#3

投稿記事 by gumi » 6年前

みけcat様

回答ありがとうございます。
いただいたご指摘を反映させました。

その上で1点お伺いさせてください。
44行目について、「ポインタを渡すべき第一引数に整数を渡している」というのは、
「*dataとは、配列の先頭アドレスを指すものなので、第一引数が整数になってしまっている」という理解でよろしいでしょうか。
mainの中で関数を呼ぶときに、dataに*がついて、sort関数が受け取るときには*がつかない、というロジックが理解できておりません。
ポインタの使い方に混乱しているため、よろしければ解説いただけますと幸いです。

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

Re: ポインタを使った配列を関数に受け渡す方法について

#4

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

gumi さんが書きました:「*dataとは、配列の先頭アドレスを指すものなので、第一引数が整数になってしまっている」という理解でよろしいでしょうか。
いいえ。
dataが配列の先頭アドレスを指し、*dataはdataが指すもの、すなわち整数になります。
gumi さんが書きました:mainの中で関数を呼ぶときに、dataに*がついて、sort関数が受け取るときには*がつかない、というロジックが理解できておりません。
*をつけてはいけないと指摘しているのに、「mainの中で関数を呼ぶときに、dataに*がついて」というのはどういう意味でしょうか?
存在しないロジックであれば、理解できなくてもいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

gumi

Re: ポインタを使った配列を関数に受け渡す方法について

#5

投稿記事 by gumi » 6年前

みけCAT様

回答ありがとうございます。

*をつけてはいけないと指摘しているのに、「mainの中で関数を呼ぶときに、dataに*がついて」というのはどういう意味でしょうか?
>申し訳ありません、「main関数の中では*がつかずdataとなり、sort関数で受け取るときint *_dataとなる」の誤りです。

box
記事: 2002
登録日時: 13年前

Re: ポインタを使った配列を関数に受け渡す方法について

#6

投稿記事 by box » 6年前

コード:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// mainから渡されるのはint *型
void sort(int *d, int n)
{
    int i, j, t;

    for (i = 0; i < n - 1; i++) {
        for (j = i; j < n; j++) {
            if (d[i] > d[j]) {
                t = d[i], d[i] = d[j], d[j] = t;
            }
        }
    }
}

int main(void)
{
    int *data;      // dataはint *型、*dataはint型
    int n, i;

    printf("配列の要素数を決めてください:");
    scanf("%d", &n);

    data = (int *) malloc(n * sizeof(int));
    if (data == NULL) {
        fprintf(stderr, "mamory allocation error\n"), exit(1);
    }

    // 乱数の初期化(これをやっとかないと、毎回同じ乱数を発生しておもしろくない)
    srand((unsigned) time(NULL));

    printf("ランダムに数を出力します:\n");
    for (i = 0; i < n; i++) {
        data[i] = rand() % 101;
    }

    // sort関数の第1引数はint *型なのでdataを渡す。また、ループの中で
    // 毎回ソートするのはほとんど無意味。
    sort(data, n);

    for (i = 0; i < n; i++) {
        printf("data[%d]=%d\n", i, data[i]);
    }
    return 0;
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

Bull
記事: 149
登録日時: 9年前

Re: ポインタを使った配列を関数に受け渡す方法について

#7

投稿記事 by Bull » 6年前

gumi さんが書きました:>申し訳ありません、「main関数の中では*がつかずdataとなり、sort関数で受け取るときint *_dataとなる」の誤りです。
C言語の文法がそうなっていると言うと身も蓋もないですが、関数の仮引数の宣言も普通の変数宣言と同じ書式になります。
引数の引き渡しだけを考えると以下の宣言と本質的には変わりません。

コード:

int *data;
/* ... */
data =(int *)malloc(n * sizeof(int));
/* ... */
int *_data = data
これなら理解できますか?

かずま

Re: ポインタを使った配列を関数に受け渡す方法について

#8

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

gumi さんが書きました:メイン関数で、乱数を格納した配列を作り、その配列をsort関数で昇順に並び替えし手出力したいのですが、
以下コードでは、エラーが出てしまいます。

どこを直せばよいのか、ご教示いただけますと幸いです。

binarysearch.c:4:18: error: expected ‘)’ before ‘int’
void sort(_data, int n)
^
binarysearch.c: In function ‘main’:
binarysearch.c:44:3: warning: implicit declaration of function ‘sort’ [-Wimplicit-function-declaration]
sort(*data, n);
^~~~
質問に誤りがあります。

そのコードをコンパイルすると、次のようなエラーメッセージが表示されます。

コード:

$ gcc binarysearch.c
binarysearch.c:4:11: error: expected declaration specifiers or '...' before '*' token
 void sort(*_data, int n)
           ^
binarysearch.c: In function 'main':
binarysearch.c:44:9: warning: implicit declaration of function 'sort' [-Wimplicit-function-declaration]
         sort(*data, n);
         ^~~~
質問のようなエラーメッセージを出させるためには、

void sort(_data, int n) というコードでないとだめです。

以前もコードには "%S" なんてないのに、"%S" についての
エラーメッセージについて質問していましたね。

なお、コードは binary search ではなく、
selection sort になっています。

それで、今回の問題は解決していないのでしょうか?

返信

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