• 締切済み

組み合わせ プログラミング

c言語についてです os linux コンパイラはgccです long fact2(int n,int m)を作成してfact2(n,m)を使って組み合わせを計算するプログラムを作れという問題で下記のように作りましたが コンパイルできません. エラーメッセージは 2-1.c:14: error: 関数 `fact2' への引数が少なすぎます 2-1.c:14: error: 関数 `fact2' への引数が少なすぎます 2-1.c:14: error: 関数 `fact2' への引数が少なすぎます です 関数のとこが違うと思うですが どうしたらいいのかわかりません それともなにか他のとこが違うのでしょうか? #include <stdio.h> long fact2(int,int); main() { int n, m; long c; printf(" nCm (n>m) \n"); printf("input n m ="); scanf("%d %d",&n, &m); c =fact2(n) / (fact2(m) * fact2(n-m)); printf("%dC%d = %ld\n",n,m,c); } long fact2(int n,int m) { int i; long c=1; for(i=1; i<=n; i++) c*=i; return(c); }

noname#74733
noname#74733

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

#1 の言うように, c =fact2(n) / (fact2(m) * fact2(n-m)); を c =fact2(n, 0) / (fact2(m, 0) * fact2(n-m, 0)); とでもすれば動きます. 「与えられた引数をすべて使わなければならない」という規則はないし. ま, はっきりいってこれは問題がよくないと思う. 「long fact2(int n,int m)を作成してfact2(n,m)を使って組み合わせを計算するプログラムを作れ」という問題からは「fact2 の仕様」が分からないんだよね.

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.4

>fact2の中身でもn,m2つ使おうとしたらどうやればいいのかわからなくなってしまって・・・ 課題では long fact2(int n,int m)を作成してfact2(n,m)を使って組み合わせを計算するプログラムを作れ と指示されています。 なので long fact2(int,int); と定義しなければなりません。 main関数からは c =fact2(n,m); という形で呼び出さなければいけません。 fact2関数は long fact2(int n,int m) {  return (nとmの2つの変数から、組み合わせ数「nCm」を計算する式); } と言う書き方をしないとなりません。 nとmの2つの変数からnCm計算する式は n! / (n-m)! / m! になります(ここは「n! / (m! * (n-m)!)」でも構わないが、本来の組み合わせ数の式は「(n! / (n-m)!) / m!」であるので、こちらの方が適切) Cコンパイラには階乗を演算する演算子はありませんから、階乗を返す関数が必要です。 階乗を返す関数は、質問者さんがもう作ってますから、そのまま流用します。 long fact(int x) {  int i;  long c=1;  for(i=1; i<=x; i++) c*=i;  return(c); } すると式 n! / (n-m)! / m! は fact(n) / fact(n-m) / fact(m) になります。 fact2関数の  return (nとmの2つの変数から、組み合わせ数「nCm」を計算する式); の所に、この式を書けば良い事になります。 --------------- 結論は 質問者さんは「順列組み合わせ関数であるfact2(n,m)を作れ」と言う課題で、一生懸命「階乗を返す関数」を作って、順列組み合わせの式をfact2関数に書かず、main関数の中に書いてた、と言う勘違いをしていた。 って事。

  • okg00
  • ベストアンサー率39% (1322/3338)
回答No.3

はい。勘違いです。 関数と引数の関係について復習する事をお勧めします。 http://www.kumei.ne.jp/c_lang/intro/no_03.htm 関数を呼び出す際にパラメータとして扱われるのが引数です。ここで、扱うパラメータを指定します。プログラム中で何種類のパラメータで引き渡すかではありません。 fact2(n) / (fact2(m) * fact2(n-m)); では個別にfact2(n)とfact2(m)とfact2(n-m)が計算されます。fact2(n-m)では先にn-mが計算され、その結果をfact2関数のパラメータとして呼び出します。 なお、先のn,mと long fact2(int n,int m) { int i; のn,mは別物です。仮引数と実引数の差です。一緒にしないでください。 http://www.cc.kyoto-su.ac.jp/~yamada/ap/parameter_argument.html >fact2の中身でもn,m2つ使おうとしたら 無理に2つを使う必要はありません。一度に一つしか使わないなら、一つだけで構いません。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

