1次元配列について

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

1次元配列について

#1

投稿記事 by 困ったさん » 18年前

1つ目の問題ではみなさん詳しくお答えいただきありがとうございました。では、2つ目の問題についても
おたずねさせて頂きます。問題は

まず1 次元整数型配列(配列名data,要素数は任意)を準備する.キーボードから任意個の整数デ
ータを入力させ,入力されたデータの ①最大値,②最小値,③平均,④標準偏差 を求めて画面表
示するプログラムを作成しなさい.ただし,上記の4 つの処理について,それぞれ下記の条件を満た
す関数を作成すること.
① 最大値: int max( int *, int )
第1 引数: 配列アドレス 第2 引数: データ数 返り値: 最大値
② 最小値: int min( int *, int )
第1 引数: 配列アドレス 第2 引数: データ数 返り値: 最小値
③ 平均: float average( int *, int )
第1 引数: 配列アドレス 第2 引数: データ数 返り値: 平均値
④ 標準偏差: float std_dev( int *, int )
第1 引数: 配列アドレス 第2 引数: データ数 返り値: 標準偏差

というものです。こちらの問題について少々あつかましいお願いになってしまうんですが、
どなたかにサンプルプログラムを書いていただいてそのプログラムの分からないところについて
質問させていただくという形にはならないでしょうか?正直わかることが無く分からない所だらけなので
一度完成したプログラムを見てみたいと思ったんですがどうでしょうか?あつかましいお願いしてすいません。
よろしくお願いしますm(_ _)m

バグ

Re:1次元配列について

#2

投稿記事 by バグ » 18年前

:データ数を入力させる。(scanf関数でいけそうですね。)

:で得た数の領域だけint型でメモリを動的に確保する。

とりあえず、ここまで作ってみて下さい。教科書なり参考書なりを読めば必ず載っていますので頑張ってください。

自分でコーディングしなければ、絶対に理解できませんよ。他人のコードを見て分かった気になったとしても、身につかないですから。

管理人

Re:1次元配列について

#3

投稿記事 by 管理人 » 18年前

>サンプルプログラムを書いていただいてそのプログラムの分からないところについて、質問させていただくという形にはならないでしょうか?

このような勉強スタイルはこれから先、いつも出来るわけじゃないです。

いつも、誰かに完成品を作ってもらってから理解するという勉強スタイルをとっていたのではいつまでたっても自力で書けませんし、いつもそのように丁寧にコードを書いてくれる人がいるとは限りません。

これはコードを書いてあげることが面倒で言っているわけではないんです。質問してくださった日に、全てコードは書いてみました。

1つの関数に付き、4~5行で実装できるごく基本的な物でした。

前回の質問で関数の使い方について詳しくご説明しましたよね。

厳しいことを言うようですが、説明した文章をしっかり読んでいただいて、次に活かしていただかないと困ったさんの力にならないので。

どうか、自分の力で頑張ってみてください。

まず、複数回入力を受け付ける処理を作ってください。

次に、最大値を求めるプログラムを作ってみましょう。

次に・・

と少しずつ作ってみましょう。そのたびにあっているか、どうしたらいいか聞いてもいいですので、是非一から自分の力でやってみてください。

困ったさん

Re:1次元配列について

#4

投稿記事 by 困ったさん » 18年前

そうですよね。どうもすいませんm(_ _)m 自分の考えは浅はかでした。

プログラムの書き始めは

#include<stdio.h>
#define k (3)

