関数の定義について

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

関数の定義について

#1

投稿記事 by yozakaru » 12年前

はじめまして。自分は大学生なのですが関数の宣言がわからなくて困っています。
自分なりに調べて理解したつもりなのですがプログラムがうまくできません。
下記のプログラムは自由落下の時間と高さと速度を0~15秒ごとに表示するプログラムです。
C言語は始めて1ヶ月程度です。OSはLinuxだと思います。(WindowsにXmingというソフトでLinuxをやってます)

コード:

#include <stdio.h>

int kspeed(int m, int n);
int kheight(int m, int n);

#define T 15
#define G 9.8

main()
{
	int i,j,k;
	
	for(i=0;i<=T;++i){
		j=kspeed(G,i);
		k=kheight(G,i);
		printf("%.1f %.1f %.1f\n",i,j,k);
	}
}

int kspeed(int base, int n)
{
	int i,v;
	v=0;
	
	for(i=0;i<=n;++i)
	v=base*i;
	return n;
}

int kheight(int base, int n)
{
	int i,h;
	h=1500;
	
	for(i=0;i<=n;++i)
	h=-base*i*i/2.0;
	return h;
}
フォーラムを見て書きましたがミスなどあったらすいません。

non
記事: 1097
登録日時: 15年前

Re: 関数の定義について

#2

投稿記事 by non » 12年前

関数の宣言がわからないとのことですが、宣言はこれで間違っていないと思います。

問題があるとすれば、
プログラムの中身は見ていませんが、27行で nを返しているのが意味がないかと。
折角、計算したvを返すのでは?
non

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

Re: 関数の定義について

#3

投稿記事 by box » 12年前

yozakaru さんが書きました:

コード:

#define G 9.8
加速度定数を実数(浮動小数点数)として扱おうとされているようですので、
yozakaru さんが書きました:

コード:

int kspeed(int base, int n)
int kheight(int base, int n)
baseがint型なのはまずいと思います。
yozakaru さんが書きました:

コード:

	int i,j,k;
		printf("%.1f %.1f %.1f\n",i,j,k);
書式文字列(%.1f)と変数の型(int)が食い違っている箇所があります。
おそらく、秒数は整数、速度と高さは浮動小数点数にしたいのではないか、と想像しています。
int型:%d
double型:%.1f
のように、変数の型と書式文字列とを統一しましょう。

ついでに…。
速度や高さを表わすための変数名として、jやkが本当に適切かどうか、やや疑問があります。
もっとそれらしい名前を付ける方が、後で見たときにすぐわかるのではないか、と思います。
yozakaru さんが書きました:

コード:

	int i,v;
vは浮動小数点数なのでありましょう。
yozakaru さんが書きました:

コード:

	for(i=0;i<=n;++i)
	v=base*i;
vを計算する際に毎回上書きしていて、残るのはbase * nだけです。つまり、この2行は

コード:

    v = base * n;
という1行と全く同じことをしているに過ぎません。本当にそういうことがしたいのでしょうか。
yozakaru さんが書きました:

コード:

	return n;
nをreturnするのがまずいであろうことは、他の回答者さんからのご指摘のとおりです。
yozakaru さんが書きました:

コード:

	int i,h;
hは浮動小数点数なのでありましょう。
yozakaru さんが書きました:

コード:

	h=1500;
この初期化は、結局無意味になっています(理由は後述)。
yozakaru さんが書きました:

コード:

	for(i=0;i<=n;++i)
	h=-base*i*i/2.0;
hを計算する際に毎回上書きしていて、残るのは-base * n * n / 2.0だけです。
1500という初期値とは無関係になっています。
つまり、この2行は

コード:

    h = -base * n * n / 2.0;
という1行と全く同じことをしているに過ぎません。本当にそういうことがしたいのでしょうか。

関数の定義の仕方から派生して、コードの中身でおかしいと思える点にまで言及しました。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: 関数の定義について

#4

投稿記事 by box » 12年前

kspeed関数とkheight関数におけるループの必要性については、
そもそも、main関数で
yozakaru さんが書きました:

