配列を引数とする関数について

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

配列を引数とする関数について

#1

投稿記事 by Makoto » 7年前

問題文のようにしたいです。お願いします。
次の返却値と引数の型をもつave関数を定義し,n個の配列要素の平均値を計算する.
double ave(int a[], int n);
/* a[0]~a[n-1]の平均値を計算する */
大域変数を使わないこと
ave関数には,scanfやprintfを書かないこと
main関数は書き換えてはいけない

コード:

#include <stdio.h>

/* ここに関数プロトタイプ宣言を書く */

int main(void) 
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;
    ans = ave(a, 5);
    printf("平均値は %f\n", ans);
    return 0;
}

double ave(int a[], int n)
{
/* ここにプログラムを書く */
}
私のソースコード

コード:

#include <stdio.h>

double ave(int a[], int n);

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;
    ans = ave(a, 5);
    printf("平均値は %f\n", ans);
    return 0;
}

double ave(int a[], int n)
{
    a = a[0]+a[1]+a[2]+a[3]+a[4];
}

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

Re: 配列を引数とする関数について

#2

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

ave関数を使わず、main関数で直接平均値を求めて出力することはできますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Makoto

Re: 配列を引数とする関数について

#3

投稿記事 by Makoto » 7年前

はい、できます。

コード:

#include <stdio.h>

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};    
    int b;
    double ans;
   
    b = a[0]+a[1]+a[2]+a[3]+a[4];
    ans = b/5;
    printf("%f\n", ans);
}

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

Re: 配列を引数とする関数について

#4

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

Makoto さんが書きました:はい、できます。

コード:

#include <stdio.h>

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};    
    int b;
    double ans;
   
    b = a[0]+a[1]+a[2]+a[3]+a[4];
    ans = b/5;
    printf("%f\n", ans);
}
では、とりあえずこれをそのまま関数にしましょう。

コード:

#include <stdio.h>

double ave(int a[], int n);

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;
    ans = ave(a, 5);
    printf("平均値は %f\n", ans);
    return 0;
}

double ave(int a[], int n)
{
    int b;
    double ans;
    b = a[0]+a[1]+a[2]+a[3]+a[4];
    ans = b/5;
    return ans;
}
このコードには、
  • 平均値の小数点以下が切り捨てられてしまう
  • 渡されたnを使っていない(渡される配列の要素数が決め打ちになってしまっている)
という問題がありますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Makoto

Re: 配列を引数とする関数について

#5

投稿記事 by Makoto » 7年前

解決しました!みけCATさん、今回もありがとうございました(^-^)

コード:

#include <stdio.h>

double ave(int a[], int n);

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;
			
    ans = ave(a, 5);
    printf("平均値は %f\n", ans);

    return 0;
}

double ave(int a[], int n)
{
    double sum, ans;
	
    for(n=0; n<5; n++)
    {
        sum += a[n];
    }
        
    ans = sum/5;

    return ans;
}

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

Re: 配列を引数とする関数について

#6

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

Makoto さんが書きました:

コード:

double ave(int a[], int n)
{
    double sum, ans;
	
    for(n=0; n<5; n++)
    {
        sum += a[n];
    }
        
    ans = sum/5;

    return ans;
}
この関数は、未初期化の自動変数の値(不定)を計算に使用しているので、未定義動作になります。
また、nの使い方もおかしいですね。
オフトピック
「main関数は書き換えてはいけない」 = 「このmain関数でのみ正しく動作すればいい」ということなら、
こっちのほうがより良い実装かもしれません。

コード:

#include <stdio.h>

double ave(int a[], int n);

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;
    ans = ave(a, 5);
    printf("平均値は %f\n", ans);
    return 0;
}

double ave(int a[], int n)
{
    return 3;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Math

Re: 配列を引数とする関数について

#7

投稿記事 by Math » 7年前

次のコードは(VS2017でテスト)正しい結果がでる”C言語”のただしい書法ですが妙に感じますよね! 

コード:

#include <stdio.h>
 
double ave(int *a, int n);
 
int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;
            
    ans = ave(a, 5);
    printf("平均値は %f\n", ans);
 
    return 0;
}
 