>c =fact2(n) / (fact2(m) * fact2(n-m));に引数が2こ入っていますがこれは私の勘違いでしょうか? はい。勘違いなさっています。 fact2(n):引数は1個(n) fact2(m):引数は1個(m) fact2(n-m):引数は1個(n-m) ところで、そもそもfact2は何をする関数でしょうか。 コードを見る限り、2個目の引数mを全く使っていませんね。 もし、fact2が階乗を求める関数であれば、引数は1個あればじゅうぶんなように思います。 2個目の引数が必要な理由は、私にはちょっとわかりません。

  • okg00
  • ベストアンサー率39% (1322/3338)
回答No.1

エラーメッセージの通りですね。 プロトタイプ宣言では >long fact2(int,int); とあり、引数を2つ指定していますが、 実際に使う場面では >c =fact2(n) / (fact2(m) * fact2(n-m)); 引数を1つしか渡していません。 引数の個数を合わせてください。 ※fact2の中身ではmを使っていないようですが...

noname#74733
質問者

補足

c =fact2(n) / (fact2(m) * fact2(n-m));に引数が2こ入っていますがこれは私の勘違いでしょうか? fact2の中身でもn,m2つ使おうとしたらどうやればいいのかわからなくなってしまって・・・

関連するQ&A

  • 困ってます…nCrを求めるC言語プログラミング

    nCr、つまりn個のうちr個を取り出すときの場合の数を求めるプログラミングを作りたいのですが、どうもうまくいきません。 関数combinationを作って求めるという指定もあり、自分で出来るとこまで作ってみたのですが訳がわからなくなってしまい、かなり困っています…; コンパイルは出来るのですが実行してもセグメントエラーが出るばかりで… すみませんがご指摘していただけないでしょうか…? #include<stdio.h> //階乗を計算する関数 int fact(int num){ int i; if(num < 0){ return -1; } else if(num == 0){ return 1; } else if(num == 1){ return 1; } else { i = num * fact(num - 1); return i; } } //コンビネーションを計算 int combination(int n, int r) { int fact(int num); int i; i=fact(n)/fact(r)/fact(n-r); return combination(n-1, r-1)-combination(n,r-1); } int main(void) { int n, r; while ( printf("n r を入力して下さい。"), scanf("%d%d", &n, &r) == 2 ) { printf("nCr(%d,%d)=%d\n", n, r, combination(n, r)); } return 0; }

  • 組合せ

    2個の整数m,n(m≧n)をキーボートから受け取って、m個の相異なる物の中からn個取り出す組合せの数を計算するプログラムを作っているんですが、下のプログラムだと、13の階乗でオーバーフローしてしまいました。combination関数を使わずに、13の階乗を計算したいのですが…。 13!/(k!(13-k)!)で、13!でオーバーフローなので、13!/k!=(k+1)×…×13を計算すればいいのは分かるのですが、どういう関数を定義すればいいのかわかりません。 ヒントやアドバイス頂けると、助かります。 よろしくお願いします。 #include <stdio.h> void main(void) {long m,n; long fact(long); while(scanf("%ld,%ld",&m,&n)!=EOF) printf("comb(%ld,%ld)=%ld\n",m,n, fact(m)/(fact(n)*fact(m-n))); } long fact(long k) {long i,f; f=1; for (i=1;i<=k;i=i+1) f=f*i; return(f); }

  • 組み合わせ

    n個の集合からp個を取る組み合わせの総数を出力するプログラムなんですが nCp=n!/p!(n-p)!という式を使い #include<stdio.h> int kaijo(int m); int comb(int n,int p); int main(void) { int i,j; printf("n="); scanf("%d",&i); printf("p="); scanf("%d",&j); printf("comb(%d,%d)=%d\n",i,j,comb(i,j)); } int kaijo(int m) { if(m>0) return(m*kaijo(m-1)); else return 1; } int comb(int n,int p) { if(n>0) return((n*kaijo(n-1))/(p*kaijo(p-1)*(n-p)*kaijo(n-p-1))); else return 1; } と書いてみたのですがこれではnが大きいとC言語のint型で扱える最大値を超えてしまい正しい結果が出力されません。  そこでint型を使ったままでnやpが大きい場合でもある程度出力できるようにしたいのですがどう改良したらよいのでしょうか? おそらくnCp=n*(n-1)*・・・*(n-p+1)/p!という式を使うのですがよく分かりません。よろしくお願いします。

  • プログラミングの変数について質問です。

    プログラミングの変数について質問です。 次のプログラミングは自分で書いたプログラムの一部です。 void inputmonster(int x[][3], struct monster monster) { int i, s, t, m, n; for(t = 0; t < 2; t++){ s = 0; while (s < 1){ printf("player%dは好きなモンスターを3つ選んでください\n\n", t+1); for (i = 0; i<3; i++){ printf("%d体目を選んでください。\n\n", i+1); for(m = 0; m < 5; m++) printf("%d, %s\n", m+1, monster[m].name); scanf("%d", &x[t][i]); printf("%d体目 : %s\n\n", i+1, monster[x[t][i]-1].name); } printf("これでよろしいですか?\n"); for(i = 0; i<3; i++) printf("%d体目 : %s ", i+1, monster[x[t][i]-1].name); printf("1、はい 2、いいえ\n"); scanf("%d", &n); if(n == 1) s = 1; else s = 0; } } } これをコンパイルすると次のようなエラーが表示されます。 monsterbattle.c: 関数 ‘inputmonster’ 内: monsterbattle.c:497:63: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません for(m = 0; m < 5; m++) printf("%d, %s\n", m+1, monster[m].name); ^ monsterbattle.c:499:45: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません printf("%d体目 : %s\n\n", i+1, monster[x[t][i]-1].name); ^ monsterbattle.c:503:68: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません for(i = 0; i<3; i++) printf("%d体目 : %s ", i+1, monster[x[t][i]-1].na me); どのように改変すればこのようなエラーを表示しないようにできるのでしょうか? 基本的な質問ではあると思いますが、是非教えていただけるとありがたいです。 よろしくお願いします。

  • 組み合わせ順列

    nCrを求める関数combination(n,r)をC言語で作りたいのですが、どうすればよいか教えてください。また、参考となるようなサイトを教えてください。僕の作った関数だと、すぐに桁あふれになってしまいます。そのことを考慮して、桁あふれにになりにくい関数もつくりました。これは パスカルの三角形の関係を使ったnCr=n-1Cr +n-1Cr-1の関係を使っての再帰関数です。しかし、これだと結果を出すのに時間がかかってしまいます。僕がつくった関数をいくつか出しておきますのでいい考えがあれば教えてください。64C32が高速に正確に出れれば最高です。 long combination(int n,int r) { int i, a, b; long c; if(r>n/2) r=n-r; a= n; b= 1; c= 1L; for(i=0 ;i< r ;i++){ c= c* a/ b; a--; b++; } return c; } これはすぐに桁あふれになってしまう。 long combination(int n,int r) { int i, a, b; double c; if(r>n/2) r=n-r; a= n; b= 1; c= 1.0; for(i=0 ;i< r ;i++){ c= c/b*a; a--; b++; } return (long)c; } これはcをdoubleにして計算する分、丸めこみが生じ誤差がでる。 long combination(int n,int r) { long c; if(r> n-r) r=n-r; if(r==0) return 1; else if(r==1) return n; else{ c= combination(n-1,r-1)+ combination(n-1,r); return c; } } これは誤差は出ず正確であるがいかんせん遅い!

  • C言語のプログラミングで困っています

    C言語を勉強しています。まだまだ初心者で分からないことだらけなのですが、今回はファイル入出力の部分が分からず苦戦しています。 『100個の実数が入った2つのテキストファイルから数値を読み込み、  絶対値を求めるなどの計算をする』プログラムを作成しているのですが、 コンパイルし実行すると強制終了してしまいます。 プログラムは、 void main(void) { FILE *fp; double c[50000];   double d[50000];   double e[50000]; int n = 0;   int m = 0;   int i = 0;   char fname[80];   char fname2[80]; printf("ファイル名 : ");    gets(fname); if((fp = fopen(fname, "r")) == NULL){ printf("ファイルがオープンできません\n"); exit(1); } printf("\n"); while (fscanf(fp,"%lf",&c[i])!=EOF){ printf("%3d : %3lf",++n,c[i]); printf("\n"); i++; } printf("\n"); i=0; n=0; printf("ファイル名 : ");    gets(fname2); if((fp = fopen(fname2, "r")) == NULL){ printf("ファイルがオープンできません\n"); exit(1); } printf("\n"); while (fscanf(fp,"%lf",&d[i])!=EOF){ printf("%3d : %3lf",++n,d[i]); printf("\n"); i++; } …(以下計算) のようになっています。 整数のデータで計算を行うと、正常に動くのですが…。 コンパイルしてもエラーが出ないので、どこが悪いのかわからず困っています。 どなたか教えていただけないでしょうか。お願いしますm(_ _)m

  • nCmの関数

    C言語で、nCmを(n-m+1/m)*nCm-1として再起を利用して計算する関数を作りたいです int comb1(int n, int m){ if(m==0) return1; else return /********/; } /********/この部分を上手に使えば、(n-m+1/m)*nCm-1の再起する関数として動くようなのですが分からずにいます 回答の分かる方、宜しくお願いいたします

  • 組み合わせ

    aに100、bに20や2を入力すると プログラムが停止します。 計算できるように御指摘お願いします。 以下のプログラムです。 #include<stdio.h> int factrical(int n){ if(n>0){ /*printf("%d\n",n);*/ return (n*factrical(n-1)); } else{ return(1);} } int combination(int n ,int r){ return(factrical(n)/(factrical(n-r)*factrical(r))); } int main (void){ int a,b,c; printf("二つの数を入力してください。\n"); do{ printf("大きい方の数を入力してください。\n"); scanf("%d",&a); scanf("%d",&b); }while(a<b); c=combination(a,b); printf("%d",c); return(0);}

  • プログラミング教えてください!!!お願いします。

    プログラミング教えてください!!!お願いします。 次の文が実行されると何がどのようにプリントされるか。何もプリントされない時は「なし」と記せ。 また、途中に「ブランク」が入る場合は、”b”と記せ。 (1) int func1(), func2(); int data = 100; main() { int w = 1; static x =10; printf("** %d, %d, %d\n" ,w,x,data); func1(); printf("** %d, %d, %d\n" ,w,x,data); } int func1(){ int w = 2; static int x = 20: printf("*** %d, %d, %d\n", w, x, data); x += 10; func2(); printf("*** %d, %d, %d\n" , w,x,data); x *= 2; data = data - x; } int func2() { int w = 3; static int x = 30; printf("**** %d, %d, %d\n" ,w,x,data); data -= x; } (2) int func1(char *, char *, char *); int func2(char *, char *, char *); main() { char sta[20], stb[20], stc[20], std[20]; int i=0; func1("abc","xyz",sta); printf("%d -- %s\n" ,++i,sta); func1("123","456",stb); printf("%d -- %s\n" ,++i,stb); func1(sta,stb,stc); printf("%d -- %s\n" ,++i,stc); func2(sta,stb,std); printf("%d -- %s\n" ,++i,std); } int func1(char *a, char *b, char *c){ while(*a) *c++ = *a++; while(*b) *c++ = *b++; * c = 0x00; } int func2(char *a, char *b, char *c){ int i = 0; while(*b){ if(i%2 == 0) *c++ = *a++; else *c++ = *b++; i++; } *c = 0x00; }

  • プログラミング 問題

    もともとの商品の値段が1000円を超えている場合は1割引する。1000円以下の場合はそのままである。まず商品の値段を引数に取り、割引後の値段を返す関数を書け。 次に、この関数を使って「最初に10回商品の値段を入力すると、それぞれに対して割引後の値段をまとめて表示する」というプログラムを書け。 ここまで出来ましたがそれ以上どうしてもわかりません。エラーも出ます 教えてくださいm(_ _ )m #include <stdio.h> double discount(double a); int main(void) { double i,c,n[10]; for(i=0; i<10; i++){ printf("price?"); scanf("%lf",&c); n[i]=discount(c); } for(i=0; i<10; i++){ printf("%f\n",n[i]); } return 0; } double discount(double a){ double b; if(a>1000){ b=a*0.9; }else{ b=a; } return b; }

専門家に質問してみよう