質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

805閲覧

有理数の掛け算の約分無しまでは実行できるが、約分まで考慮するとsegmentation faultになってしまう。

aoba-purines

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2022/04/10 14:44

構造体を用いて有理数型の掛け算をする関数mula、最大公約数を求める関数gcdを用いて、有理数型掛け算の結果を約分して返すプログラムを作成したのですが、実行するとsegmentation faultになってしまいます。

html

1#include<stdio.h> 2#include<stdlib.h> 3 4typedef struct { 5 int n, d; 6} rational; 7 8int gcd ( int a, int b ) 9{if(a == b){ 10 return a;} 11 else if(a > b){ 12 return gcd(a-b,a);} 13 else { 14 return gcd(a,b-a);} 15} 16rational setr(int n, int d) 17{ 18 rational z; 19 if (d == 0) { 20 fprintf(stderr, "Denominator must be nonzero.\n"); 21 exit(1); 22 } 23 z.n = n; 24 z.d = d; 25 return z; 26} 27 28void printr(rational z) 29{ 30 printf("%d/%d\n", z.n, z.d); 31} 32 33rational mulr(rational x, rational y) 34{ 35 int n = x.n * y.n; 36 int d = x.d * y.d; 37 int k = gcd(n,d); 38 rational z = setr(n/k, d/k); 39 return z; 40} 41 42void check4(int argc, char *argv[]) 43{ 44 rational x, y; 45 { 46 int a = atoi(argv[1]); 47 int b = atoi(argv[2]); 48 int c = atoi(argv[3]); 49 int d = atoi(argv[4]); 50 x = setr(a, b); 51 y = setr(c, d); 52 } 53 { 54 // mulr 55 rational z = mulr(x, y); 56 printr(z); 57 } 58 } 59int main(int argc, char *argv[]) 60{ 61 check4(argc, argv); 62 return 0; 63}

約分を考えない際には上手くいったので

int k = gcd(n,d); rational z = setr(n/k, d/k);

の箇所が間違っていると思います。しかしどう全体を訂正すれば良いのかわかりません。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/04/10 14:55

どのような値を入れたらその現象が発生するのでしょうか。 また、どこまで実行出来ていてその時の変数の値はどうなっているのかをお調べになったでしょうか。
aoba-purines

2022/04/10 15:07

どの値でも駄目でした。 最大公約数kで分母分子を割るという考えは間違っていないと思います。 kで割らない場合はどの値でも成功しました。
jimbe

2022/04/10 17:31 編集

> どの値でも駄目でした。 4 つの int 型を基に動作するプログラムの場合、int が 32bit として数の組み合わせは約 43 憶の 4 乗個存在します。 その全てで駄目だったのでしょうか。 プログラムの動作に対しましては推測で範囲を限定(もしくは拡張)しないほうが良いと思います。 例えば全部 0 を指定しても発生するのでしょうか。 発生するとすれば、setr 関数の if 文内で exit するまでの間に問題があることになります。 全部 1 では? 全部 -1 では? 正数・ゼロ・負数の組み合わせや約分が発生する場合・しない場合等でいくつかのテストパターンを作り、それぞれでどう動作するはずか、そして実際にはどう動作しているかを一つ一つ確認することで、バグを探し出せます。
aoba-purines

2022/04/11 01:32

有難うございます。 やってみます。
guest

回答3

0

ベストアンサー

gcd を以下のようにしてください。

C

1int gcd(int a, int b) 2{ 3 int i; 4 int min = a; 5 if (a > b) min = b; 6 for (i = min; i > 0; i--){ 7 if ((a % i == 0) && ( b % i == 0)) return i; 8 } 9 return 1; 10} 11

失礼しました。こちらのようなやりかたをしたかったのですね。
最大公約数の求め方

C

1int gcd(int a, int b) 2{ 3 int min = a; 4 int max = b; 5 int x; 6 if (a < 1 || b < 1) return 1; 7 if (a == b) return a; 8 if (a > b){ 9 min = b; 10 max = a; 11 } 12 x = max % min; 13 if (x == 0) return min; 14 return gcd(min,x); 15} 16

投稿2022/04/10 22:13

編集2022/04/11 01:15
tatsu99

総合スコア5424

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aoba-purines

2022/04/11 01:29

解決しました。 有難うございました。
guest

0

C言語のコードを書くなら、デバッグできる環境を整えましょう。
Eclipseや、WindowsならVisualStudioなど。
コードの任意の場所で実行を止め、変数のナカミを見ることができます。そこから1行づつ実行して、コードの流れを見れるようになります

投稿2022/04/10 22:00

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

a > bのときに、gcd(a-b,a)としているのが原因ではないでしょうか? gcd(a-b,b)なら、確実に元の組み合わせよりもより小さな整数の組み合わせになりますが、gcd(a-b,a)だと大きな数の組み合わせになり、無限ループとなる可能性がありそうです。

投稿2022/04/10 15:32

majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問