double ave(int *a, int n)
{
	double sum = 0, ans;
    
    for(n=0; n<5; n++)
    {
        sum += n[a];
    }
        
    ans = sum/5;
 
    return ans;
}
[/size]

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

Re: 配列を引数とする関数について

#8

投稿記事 by box » 7年前

別の回答にもあるとおり、ave関数における変数nの使い方が超絶おかしいので修正。
せっかく要素数(今回はn)を引数で受け取っているのに、それを変えちゃまずいでしょう。
要素数がたまたま5であるから、正しく動いているように見えるだけ。要素数が5以外だったらどうする?
今回の場合、ave関数は、渡ってきた配列の要素数が「いくつであっても」対応できるようにしておくべき。

コード:

#include <stdio.h>

double ave(int a[], int n);

int main(void)
{
    int a[5] = {3, 1, 4, 2, 5};
    double ans;

    ans = ave(a, 5);
    printf("平均値は %f\n", ans);

    return 0;
}

double ave(int a[], int n)
{
    double sum;
    int i;

    for (sum = i = 0; i < n; i++) {
        sum += a[i];
    }
    return sum / n;
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

Math

Re: 配列を引数とする関数について

#9

投稿記事 by Math » 7年前

[修正版]

コード:

#include <stdio.h>

double ave(int* a, int n);

int main(void)
{
	int a[5] = { 3, 1, 4, 2, 5 };
	double ans;

	ans = ave(a, 5);
	printf("平均値は %f\n", ans);

	return 0;
}

double ave(int* a, int n)
{
	double sum;
	int i;

	for (sum = i = 0; i < n; i++) {
		sum += i[a];
	}
	return sum / n;
}




[/size]

Math

Re: 配列を引数とする関数について

#10

投稿記事 by Math » 7年前

[修正版]

コード:

#include <stdio.h>

double ave(int* a, int n);

int main(void)
{
	int a[5] = { 3, 1, 4, 2, 5 };
	double ans;

	ans = ave(a, 5);
	printf("平均値は %f\n", ans);

	return 0;
}

double ave(int* a, int n)
{
	double sum;
	int i;

	for (sum = i = 0; i < n; i++) {
		sum += i[a];
	}
	return sum / n;
}




[/size]

Math

Re: 配列を引数とする関数について

#11

投稿記事 by Math » 7年前

失礼。同じものが 2個送られてしまいました。
C言語では「配列とポインターの関係」が微妙で
1.式のなかで配列は「その先頭要素へのポインター」によみかえられる。

2.添字演算子は配列とは無関係で p は *(p+1) の ”簡便記法”である。
 従って 22行のように i[p] と p 同値となる ( *(p+1) = *(1+p) だから )


Math

Re: 配列を引数とする関数について

#12

投稿記事 by Math » 7年前

失礼。同じものが 2個送られてしまいました。
C言語では「配列とポインターの関係」が微妙で
1.式のなかで配列は「その先頭要素へのポインター」によみかえられる。

2.添字演算子は配列とは無関係で p は *(p+1) の ”簡便記法”である。
 従って 22行のように i[p] と p 同値となる ( *(p+1) = *(1+p) だから )


Math

Re: 配列を引数とする関数について

#13

投稿記事 by Math » 7年前

失礼。ie11の動作が変ですね。2個おくられてしまいます?

Math

Re: 配列を引数とする関数について

#14

投稿記事 by Math » 7年前

間違えていました。ただしくは
2.添字演算子[]は配列とは無関係で a は *(a+i) の ”簡便記法”である。
 従って 22行のように i[a] と a は同値となる ( *(a+i) = *(i+a) だから )

Math

Re: 配列を引数とする関数について

#15

投稿記事 by Math » 7年前

a は *(a+i)の簡便記法であり 人間にわかりやすくするためだけに[]演算子が導入されている。
これは syntax sugar ( 甘く取っ付きやすいという意味)と呼ばれる。

返信

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