int main(void){
int data[k];
int i,j;
for(i = 0 ; i < 3 ; i++)
{
printf("要素を入力 ->");
scanf("%d",&data);
}

という感じでいいんですか?

box

Re:1次元配列について

#5

投稿記事 by box » 18年前

> #define k (3)

3は半角にしてください。

> for(i = 0 ; i < 3 ; i++)

せっかくkを#defineしているので、
i < k
とする方がよいでしょう。
そうしておけば、配列の要素数を変更する際、
#defineのところだけを修正すればすみます。

> という感じでいいんですか?

よいと思います。

困ったさん

Re:1次元配列について

#6

投稿記事 by 困ったさん » 18年前

3はうっかりミスでした。わかりました。では、入力をしたので次は最大値とかですね。最大値はどうすれば求められるんでしょうか?

バグ

Re:1次元配列について

#7

投稿記事 by バグ » 18年前

OKです(^-^)
ただ、int型の変数であるjは未使用なので警告が出ると思います。消しておいた方がよいですよ。

次は最大値を求める関数の作成です。

int max(int *pData, int Val)
{
//ここに処理を書き込む
}

最大値の求め方で最も簡単な方法は、全ての組み合わせを調べる方法ですね。

データの個数分だけfor文でループさせ、*pDataと*(pData + n )の値を比較して、大きかった方を最大値格納用の変数に代入すれば、ループを抜けた時に最大値が求められるはずです。

管理人

Re:1次元配列について

#8

投稿記事 by 管理人 » 18年前

なかなか突っ込んだ解説が出来ずに、すみません。

そうそう、そうやって1つずつ解いていけばいつか必ず完成しますから。

もうちょっといいscanfの作り方を説明します。

こうすれば、入力された個数が判別できます。

入力された回数は不定ですよね?

ですから、何回入力が行われたか数えなければなりません。

EOFというものをご存知でしょうか?ctrl + Zを押すと入力はEOFとなります。

これが入力されるまで格納を続けてみます。
while(scanf("%d",&dat[n])!=EOF)
	n++;
これです。scanfで、EOFが入力されたと判定されるまで、nを増加させていきます。

dat配列にいれていくので、要素数nが入力回数となります。

EOFが入力されるとループを抜けます。



とりあえず、書式をフォーマットしたものを示しますので、これにそってやってみてください。
#include <stdio.h>
#include <math.h>

int min(int dat[/url],int n){
	int minium;//最小値を格納する変数

/*ここに最小値を求めるプログラム*/

	return minium;
}

int main(){
	int n=0,dat[1024];
	while(scanf("%d",&dat[n])!=EOF)
		n++;
	printf("最小値=%d\n",min(dat,n));
	return 0;
}
配列を動的に確保したほうがよりよいのでしょうが、難しくなるので、ちょっとそれは完成してから挑戦することにしましょう。

box

Re:1次元配列について

#9

投稿記事 by box » 18年前

> 最大値はどうすれば求められるんでしょうか?

プログラムとは関係なしに、手で求める場合を考えてみましょう。

ここに5枚のカードがあって、裏に数字が書いてあります。
最終的に、いちばん大きい数字のカードを箱に入れることにします。
1枚ずつカードをめくって、書いてある数字を順に見ていくと13, 29, 4, 35, 12でした。
さて、どれがいちばん大きい数字でしょうか?

【最大値を求める手順の例】
1)1枚目のカードをめくる。書いてある数字(13)のカードを、とりあえず箱に入れる。
2)2枚目のカードをめくる。書いてある数字(29)は、箱に入っているカードの数字(13)より大きい。
29のカードを箱に入れる。13のカードは箱から出す。
3)3枚目のカードをめくる。書いてある数字(4)は、箱に入っているカードの数字(29)より小さい。
箱の中のカードは29のまま。
4)4枚目のカードをめくる。書いてある数字(35)は、箱に入っているカードの数字(29)より大きい。
35のカードを箱に入れる。29のカードは箱から出す。
5)5枚目のカードをめくる。書いてある数字(12)は、箱に入っているカードの数字(35)より小さい。
箱の中のカードは35のまま。
6)すべてのカードをめくり終えた時点で箱に入っているカードの数字(35)が答え。

この手順をプログラムに落とし込めばよいです。
もちろん、他にも方法はあるでしょう。

困ったさん

Re:1次元配列について

#10

投稿記事 by 困ったさん » 18年前

わからないです…。ちょっと考えてみたんですけど最大値が要素の数になっちゃってます。数値の比較はどう書くのですか?

管理人

Re:1次元配列について

#11

投稿記事 by 管理人 » 18年前

boxさんのおっしゃる説明は非常にわかりやすいと思います。

処理の内容はboxさんがおっしゃった通りに実装するだけで完成します。

よくよく考えて見ましょう。

難しい。最初からどうせ考えてもわからない。となげやりになってしまっていませんか?

