• ベストアンサー

因数分解プログラム(C言語)について(3)

つづきです /*求めた最大公約数で約分*/ if(*flag == 1){ *d = *m1 / *i; *e = *n1 / *i; } else{ printf("約分できません。\n"); *d = *m1; *e = *n1; } return 0; } int yakubun2(int *m2,int *n2,int *min2,int *flag,int *i,int *f,int *g) { /*最大公約数を見つける*/ if(*m2 < *n2){ *min2 = *m2; } else{ *min2 = *n2; } *flag = 0; for(*i = min2; *i > 0; *i--){ if(*m2 % *i == 0){ if(*n2 % *i == 0){ *flag = 1; break; } } } /*求めた最大公約数で約分*/ if(*flag == 1){ *f = *m2 / *i; *g = *n2 / *i; } else{ printf("約分できません。\n"); *f = *m2; *g = *n2; } return 0; } /*因数分解の結果を表示*/ int output(int *d,int *e,int *f,int *g) { printf("(%dχ-%d)(%dχ-%d)",*d,*e,*f,*g); return 0; } 関連URL:http://www.okweb.ne.jp/kotaeru.php3?q=474597

  • 1724
  • お礼率57% (39/68)

質問者が選んだベストアンサー

  • ベストアンサー
noname#30727
noname#30727
回答No.6

>それから、変数iとflag以外にも あとは、min1 と min2 だけでしょうか。 課題という事なので、プログラムが正しく動いているかどうかは試していませんが、全体を見て気になった事を・・・ yakubun1 と yakubun2 は同じ内容なので1つにまとめた方がいいです。これについては、bunkai1 と bunkai2 にも同じことが言えます。 1つにまとめると、試行錯誤している段階での修正量が減り、修正ミスも減ります。そして、C 言語の関数への理解度が高い事をアピールできます。 私の場合、ポインタを使って値を返す時、その変数を前に持ってくる事が多いですが、決まりというわけではないです。 yakubun(&d, &e, m1, n1); yakubun(&f, &g, m2, n2); void yakubun(int *rm, int *rn, int m, int n) { int i; int flag; int min; /* 以下省略 */ }

1724
質問者

お礼

お陰様で、まとまりのあるプログラムになりました。 ありがとうございました。

その他の回答 (6)

  • jmh
  • ベストアンサー率23% (71/304)
回答No.7

> pは、どのようにプログラムで記述すればいいのですか? aX^2+bX+c=p(qX-r)(sX-t) の右辺を展開、 係数比較で、a=pqsを得ます。つまりp=a/q/sです。 c.f. 469180 の /* 割り切れるはず */ のところ。 ただし「割り切れるはず」かどうかに自信がなければ、割る前に調べた方がよいです。

1724
質問者

お礼

お陰様で無事できました。 ありがとうございました。

  • jmh
  • ベストアンサー率23% (71/304)
回答No.5

前回は、特に指摘しなかったのですが、 普通、6X^2+28X+16を因数分解すると、  2(X+4)(3X+2) ですよね? 一般に、aX^2+bX+cがもし因数分解できれば、  p(qX-r)(sX-t) の形になると思います。 つまり、最後の printf は、   printf("%d(%dX-(%d))(%dX-(%d))", ...); だと思いますよ。

1724
質問者

補足

jmhさん、アドバイスありがとうございます。 確かにおっしゃられた通りです。 直したプログラムで6X^2+28X+16を因数分解したら、 (X+4)(3X+2) になってしまいました。 pは、どのようにプログラムで記述すればいいのですか? 今一、ピンときません。 よろしかったら、ご教授ください。お願いします。

noname#30727
noname#30727
回答No.4