コード:

	for(i=0;i<=T;++i){
0秒から15秒までループしているのに、どうしてkspeed関数とkheight関数においても
yozakaru さんが書きました:

コード:

	for(i=0;i<=n;++i)
	for(i=0;i<=n;++i)
ループしなければならないかがよくわかりません。

この回答も、「関数の定義」というご質問のタイトルとは直接関係はありませんが、
「正しい実行結果を得るためにここは直した方がいいであろう」という趣旨のもとに回答しています。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

yozakaru
記事: 14
登録日時: 12年前

Re: 関数の定義について

#5

投稿記事 by yozakaru » 12年前

たくさんの回答ありがとうございます。
皆さんの回答を参考に作ってみましたが小数点定義しているのになぜかVとHが小数点切り捨てで表示されてしまいます。

コード:


#include <stdio.h>

#define T 15
#define G 9.8

main()
{
	int i;
	double t,V,H;
	
	for(i=0;i<=T;i++){
		t=i;
		V=kspeed(G,i);
		H=kheight(G,i);
		printf("%.1f(s) %.1f(ms) %.1f(m)\n",t,V,H);
	}
	return i;
}

int kspeed(double base, int n)
{
	int i;
	double v,t;
	v=0;
	
	for(i=0;i<=n;++i)
	
	v=base*i;
	return v;
}

int kheight(double base, int n)
{
	int i,t;
	double h;
	
	for(i=0;i<=n;++i)
	h=1500-(base*i*i/2.0);
	return h;
}
あと、回答の中でいくつか間違ってるではなくおかしいという点がありましたがこれは学校で習ったプログラムを参考にして作ったためです。
自分は下記のプログラムを参考に上記のプログラムを作りました。

コード:

#include <stdio.h>

int power(int m, int n);

main()
{
	int i,j,k;
	
	for(i=0;i<10;++i){
		j=power(2,i);
		k=power(-3,i);
		printf("%2d %4d %6d\n",i,j,k);
	}
}

int power(int base, int n)
{
	int i,p;
	
	p=1;
	
	for(i=0;i<n;++i)
	p=p*base;
	
	return p;
}
フォーラムを見てて思ったのですがこれはマルチポストになってしまうんでしょうか?

usao

Re: 関数の定義について

#6

投稿記事 by usao » 12年前

とりあえず指摘されているいくつかの間違いについてはそのまま残っているようですが,

>小数点切り捨て
については,関数の戻り値を整数型に指定しているから でしょう.

usao

Re: 関数の定義について

#7

投稿記事 by usao » 12年前

おっと… 「関数の定義の方法」が質問内容みたいなので,それに即した答え方に直します.

(1)return で返したいデータの型に合わせて,関数を定義する必要があります.
 今回の例で言えば,double型な計算結果をreturnで返したいのだから,
kspeed() (kheight()も同様) の定義は

コード:

    double kspeed( double base, int n ){ ... }
のようにすべきです.
 今回示されたコードでは 戻り値の型が int になってしまっているため,
結果として,計算結果を整数に丸めた値が返されてしまっています.

(2)関数を使用する箇所よりも前に 関数の宣言 が必要です.
(最初のコードではあったけど,今回のではなくなってしまっているので 念のための指摘.)
関数の宣言は,単に 定義から{ }の部分を取り去ったものを 末尾に ; を付けて書けばよいです.
 今回は main() の中で kseed() が使われているので,

コード:

double kspeed( double base, int n );

int main()
{ ... }
のように,main()よりも前に関数の宣言を書きます.

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

Re: 関数の定義について

#8

投稿記事 by box » 12年前

yozakaru さんが書きました: フォーラムを見てて思ったのですがこれはマルチポストになってしまうんでしょうか?
同じ内容の質問を、「ほぼ同じタイミングで、別の掲示板に」投稿していると、
マルチポストとなります。
今回のご質問がそれに該当するかどうかは、私が別の掲示板を参照していないので、
わかりません。

ところで、老婆心ながら…。
変数名baseとかnとかいうのは、それを使っている関数が「べき乗を求めるもの」だから
そういう風になっているのですよね。
速度とか高さとかを求めるための関数においては、やはりそれらしい変数名を付ける方が、
その関数で何をしているかがよくわかると思います。
もし、「引数が2個だったら、何でもかんでもbaseとnにしておけばいい」とお考えでしたら、
それはちょっと違うような気がします。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

yozakaru
記事: 14
登録日時: 12年前

Re: 関数の定義について

#9

投稿記事 by yozakaru » 12年前

皆さんありがとうございました。
おかげで問題点は多少あるものの欲しい結果を得られるプログラムになりました。
問題点はこれからC言語を学んでいきなおそうと思います。

コード:

#include <stdio.h>
 
#define T 15
#define G 9.8

double kspeed(double gravity, int n);
double kheight(double gravity, int n);
 
main()
{
    int i,t;
    double V,H;
    
    for(i=0;i<=T;i++){
        t=i;
        V=kspeed(G,i);
        H=kheight(G,i);
        printf("%d(s) %.1f(ms) %.1f(m)\n",t,V,H);
    }
    return i;
}
 
double kspeed(double gravity, int n)
{
    int i;
    double v,t;
    v=0;
    
    for(i=0;i<=n;++i)
    v=gravity*i;
    return v;
}
 
double kheight(double gravity, int n)
{
    int i,t;
    double h;
    
    for(i=0;i<=n;++i)
    h=1500-(gravity*i*i/2.0);
    return h;
}
またつまずいてしまったら質問しに来るので、その時はアドバイスお願いします。

non
記事: 1097
登録日時: 15年前

Re: 関数の定義について

#10

投稿記事 by non » 12年前

最低でも、29行と39行のforはなくしましょうよ。みっともないから。

コード:

double kspeed(double gravity, int second)
{
    return gravity*second;
}
 
double kheight(double gravity, int second)
{
    return 1500.0-(gravity * second * second / 2.0);
}
non

閉鎖

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