数値の比較はどうやるのかとおっしゃっていますが、前述の困ったさんの知識を拝見するとすぐにかけるはずです。

落ち着いて考えてみてください。

今必要なのは「比較の対象 と 最大値を入れる箱」です。つまりカードと箱が必要なんです。

具体的に言えば変数である(最小値を計算するのなら) dat[/url]とminimumです。

比較はなんら難しくないですよね。

if( x > y )

ですから。

これ以上言ってしまうと答えそのものを書いてしまうことになるので、boxさんのご回答とこの回答がギリギリのヒントです。

boxさんのおっしゃる事を最初からループ文で書くのが難しければ、1つずつ全部書き並べてもいいので、一度書いてみましょう。

ループ文は最初から書かずに、全部手書きしてから作り直すというのも手です。

困ったさん

Re:1次元配列について

#12

投稿記事 by 困ったさん » 18年前

途中経過です。

#include<stdio.h>
#define k (3)

int main(void){
int data[k];
int i,max;
for(i=0;i<k;i++)
{
printf("要素を入力 ->");
scanf("%d",&data);
}
max=max(&data,k);
printf("最大値は%d\n",max);
return 0;
}

int max(int *pData,int Val){
int max;
max=*pData;
for(Val=1;Val<3;Val++){
if(max< *(pData+Val))
max=*pData+Val;
}
return max;
}

こんな感じになっちゃったんですけど、「関数でないものを呼び出している」ってエラーが出ちゃって
どこがおかしいのでしょうか?

box

Re:1次元配列について

#13

投稿記事 by box » 18年前

> max=max(&data,k);

変数名maxと関数名maxは、別々の名前にしましょう。

max関数の第1引数が正しくありません。
配列dataのi番目の要素のアドレスではなく、配列data全体を渡しますので、
配列dataの先頭要素のアドレス、つまり&data[0]を渡します。
&data[0]は、単にdataと書くことができます。
配列名は、その配列の先頭要素のアドレスを表わすからです。

また、今回のようにmax関数の定義がmain関数の後ろにある場合、
max関数のプロトタイプ宣言が必要です。

max関数の中身も正しくありませんが、それはまた別途。

管理人

Re:1次元配列について

#14

投稿記事 by 管理人 » 18年前

前に私がお書きしたフォーマットは見ていただけました?

最大値を求めるプログラムのフォーマットを示します。
#include <stdio.h>
#include <math.h>

int max(int dat[/url],int n){
	int maximum;//最大値を格納する変数

/*ここに最大値を求めるプログラム*/

	return maximum;
}

int main(){
	int n=0,dat[1024];
	while(scanf("%d",&dat[n])!=EOF)
		n++;
	printf("最大値=%d\n",max(dat,n));
	return 0;
}
私が変数名をmaximumとしたのは、関数名maxと競合しないためです。
変数名・関数名を同じ名前にしてはいけません。

>任意個の整数データを入力させ

というからには、入力回数はdefineで決めない方がいいと思います。

配列の考え方をもう少し勉強してみてください。

http://www5c.biglobe.ne.jp/~ecb/c/c00.html

この辺の配列とかを読んでみてください。

datが示すものと、dat[0]が示すものと、&dat[0]がどう違うか、これだけ最小限理解出来るようになってください。

そうすれば、先ほどのような間違いはなくなると思います。

バグ

Re:1次元配列について

#15

投稿記事 by バグ » 18年前