#1, #2 の方の回答とも関連しますが、 プロトタイプ宣言→ int judge(int *,int *,int *); 呼び出し→ judge(&a,&b,&c); 関数の定義→ int judge(int *a,int *b,int *c,float *D) になっているので、コンパイルが通ってしまったとしても、D が不定になります。 #3 の方の回答への補足ですが、 >for(*i = *min2; *i > 0; *i--){ *i-- は演算子の優先度から、(*i)-- としないと目的の結果にはならないので、このあたりは注意が必要です。 ポインタがよくわからないということですが、必要のないポインタを乱用していることが原因です。 関数 judge を例に、普通の呼び出し方を考えてみましょう。 /*因数分解できるか判断する関数*/ float judge(int a,int b,int c) { float D; D = b * b - 4 * a * c; if(D > 0 || D ==0){ printf("判別式は条件を満たしました。\n因数分解を行います。\n"); } else if(D < 0){ printf("判別式はD < 0であるため、因数分解できません。\n"); exit(1); } return D; } int main(void) { ... D = judge(a, b, c); ... } ポインタは必要のないときには使わない方が誰にとっても見やすいです。 関数 main の中で全ての変数を定義するようなやりかたは良くないので、その関数だけで必要な変数は、その関数で定義するようにします。 関数 input などは、入力された値3つを main に返す必要があるから、今のままでいいのですが、特に返す値の無い関数は、戻り値の型を void としたほうが良いでしょう。

1724
質問者

補足

皆さん、アドバイスどうもありがとうございます。 inthefloiさんのアドバイスを参考にして 前よりはプログラムが良くなりました。 しかし、まだ不具合がある感じです。 それから、変数iとflag以外にも ローカル変数でもプログラムに支障がない変数 (ポインタである必要がない変数)を 教えては頂けないでしょうか? お願いします

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.3

