参照渡し

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

参照渡し

#1

投稿記事 by yuu » 13年前

再帰関数の答えを参照渡ししたいのですが
うまくできません
どうしたら
いいでしょうか?

コード:

#include<stdio.h>

int fact(int *n);
int main(void)
{
	int n;
	printf("Input Integer=");
	scanf("%d",&n);
	fact( &n);
	printf("Factorial=%d\n",n);
	return 0;
}

int fact(int *n)
{   
	if(n==0)return(1);
	*n=*n*fact(n-1);	
}

一応このプログラムなんですけど
よくわかりません

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 参照渡し

#2

投稿記事 by YuO » 13年前

fact関数の,
  • nの役割
  • 入力としての*nの意味
  • 出力としての*nの意味
  • 戻り値の意味
をちゃんとコメントに書いてみると,頭の中が整理できるかと思います。
これらがちゃんと整理できないまま作ろうとしているために,
yuu さんが書きました:よくわかりません
となっているのだと思います。

そして,このままの関数仕様で作れなくもないですが,入力と出力の引数を分離するよう入れた方が作りやすいと思います。

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

Re: 参照渡し

#3

投稿記事 by non » 13年前

私も方法を思いつかない。
そもそも、参照渡しでやれっていう課題なの?
non

yuu

Re: 参照渡し

#4

投稿記事 by yuu » 13年前

そうですけど

できないですね

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

Re: 参照渡し

#5

投稿記事 by non » 13年前

条件としては
int fact(int *n)
このプロトで作りなさいって事なんですね。
値は返して良い。
non

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 参照渡し

#6

投稿記事 by YuO » 13年前

yuu さんが書きました:できないですね
自動変数を1個使えばできます。
できないとする根拠はなんなのでしょうか。
# できないと言い切るのは非常に難しいことだと思いますが。

というか,

コード:

int fact(int n, int *result);
とすれば綺麗になるのに,

コード:

int fact(int *n);
に固執する必要も無いと思いますが……。

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

Re: 参照渡し

#7

投稿記事 by non » 13年前

nを参照渡しにしろっていう課題だと思いますよ。
nを値渡しにしちゃ拙いのでは?
non

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 参照渡し

#8

投稿記事 by beatle » 13年前

non さんが書きました:nを参照渡しにしろっていう課題だと思いますよ。
nを値渡しにしちゃ拙いのでは?
「答えを参照渡ししたい」と書いてありますから、参照にするのはresultでいいのではないでしょうか。

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

Re: 参照渡し

#9

投稿記事 by non » 13年前

確かに一番最初に
>再帰関数の答えを参照渡ししたいのですが
って書いてあるなぁ。答えならnではないのか・・・
本人のRESを待ちましょう。
non

たかぎ
記事: 328
登録日時: 14年前
住所: 大阪
連絡を取る:

Re: 参照渡し

#10

投稿記事 by たかぎ » 13年前

もしかして、こういうことでは?

コード:

#include<stdio.h>
#include<limits.h>

int fact(int *n)
{
     if (*n == 0)
     {
          *n = 1;
     }
     else
     {
          int nn = *n - 1;
          if (fact(&nn) || INT_MAX / *n < nn)
               return -1;
          *n *= nn;
     }
     return 0;
}

int main(void)
{
     int n;
     scanf("%d", &n);
     if (fact(&n) == 0)
          printf("Factorial=%d\n", n);
     else
          puts("overflow");
}
最後に編集したユーザー たかぎ on 2011年12月15日(木) 16:26 [ 編集 1 回目 ]

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

Re: 参照渡し

#11

投稿記事 by non » 13年前

なるほどですね。思いつきませんでした。戻り値を、正常終了かに使うところなど、プロはさすがだと思います。
non

RYO

Re: 参照渡し

#12

投稿記事 by RYO » 13年前

質問者さんの書かれたfact()の中身はかなり変なことやってますね
何をやりたいのかは何となくわかるのですが…
fact()をポインタ変数の値渡しをやめて、参照渡しで作り直せってことではないでしょうか?

yuu

Re: 参照渡し

#13

投稿記事 by yuu » 13年前

遅くなりました
nの値を参照渡しにより渡すみたいです
本当は再帰関数で作るものですが
たぶん
違う方法で参照渡しするのだと思い
作り変えてみましたが
うまくいきません

コード:

#include<stdio.h>

void fact(int& n);
int main(void)
{
	int n;
	printf("Input Integer=");
	scanf("%d",&n);
	fact( n);
	printf("Factorial=%d\n",n);
	return 0;
}