>>管理人さん
int max(int dat[/url],int n){
管理人さんはこう記述するんですね~(^-^)

int max(int *pData,int Val){
私はこう記述するんですよ。

こんなところにも人の癖が出てなんだか楽しいですね。
っとと、スレの邪魔してはマズイですね(^_^;)

私も勉強を始めた頃、配列とポインタについては理屈を並べられてもなかなか理解できなかった覚えがあります。
ただ、C言語でプログラムを組む以上、絶対に避けて通れないものでもありますからねぇ…。
結局は自分でトライ&エラーを繰り返して感覚的に理解するのが結局は一番の近道なんじゃないかな…と思います。

>>困ったさん
困ったさんはやる気はあるみたいですし、↑の理解の為のお手伝いはできると思うので、応援しますよ(^-^)

管理人

Re:1次元配列について

#16

投稿記事 by 管理人 » 18年前

ポインタを意識せずにプログラムを紹介したい時は、なるべくdat[/url]このように書くようにしています。
ポインタがまだわからなければ、*datと書いても、これが配列を示すとはピンとこないと思いますので・・。

慣れてきたらバグさんの方がいいと思いますよ。名前からして受け取った配列だってことピンときますしね^^

困ったさん

Re:1次元配列について

#17

投稿記事 by 困ったさん » 18年前

管理人さんすいません。要素の数は任意というのは作成者が要素の数を自由に設定していいということなんです。だから今回は3にさせてもらいました。

困ったさん

Re:1次元配列について

#18

投稿記事 by 困ったさん » 18年前

最大値を求めるプログラムだけですけど書いてみました。

#include<stdio.h>
#define k (3)

int max(int*,int);
int main(void){
int data[k];
int i;
for(i=0;i<k;i++)
{
printf("要素を入力 ->");
scanf("%d",&data);
}
printf("最大値は%d\n",max(data,k));
return 0;
}

int max(int *pData,int Val){
int maximum;
maximum=*pData;
for(Val=1;Val<3;Val++){
if(maximum< *(pData+Val))
maximum=*(pData+Val);
}
return maximum;
}

これで一応最大値はもとめられるんですけど大丈夫でしょうか?

フリオ

Re:1次元配列について

#19

投稿記事 by フリオ » 18年前

 
 コードは、"pre"タグを使って字下げしたほうが見易いです。

 "value"という値がどういう意味を持つのか、なぜその値を引数にして、
関数にわたす必要があるのか、を考えてみてはどうでしょう。
 

box

Re:1次元配列について

#20

投稿記事 by box » 18年前

> maximum=*pData;
> for(Val=1;Val<3;Val++){
> if(maximum< *(pData+Val))
> maximum=*(pData+Val);
> }
> return maximum;
> }
>
> これで一応最大値はもとめられるんですけど大丈夫でしょうか?

大丈夫じゃないです。
max関数の第2引数Valについて、main関数からせっかく受け取った値
(今回は3)を、forループの入口で1に初期化してしまっています。
ループ制御用にVal以外の変数を用意して、
その変数が1からVal未満の場合にループを回すようにしてください。

また、上に引用した
*pData
*(pData+Val)
には別の書き方があることも覚えておくとよいでしょう。
*pDataはpData[0]と、
*(pData+Val)はpData[Va[/url]とも書けます。

引数のところの*pDataはpData[0]とは書けません、念のため。

困ったさん

Re:1次元配列について

#21

投稿記事 by 困ったさん » 18年前

 
>  コードは、"pre"タグを使って字下げしたほうが見易いです。

字下げはどのように使うのですか?また、それはコメント入力時に使うのですか?

>max関数の第2引数Valについて、main関数からせっかく受け取った値
>(今回は3)を、forループの入口で1に初期化してしまっています。
>ループ制御用にVal以外の変数を用意して、
>その変数が1からVal未満の場合にループを回すようにしてください。

そうですか。Valがデータの数だからメインでいうiと同じものだとか勘違いしてました。
仮にmax関数でnを使った場合、i→n,data→*pData,k→Valになるということでしょうか?
それともこの考えも間違っているのでしょうか??

同じ名前は使わないほうがいいということでしたが、例えば

int max(int *pData,int Val)
int min(int *mData,int m)

というように違う関数でも同じ名前は避けたほうがいいのですか?

box

Re:1次元配列について

#22

投稿記事 by box » 18年前

> 字下げはどのように使うのですか?また、それはコメント入力時に使うのですか?

ソースコードを入力する際、
if (n == 10) {
        /* 何か */
    } else {
        /* 別の何か */
    }
のようにして、見やすくするための字下げを行なっていますか?
ここの掲示板にソースコードを投稿する場合、コメント入力欄に
ソースの内容を貼り付け、その前後をHTMLタグの一種である
<pre>と</pre>とで囲みます。<と>は、ここでは便宜上
全角を使っていますが、実際は半角です。お間違えなきよう。

> そうですか。Valがデータの数だからメインでいうiと同じものだとか勘違いしてました。
> 仮にmax関数でnを使った場合、i→n,data→*pData,k→Valになるということでしょうか?
> それともこの考えも間違っているのでしょうか??

main関数でmax関数を呼び出しているのは

>printf("最大値は%d\n",max(data,k));

ここです。一方、max関数の本体は

>int max(int *pData,int Val){

で始まっています。呼出し側と本体側で、
引数の数と型が一致していなければなりません。
よって、今回の場合は、
・main関数のdataとmax関数のpData
・main関数のkとmax関数のVal
の2組が対応付いています。

今回、max関数でnという変数を使ったとして、それがmain関数の
何かの変数と対応付くことはありません。

> というように違う関数でも同じ名前は避けたほうがいいのですか?

いえ、そういうことはありません。
int max(int *pData, int Val)
int min(int *pData, int Val)
のように、異なる関数の中で同じ引数名や変数名を使うことができます。
変数名が同じでも、各々は別物です。
上手な例えかどうかはわかりませんが、
1年1組の鈴木さんと1年2組の鈴木さんは、同じ「鈴木」さんでも
クラスが違うので別人であるのと同じことです。

管理人

Re:1次元配列について

#23

投稿記事 by 管理人 » 18年前

>要素の数は任意というのは作成者が要素の数を自由に設定していいということなんです。だから今回は3にさせてもらいました。

これでは関数で要素数を受け取る意味が無いですがいいんでしょうか・・。
最初からdefineで決まっていて、その値を使うのでしたらこの受け取りは必要なくなってしまいます。
任意の数っていうのはそのときに変わるようにしたほうがいいんじゃないでしょうか。

なお、ポインタを表記するとどうしても難しく思えるので、私がお書きしたフォーマットに従ったほうがわかりやすいように思います・・。

dat[/url]で受け取ればポインタを意識しなくていいと思いますし、dat[0]とすれば配列の最初を示します。

>> というように違う関数でも同じ名前は避けたほうがいいのですか?

>1年1組の鈴木さんと1年2組の鈴木さんは、同じ「鈴木」さんでも クラスが違うので別人であるのと同じことです。

わかりやすいご説明ですね。
グローバル変数とローカル変数の違いを抑えておいてください。
グローバル変数はプログラムの最初、defineと同じ位置に書いて、どの関数でも宣言なしで使える変数です。
ローカル変数は、関数の中で宣言して使うもので、その関数の中でしか有効ではありません。
なお、関数名と変数名は異なるものにしてください。

box

Re:1次元配列について

#24

投稿記事 by box » 18年前

> これでは関数で要素数を受け取る意味が無いですがいいんでしょうか・・。

確かに、要素数を#defineしていたら引数にしなくても
かまわないことは確かですが、まあ今回はよいのではないでしょうか。

それよりも、
○最大値・最小値・平均値・標準偏差の求め方を理解する
○関数の引数の意味合いを理解する
○ローカル変数とグローバル変数の違いを理解する
といったことの方が大切でありましょう。

困ったさん

Re:1次元配列について

#25

投稿記事 by 困ったさん » 18年前

> これでは関数で要素数を受け取る意味が無いですがいいんでしょうか・・。

そう言われるとちょっと疑問に感じてきました。もし、入力時に任意個入力する場合は
管理人さんが書いてくれたフォーマット(EOFのやつ)を参考にすればいいんですよね?

平均値は入力したものを足して入力個数で割ればでますよね?最大値を参考に平均値も書いて
みたんですけど、平均値が0しか表示されなくてうまくいきません。平均値は最大値とかとは記述に
大きな違いがありますか?また、標準偏差はどうすれば求められるのですか?

バグ

Re:1次元配列について

#26

投稿記事 by バグ » 18年前

平均を求める関数はfloat型になっていますよね?
という事は計算する際に、受け取ったint型の変数をfloat型にキャストしてやらなければ、計算ができません。
キャストは分かりますか?

box

Re:1次元配列について

#27

投稿記事 by box » 18年前

> 平均値は入力したものを足して入力個数で割ればでますよね?最大値を参考に平均値も書いて
> みたんですけど、平均値が0しか表示されなくてうまくいきません。平均値は最大値とかとは記述に
> 大きな違いがありますか?また、標準偏差はどうすれば求められるのですか?

平均値を求める関数のコードを見せてください。
平均値の前に、最小値は求まりましたか?
標準偏差の求め方は、検索エンジンなどで調べてみてください。

困ったさん

Re:1次元配列について

#28

投稿記事 by 困ったさん » 18年前

> 平均を求める関数はfloat型になっていますよね?
> という事は計算する際に、受け取ったint型の変数をfloat型にキャストしてやらなければ、計算ができません。
> キャストは分かりますか?

int n=10;
float k;
k=(float)n;

みたいな書き方をするやつではなかったでしたっけ?

>平均値を求める関数のコードを見せてください。

最大値のプログラムをいじっただけなので、また例によって大きな間違いがあるんでしょうけど…。

float average(int *pData,int Val){
int ave,sum,n;
sum=*pData;
for(n = 1; n < Val ; n++){
sum += *(pData + n);
}
ave = sum/Val;
return ave;
}

今のところこうなっています。

>平均値の前に、最小値は求まりましたか?

最小値は不等号を逆にすればいいんですよね?てか、それで求められました。

ついでに・・・いまいちpreの使い方がわかりません。

box

Re:1次元配列について

#29

投稿記事 by box » 18年前

> 今のところこうなっています。

aveとsumをfloat型にしてください。

> ついでに・・・いまいちpreの使い方がわかりません。

ソースコードの行ごとに入れなくてもいいです。
<pre>
ソースコード全体
(何行でも)
</pre>
のように、ソースコード全体という具材を1回だけ
サンドイッチしてください。

困ったさん

Re:1次元配列について

#30

投稿記事 by 困ったさん » 18年前

最大値・最小値・平均値を求めるプログラムはこれで大丈夫ですか?
#include<stdio.h>
#define k (3)

int max(int*,int);
int min(int*,int);
float average(int*,int);

int main(void){
 int data[k];
 int i;
 for(i = 0; i < k; i++){
  printf("要素を入力 ->");
  scanf("%d",&data);
 }
printf("最大値は%d\n",max(data,k));
printf("最小値は%d\n",min(data,k));
printf("平均値は%f\n",average(data,k));
return 0;
}

int max(int *pData,int Val){
 int maximum,n;
 maximum = *pData;
 for(n = 1 ;n < Val; n++){
  if(maximum < *(pData+n))
  maximum = *(pData+n);
 }
 return maximum;
}

int min(int *pData ,int Val){
 int minimum,n;
 minimum = *pData;
 for(n = 1; n < Val; n++){
  if(minimum > *(pData+n))
 minimum = *(pData+n);
 }
 return minimum;
}

float average(int *pData,int Val){
 int n;
 float sum,ave;
 sum = *pData;
 for(n = 1; n < Val; n++){
  sum += *(pData + n);
 }
 ave = sum/Val;
 return ave;
}


どうでしょうか?これで大丈夫なら後は標準偏差だけですが、標準偏差についてちょっと調べなければ!です。

管理人

Re:1次元配列について

#31

投稿記事 by 管理人 » 18年前

標準偏差についてですが、平均を求める関数を利用するとスマートになるかもしれません。

wikiなんかで調べたら標準偏差の求め方はわかります。

よければ今までのプログラムで私が書いたものをみてみてください。考え方は全く同じです。
#include <stdio.h>
#include <math.h>

int min(int dat[/url],int n){
	int minium=dat[0];
	for(int i=0;i<n;i++)
		if(minium>dat)
			minium=dat;
	return minium;
}

int max(int dat[/url],int n){
	int maxium=dat[0];
	for(int i=0;i<n;i++)
		if(maxium<dat)
			maxium=dat;
	return maxium;
}

float average(int dat[/url],int n){
	float ave=0;
	for(int i=0;i<n;i++)
		ave+=(float)dat;
	return ave/(float)n;
}

int main(){
	int n=0,dat[1024];
	while(scanf("%d",&dat[n])!=EOF)
		n++;
	printf("最小値=%d\n最大値=%d\n平均=%f\n",min(dat,n),max(dat,n),average(dat,n));
	return 0;
}
入力が0回の時の条件分岐も余裕があればつけたほうが良いと思います。

困ったさん

Re:1次元配列について

#32

投稿記事 by 困ったさん » 18年前

私は結局こういうプログラムになりました。標準偏差は

√((各データの2乗の平均)-(各データの平均の2乗))

で求めていますが式は合っているのでしょうか?
#include<stdio.h>
#include<math.h>
#define k (3)

int max(int*,int);
int min(int*,int);
float average(int*,int);
float std_dev(int*,int);

int main(void){
 int data[k];
 int i;
  for(i = 0; i < k; i++)
  {
   printf("要素を入力 ->");
   scanf("%d",&data);
  }
 printf("最大値は%d\n",max(data,k));
 printf("最小値は%d\n",min(data,k));
 printf("平均値は%f\n",average(data,k));
 printf("標準偏差は%f\n",std_dev(data,k));
 return 0;
}

int max(int *pData,int Val){
 int maximum,n;
 maximum = *pData;
  for(n = 1 ;n < Val; n++){
   if(maximum < *(pData+n))
    maximum = *(pData+n);
  }
 return maximum;
}

int min(int *pData ,int Val){
 int minimum,n;
 minimum = *pData;
  for(n = 1; n < Val; n++){
   if(minimum > *(pData+n))
    minimum = *(pData+n);
  }
 return minimum;
}

float average(int *pData,int Val){
 float ave,sum;
 int n;
 sum = *pData;
  for(n = 1; n < Val; n++){
   sum += *(pData + n);
  }
 ave=sum/Val;
return ave;
}

float std_dev(int *pData,int Val){
 float sigma,dat,sum,ave;
 int n;
 sum = *pData;
  for(n = 1; n < Val; n++){
   sum += *(pData + n);
  }
 ave = sum/Val;
 dat = pow(*pData,2);
  for(n = 1; n < Val ; n++){
   dat += pow(*(pData + n),2);
  }
 sigma = sqrt((dat/Val) - pow(ave,2));
 return sigma;
}


これで完成といえるのなら、入力個数を任意にしたり、個数が0個の時のプログラムも考えてみたいと思います。あ、平均値や標準偏差のところでfloatにキャストしてないんですけど、キャストしないと正しい結果はえられないですよね?
ところで管理人さん。管理人さんのフォーマットは入力時にprintfが使われてなくて何も表示されない状態で入力待ちになっていますよね?これを例えば「要素を入力(C-zで入力終了)->」と表示して入力待ちにしたい場合はどう記述すればよいのでしょうか?ちょっとやってみたんですけど,どうにも正しい表示が行なわれなくて・・・。

管理人

Re:1次元配列について

#33

投稿記事 by 管理人 » 18年前

ただ前に書いたらいいだけではなくてですか?
printf("要素を入力(C-zで入力終了)-> ");
while(scanf("%d",&dat[n])!=EOF){
	n++;
}
ループさせて毎回書きたいのでしたらprintf文をループの中にも書いていただけたら毎回表示されます。

管理人

Re:1次元配列について

#34

投稿記事 by 管理人 » 18年前

後者判定したいなら
int n=-1,dat[1024];
	do{
		n++;
		printf("input ->");
	}while(scanf("%d",&dat[n])!=EOF);
このようにかけるでしょう。

管理人

Re:1次元配列について

#35

投稿記事 by 管理人 » 18年前

実行例
input ->1
input ->2
input ->3
input ->4
input ->5
input ->6
input ->^Z
最小値=1
最大値=6
平均=3.500000

管理人

Re:1次元配列について

#36

投稿記事 by 管理人 » 18年前

前にも言った事と重複しますが、pow関数に渡す引数の型に注目してください。

double pow(double x, double y);

float powf(float x, float y);

long double powl(long double x, long double y);

pow関数を使うにはdoubleで渡す必要があり、floatで渡すならpowf、int型で渡す関数はないので、

2は任意の型に変換しましょう。

困ったさん

Re:1次元配列について

#37

投稿記事 by 困ったさん » 18年前

> pow関数を使うにはdoubleで渡す必要があり、floatで渡すならpowf、int型で渡す関数はないので、

powやsqrtなどは引数の型によって記述が少し変わるんですね。これはmath.hを使う関数なら共通して
言える事なのですか?

> ループさせて毎回書きたいのでしたらprintf文をループの中にも書いていただけたら毎回表示されます。

すいません。ちょっとした記述ミスでした({}の付け忘れ)・・・。ちゃんとできました。
ありがとうございますm(_ _)m

管理人

Re:1次元配列について

#38

投稿記事 by 管理人 » 18年前

関数と言うものは渡す型と受け取る方は同じでないといけません。
intで受け取る関数なのにdoubleで渡してはいけませんし、このことはどの関数でも共通して言えることです。

manpageなどみてください。

http://www.linux.or.jp/JM/html/LDP_man- ... pow.3.html

関数には全て型があり、その仕様がちゃんとかかれていますので、これにそってください。

名前が変わることについても別にmathに限ったことでは無いと思います。
標準関数については、検索すれば見れますので一度確認してみてはいかがでしょうか。

管理人

Re:1次元配列について

#39

投稿記事 by 管理人 » 18年前

例えば、引数の数や型がかわると

scanf
int scanf(const char *format, ...)
scanf( ... ) は fscanf(stdin, ... ) と同じである.

fscanf
int fscanf(FILE *stream, const char *format, ...)
出力フォーマット format に従って stream から読み込む.

sscanf
int sscanf(char *s, const char *format, ...)
入力文字列が文字列 s から取られる以外は scanf と同じ.

似たような処理でもこのように名前も変わります。
名前が1文字でも違えば全く違う関数と同じ事なので、特に意識する必要はないかと思いますが。

困ったさん

Re:1次元配列について

#40

投稿記事 by 困ったさん » 18年前

理解を完璧にするには時間が少しかかりそうですけど、ちゃんと勉強してくだらないことで質問しないようにしたいです。
ありがとうございましたm(__)m

box

Re:1次元配列について

#41

投稿記事 by box » 18年前

> 最大値・最小値・平均値を求めるプログラムはこれで大丈夫ですか?

正しいプログラムの一例であるといえます。
一例といったのは、他にもいろいろな書き方があるからです。

box

Re:1次元配列について

#42

投稿記事 by box » 18年前

> 私は結局こういうプログラムになりました。標準偏差は

std_dev関数で、データの平均値を求める際は
average関数の戻り値を利用するとよいでしょう。
同じロジックを複数回書いてバグを発生させるより、
既存のロジックを使う方が安上がりです。

> キャストしないと正しい結果はえられないですよね?

float型のsumにint型の*pDataを代入する際、
自動的に型変換を行ないます。
sum = *pData;
と書いても
sum = (float) *pData;
と書いても同じです。

困ったさん

Re:1次元配列について

#43

投稿記事 by 困ったさん » 18年前

なんか本当にプログラムが出来上がったのが信じられないです。最初はこんなのわかんないよ~って感じで丸投げ投稿してたのに、少しずつ諦めずにやったら完成できちゃいました。これもみなさんが飽きずにどんなくだらないことにも答えてくれたおかげです。本当にありがとうございましたm(__)m このトピもすごく長くなってしまいましたね。その証拠にみなさんみたく答える側じゃないのに質問だけですごくポイントが貯まっちゃいました。なんかすいません…。
とにかくみなさん長いことお付き合いくださいましてありがとうございました。

フリオ

Re:1次元配列について

#44

投稿記事 by フリオ » 18年前

 
 "sqrtf" "sqrtl""powf""powl"が標準関数としてサポートされるのは C99 からで、
それ以前はあくまで各コンパイラの独自仕様になりますから使用する際には、
注意が必要です。
 

box

Re:1次元配列について

#45

投稿記事 by box » 18年前

人が書いたコードを単に読むだけではなくて、
ご自分で実際に書いてみる方が理解が進むことを
実感できたのでしたら、よかったです。

管理人

Re:1次元配列について

#46

投稿記事 by 管理人 » 18年前

少しずつやっていけば必ず出来ますよ♪
これからも頑張ってくださいね^^

閉鎖

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