アルゴリズムは見ていませんが、ポインタを見たところ... (2)の for(*i = min1; *i > 0; *i--){ は for(*i = *min1; *i > 0; *i--){ (3)の for(*i = min2; *i > 0; *i--){ は for(*i = *min2; *i > 0; *i--){ だと思います。 ちなみに素因数分解のプログラムは http://www.okweb.ne.jp/kotaeru.php3?q=429203 の#4にあります。こちらも参考にしてはどうでしょう

1724
質問者

お礼

nitscapeさん、ありがとうございました。 参考にさせていただきました。

  • MovingWalk
  • ベストアンサー率43% (2233/5098)
回答No.2

とりあえず気づいたところ。 (2)の判別式の判定に、*D でなく D を使っているところ。 *D<0 でも終了しないので、*q = sqrt(*D); で落ちるでしょうね。 環境がわかりませんが、デバッガを使うようにしてください。 そうすれば、どこがおかしいかトレースできます。 頑張って下さい。

1724
質問者

補足

MovingWalkさん、ありがとうございます。 おっしゃられた通りでした。

  • uyama33
  • ベストアンサー率30% (137/450)
回答No.1

if(D > 0 || D ==0){ printf("判別式は条件を満たしました。\n因数分解を行います。\n"); } else if(D < 0){ ここは、 *D = (float)((*b) * (*b)) - (4 * (*a) * (*c)); if(*D > 0 || *D ==0){ printf("判別式は条件を満たしました。\n因数分解を行います。\n"); } else if(*D < 0){ ではないでしょうか? printf

1724
質問者

お礼

uyama33さん、ありがとうございます。 参考にさせていただきました。

関連するQ&A

  • 因数分解プログラム(C言語)について(2)

    つづきです /*因数分解できるか判断する関数*/ int judge(int *a,int *b,int *c,float *D) { *D = (float)((*b) * (*b)) - (4 * (*a) * (*c)); if(D > 0 || D ==0){ printf("判別式は条件を満たしました。\n因数分解を行います。\n"); } else if(D < 0){ printf("判別式はD < 0であるため、因数分解できません。\n"); exit(1); } return 0; } /*因数分解をする関数*/ int bunkai1(int *a,int *b,int *q,int *n1,int *m1,float *D) { *q = sqrt(*D); *n1 = -(*b) + *q; *m1 = 2 * (*a); return 0; } int bunkai2(int *a,int *b,int *q,int *n2,int *m2,float *D) { *q = sqrt(*D); *n2 = -(*b) - *q; *m2 = 2 * (*a); return 0; } /*約分を行う関数*/ int yakubun1(int *m1,int *n1,int *min1,int *flag,int *i,int *d,int *e) { /*最大公約数を見つける*/ if(*m1 < *n1){ *min1 = *m1; } else{ *min1 = *n1; } *flag = 0; for(*i = min1; *i > 0; *i--){ if(*m1 % *i == 0){ if(*n1 % *i == 0){ *flag = 1; break; } } } つづく 関連URL:http://www.okweb.ne.jp/kotaeru.php3?q=474593

  • 因数分解プログラム(C言語)について(1)

    ”因数分解を行うプログラムについて”の質問と同じ者です。 みなさんのご回答を参考にして、作ってみたのですが、 ポインタとかの使い方などがわからず、実行すると、 不正な処理を行ったので終了しますとなってしまいます。 どなたか、具体的にどこが悪いのか、 そしてどのように直せば正しく実行されるのか、 教えて下さい。お願いします。 以下↓がプログラムです。 800文字以上のため二つに分割しました。 #include <stdio.h> #include <math.h> #include <process.h> /*関数プロトタイプ宣言*/ int input(int *,int *,int *); int judge(int *,int *,int *); int bunkai1(int *,int *,int *,int *,int *,float *); int bunkai2(int *,int *,int *,int *,int *,float *); int yakubun1(int *,int *,int *,int *,int *,int *,int *); int yakubun2(int *,int *,int *,int *,int *,int *,int *); int output(int *,int *,int *,int *); /*関数の呼び出し*/ int main(void) { int a,b,c,q,n1,m1,min1,flag,i,d,e,m2,n2,min2,f,g; float D; input(&a,&b,&c); judge(&a,&b,&c); bunkai1(&a,&b,&q,&n1,&m1,&D); bunkai2(&a,&b,&q,&n2,&m2,&D); yakubun1(&m1,&n1,&min1,&flag,&i,&d,&e); yakubun2(&m2,&n2,&min2,&flag,&i,&f,&g); output(&d,&e,&f,&g); return (0); } /*数値入力関数*/ int input(int *a,int *b,int *c) { printf("a*x^2+b*x+c=0で,a,b,cを入力して下さい。\n"); printf("a="); scanf("%d",a); printf("b="); scanf("%d",b); printf("c="); scanf("%d",c); if(*a == 0){ printf("a = 0なので因数分解できません。\n"); exit(1); } return 0; } つづく

  • C言語

    ストップウォッチの一時停止の機能をもつプログラムを作成しているのですが、上手く動作しません。 (一時停止し、再開してもその状態から再開できない状態) #include <windows.h> #include <mmsystem.h> #include <stdio.h> #include <conio.h> #pragma comment(lib, "winmm.lib") int main(void) { int command;//キーボード入力の文字判別用変数 int quit_flag = 1;//プログラム終了フラグ 0で停止 int c_flag = 0;//カウント状態取得用フラグ 1:カウント中,0:停止中 int h,m,s,ms;//左から,時間,分,秒,ミリ秒 int b,c,d,e; int a; int f,g,i; DWORD start,cur; printf("使い方:小文字の's'でカウントスタート.カウント中,小文字の's'で停止.次の's'でまた0からスタート\n"); printf("使い方:どんな状態でも小文字の'r'でカウントリセットして停止\n"); printf("使い方:qでプログラム終了\n\n"); printf("使い方:tを押すと一時停止.一時停止中,tで計測再開\n"); h=m=s=ms=0; b=c=d=e=0; while(quit_flag != 0)//quit_flagが0以外ならループ { while(!_kbhit())//何かキーが押されるまでループ { if(c_flag != 0)//c_flagが0以外であればカウント中ということ. { h=m=s=ms = timeGetTime() - start; b=h/3600000; c=(m/60000)%60; d=(s/1000)%60; e=ms%1000; cur=timeGetTime(); ms=(cur-g); f=ms; } printf("%02d:%02d:%02d:%03d\r",b,c,d,e); } command=_getch();//ループを抜けるために押されたキーの内容をcommandに代入. if(command=='s' && c_flag == 0) { printf("\n計測開始\n"); c_flag = 1; start = timeGetTime() ; h=m=s=ms=0; } else if(command=='t' && c_flag != 0) { printf("\n一時停止\n"); c_flag = 0; a=c_flag; //計測開始時にtを押すとバグが発生するため } else if(command=='t' && a==0) { printf("\n計測再開\n"); c_flag = 1; f=timeGetTime(); } else if(command=='s') { printf("\n計測中止\n"); c_flag = 0; } else if(command=='r') { printf("\nカウンタリセット,停止\n"); c_flag = 0; h=m=s=ms=0; } else if(command=='q') { printf("\n終了\n"); quit_flag = 0; } else if(command=='l' && c_flag==1) { c_flag=0; printf("\nラップ\n"); printf("%02d:%02d:%02d:%03d\n",h/3600000,(m/60000)%60,(s/1000)%60,ms%1000); c_flag=1; } } return 0; } 差分をとれば良いと聞いたのですが、どのようにとれば良いか全く分からなくて困っています。 ソースコードを修正または適宣追加をしてくだされば幸いです。

  • C言語の配列の使い方について質問です。

    以下のプログラムを配列を使って見やすくしたいのですが、どのように作ったら良いでしょうか? 宜しくお願いします。 #include<stdio.h> int main(void) { int a, b, c, d, e, f, g, h, i, j, k, l, m ,n, o; /*5段目の処理*/ for(a = 1; a <= 15; a++) { for(b = 1; b <= 15; b++) { if(a == b) continue; for(c = 1; c <= 15; c++) { if(a == c || b == c) continue; for(d = 1; d <= 15; d++) { if(a == d || b == d || c == d) continue; for(e = 1; e <= 15; e++) { if(a == e || b == e || c == e || d == e) continue; // printf("%d %d %d %d %d\n", a, b, c, d, e); ////4段目//// if(a>b){ f=a-b; } else if(a<b){ f=b-a; } if(b>c){ g=b-c; } else if(b<c){ g=c-b; } if(c>d){ h=c-d; } else if(c<d){ h=d-c; } if(d>e){ i=d-e; } else if(e<d){ i=e-d; } // printf(" %d %d %d %d \n", f, g, h, i); /////3段目//// if(f>g){ j=f-g; } else if(f<g){ j=g-f; } if(g>h){ k=g-h; } else if(g<h){ k=h-g; } if(h>i){ l=h-i; } else if(h<i){ l=i-h; } // printf(" %d %d %d \n", j, k, l); /////2段目//// if(j>k){ m=j-k; } else if(j<k){ m=k-j; } if(k>l){ n=k-l; } else if(k<l){ n=l-k; } // printf(" %d %d \n", m, n); /////三段目///// if(m>n){ o=m-n; } else if(m<n){ o=n-m; } // printf(" %d \n", o); if(a != b != c != d != e != f != g != h != i != j != k != l != m != n != o){ printf("%d %d %d %d %d\n", a, b, c, d, e); printf(" %d %d %d %d \n", f, g, h, i); printf(" %d %d %d \n", j, k, l); printf(" %d %d \n", m, n); printf(" %d \n", o); } } } } } } }

  • C言語

    ストップウォッチの一時停止の機能およびラップ機能をもつプログラムを作成しているのですが、上手く動作しません。 (一時停止し、再開してもその状態から再開できない状態) (ラップのほうはスピリットで出力されてしまう) #include <windows.h> #include <mmsystem.h> #include <stdio.h> #include <conio.h> #pragma comment(lib, "winmm.lib") int main(void) { int command;//キーボード入力の文字判別用変数 int quit_flag = 1;//プログラム終了フラグ 0で停止 int c_flag = 0;//カウント状態取得用フラグ 1:カウント中,0:停止中 int h,m,s,ms;//左から,時間,分,秒,ミリ秒 int b,c,d,e; int a; int f,g,i; DWORD start,cur; printf("使い方:小文字の's'でカウントスタート.カウント中,小文字の's'で停止.次の's'でまた0からスタート\n"); printf("使い方:どんな状態でも小文字の'r'でカウントリセットして停止\n"); printf("使い方:qでプログラム終了\n\n"); printf("使い方:tを押すと一時停止.一時停止中,tで計測再開\n"); printf("使い方:lを押すとラップをとる.\n"); h=m=s=ms=0; b=c=d=e=0; while(quit_flag != 0)//quit_flagが0以外ならループ { while(!_kbhit())//何かキーが押されるまでループ { if(c_flag != 0)//c_flagが0以外であればカウント中ということ. { h=m=s=ms = timeGetTime() - start; b=h/3600000; c=(m/60000)%60; d=(s/1000)%60; e=ms%1000; cur=timeGetTime(); ms=(cur-g); f=ms; } printf("%02d:%02d:%02d:%03d\r",b,c,d,e); } command=_getch();//ループを抜けるために押されたキーの内容をcommandに代入. if(command=='s' && c_flag == 0) { printf("\n計測開始\n"); c_flag = 1; start = timeGetTime() ; h=m=s=ms=0; } else if(command=='t' && c_flag != 0) { printf("\n一時停止\n"); c_flag = 0; a=c_flag; //計測開始時にtを押すとバグが発生するため } else if(command=='t' && a==0) { printf("\n計測再開\n"); c_flag = 1; f=timeGetTime(); } else if(command=='s') { printf("\n計測中止\n"); c_flag = 0; } else if(command=='r') { printf("\nカウンタリセット,停止\n"); c_flag = 0; h=m=s=ms=0; } else if(command=='q') { printf("\n終了\n"); quit_flag = 0; } else if(command=='l' && c_flag==1) { c_flag=0; printf("\nラップ\n"); printf("%02d:%02d:%02d:%03d\n",h/3600000,(m/60000)%60,(s/1000)%60,ms%1000); c_flag=1; } } return 0; } 差分をとれば良いと聞いたのですが、どのようにとれば良いか全く分からなくて困っています。 上記のソースコードを基に適宣追加をしてくだされば幸いです。

  • c言語 

    答えを0にするこまち算のプログラムを組んでみたのですが、ここからどうしても進まなくなってしまいました。 自分ではいけるかなと思ったのですが、9-8-7+65-4321=9など答えがありえない数になってしまいます。 どこがいけないか教えてください。むしろ最初から組み直した方がよいのでしょうか… #include <stdio.h> int cul(); int num[9] ={9,8,7,6,5,4,3,2,1}; int total;/**/ int kigou[8]={0,0,0,0,0,0,0,0}; int main(){ for(kigou[0]=0;kigou[0]<3;kigou[0]++){ for(kigou[1]=0;kigou[1]<3;kigou[1]++){ for(kigou[2]=0;kigou[2]<3;kigou[2]++){ for(kigou[3]=0;kigou[3]<3;kigou[3]++){ for(kigou[4]=0;kigou[4]<3;kigou[4]++){ for(kigou[5]=0;kigou[5]<3;kigou[5]++){ for(kigou[6]=0;kigou[6]<3;kigou[6]++){ for(kigou[7]=0;kigou[7]<3;kigou[7]++){ keisan(); } } } } } } } } return 0; } int keisan(){ int n =0; int flag = 0; int t = 0; int i = 0; total = num[0]; /* for (n=0;n<9;n++) printf("kigou[%d] == %d",n,kigou[n]);確かめ*/ for(;n<8;n++){ if(kigou[n] == 0 && n == 0){ total = total * 10 + num[n+1]; for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ total = total * 10 + num[n+flag+1]; } n = n + flag; } flag=0; if(kigou[n]!= 0){ for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ t = num[n+1] * 10 + num[n+flag+1]; } n = n+ flag; total = total + t; } } /*0になる計算式の表示*/ kigou[8]=2;/*表示しないために空白を入れる*/ if(total==0){ for(i=0;i<9;i++){ printf("%d",num[i]); if(kigou[i]==0) printf("+"); if(kigou[i]==1) printf("-"); if(kigou[i]==2) printf(""); } printf("=%d\n",total); } return 0; }

  • c言語

    int kexnsakusuu(int n[30], int c[30],int g){ int y = 0; int h = 0; int flag = 0; int flag_1; int i=1; int u; while(c[i]>0){ h++; u = 0; flag_1=0; while(n[u]>0 && flag_1==0){ if(abs(n[u] - c[i]) <= g){y++;flag_1++;}; u++; } i++; } if(y == h)flag = 1; return flag; } n[30]に12 18 3 3 0 0 0 0 以下0 c[30]に3000 12 3 0 0 0 0 以下0 c[1] c[2]とn[]の絶対値が2以下(gは2)で調べたいのですが、上記だとf‘lagは1を返したいです。 9000件のn[]を調べると誤動作があるみたいです。

  • C言語のソートプログラム

    学校でプログラミングの課題が出たので自分のパソコンに Microsoft Visual C++ 2010 Express をインストールして作ってみました。 それが以下のプログラムです。 これは任意の値nを入力してa[n]までの配列をつくり それを降順に並び替えるものです。 #include <stdio.h> #define N 10000 int main(){ int a[N],i,j,max,min,n,temp; n=0; printf("n="); scanf("%d",&n); if(N<n){ return 0; } else if(n<=0){ return 0; } else if(n<=N){ for(i=0;i<n;i++){ printf("a[%d]",i); scanf("%d",&a[i]); } max=min=a[0]; for(i=1;i<n;i++){ if(max<a[i]){ max=a[i]; } else if(min>a[i]){ min=a[i]; } } printf("a[i]のソート結果\n"); for(i=0;i<n;i++);{ for(j=i+1;j<n;j++){ if(a[i]<a[j]){ temp=a[i]; a[i]=a[j]; a[j]=temp; } } } for(i=0;i<n;i++){ printf("a[%2d]=%d\n",i,a[i]); } printf("Max=%d\n",max); printf("Min=%d\n",min); } } これを実行すると 最初に入力した配列の順番のまま表示されてしまいます。 例えば n=4 a[0]7 a[1]4 a[2]6 a[3]1 a[i]のソート結果 a[0]7 a[1]4 a[2]6 a[3]1 のようにです。 しかしプログラミング上では for(i=0;i<n;i++);{ for(j=i+1;j<n;j++){ if(a[i]<a[j]       temp=a[i];       a[i]=a[j];            a[j]=temp;        }        }        } のようにiとjを比較して a[0]がa[1]より大きければa[0]とa[1]を交換する。 あとはa[0]とa[2], a[0]とa[3]...a[3]とa[4]まで for文の続く限り繰り返すように書いたはずです。 まだ勉強し始めた私にはどこが間違っているのか分からないので 分かる方はご指摘をお願いします。

  • C言語のプログラムについて

    三角形を判定するプログラムを作ったのですが直角三角形ができるはずがないのに直角三角形の判定が出てしまいます。簡単なことなのかもしれませんが自分ではわからなくなってしまったのでご指摘してもらいたいです。 #include<stdio.h> void tri(int x,int y,int z) { if((x*x==y*y+z*z)||(y*y==x*x+z*z)||(z*z==x*x+y*y)) { printf("これは直角三角形です。"); printf("これは三角形です。"); }else if((x+y>=z)||(x+z>=y)||(y+z>=x)) { printf("これは三角形ではありません。"); }else{ printf("これは三角形です。"); } } int main(void) { int e1,e2,e3; printf("3辺を入力してください"); scanf("%f,%f,%f",&e1,&e2,&e3); tri(e1,e2,e3); return(0); }

  • C言語で分からないところがあるのですが……

    C言語で分からないところがあるのですが…… すみません。C言語の課題で分からないところがあり、質問しに来ました。 ユーザから数を受けて、そこまでのフィボナッチ数列を表示させるというプログラムです。 下のソースコード(でいいんですよね?)は正しいやつです。 for文を使って、繰り返しの作業を行うことに成功しましたが、doとwhileに書き換える作業がうまくできません。 どなたか助けてください。 #include<stdio.h> fib(int n) { if(n == 1)return(1); else{ if(n == 2) return (1); else return fib(n-1) + fib(n-2); } } main() { int n, i ; printf("INPUT the number. : "); scanf("%d",&n); for(i=1; i<=n; i++){ printf("F%d = %d\n",i, fib(i)); } }

専門家に質問してみよう