void fact(int& n)
{   
        int i,c;
	c=n;
	for(i=0;n>i;i++)
	{
		n*=(c-i);
	}
}

nの階乗の値が返されません
どうしたらいいのでしょうか?

yuu

Re: 参照渡し

#14

投稿記事 by yuu » 13年前

遅くなりました
nの値を参照渡しにより渡すみたいです
本当は再帰関数で作るものですが
たぶん
違う方法で参照渡しするのだと思い
作り変えてみましたが
うまくいきません

コード:

#include<stdio.h>

void fact(int& n);
int main(void)
{
	int n;
	printf("Input Integer=");
	scanf("%d",&n);
	fact( n);
	printf("Factorial=%d\n",n);
	return 0;
}

void fact(int& n)
{   
        int i,c;
	c=n;
	for(i=0;n>i;i++)
	{
		n*=(c-i);
	}
}

nの階乗の値が返されません
どうしたらいいのでしょうか?

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 参照渡し

#15

投稿記事 by YuO » 13年前

どうしたらいいかの前になぜそうなったかを考えましょう。
それがわからなければ,どうすればいいのかはわかりません。

なぜそうなったかを調べる手段の一つは,丹念にコードを追うことです。
このサイズなら机上でも十分だと思いますが,
実際にデバッガ上で動かして一行ずつ進めながら変数の値を確認していく,というのは基本的なデバッグ方法です。

とりあえず机上デバッグ。
3を入力した場合に,fact関数は,
  • 18行目 : i = 0, n = 3, c = 3, n > i : true
  • 20行目 : i = 0, c = 3, c - i = 3, n = 9
  • 18行目 : i = 1, n = 9, c = 3, n > i : true
  • 20行目 : i = 1, c = 3, c - i = 2, n = 18
  • 18行目 : i = 2, n = 18, c = 3, n > i : true
  • 20行目 : i = 2, c = 3, c - i = 1, n = 18
  • 18行目 : i = 3, n = 18, c = 3, n > i : true
  • 20行目 : i = 3, c = 3, c - i = 0, n = 0
  • 18行目 : i = 4, n = 0, c = 3, n > i : false
というループの過程を経ます。

これを見れば,問題点がわかると思います。
まず,20行目での計算がおかしいことがすぐにわかります。
最初にc - iが3であるのがそもそもおかしいわけですが,単純にiが0の時にnに2をかければよいとばかりに

コード:

n *= c - i - 1;
とするとi=c-1の時にnが0になり正しい結果がでません。
これらは,i=0ではなくi=1から始めることで解決します。
次に,ループの継続条件のうちのnがどんどん変化していることがわかります。
階乗の計算では計算回数は変化しないはずなので,nが変化するのもおかしいことになります。
これは,継続条件をnではなくcを元にすることで,解決します。

2点をまとめて,

コード:

for (i = 1; i < c; ++i)
{
  n *= c - i;
}
これを追うと,
  • 1行目 : i = 1, n = 3, c = 3, i < c : true
  • 3行目 : i = 1, c = 3, c - i = 2, n = 6
  • 1行目 : i = 2, n = 6, c = 3, i < c : true
  • 3行目 : i = 2, c = 3, c - i = 1, n = 6
  • 1行目 : i = 3, n = 6, c = 3, i < c : false
となり,少なくともnが3の場合において正しい結果が得られていることがわかります。

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

Re: 参照渡し

#16

投稿記事 by non » 13年前

yuu さんが書きました: nの値を参照渡しにより渡すみたいです
本当は再帰関数で作るものですが
そのものずばりを、たかぎさんから作っていただいたのですから、お礼ぐらい言っときなさいよ。
その上で、再帰はまだ理解できないから、再帰を使わずに使ってみたいってお願いする。
スルーするのは、マナーとしてなっていない。
non

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

Re: 参照渡し

#17

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

yuu さんが書きました:再帰関数の答えを参照渡ししたいのですが
つまりこういうことですか?

コード:

#include<stdio.h>
 
int fact(int& n);
int fact2(int n);
int main(void)
{
    int n;
    printf("Input Integer=");
    scanf("%d",&n);
    fact( n);
    printf("Factorial=%d\n",n);
    return 0;
}
 
int fact(int& n)
{
    n=fact2(n);
    return 0;
}

int fact2(int n) 
{
    if(n<=1)return 1;
    return n*fact2(n-1);
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

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