🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

2回答

1838閲覧

printfを加えたら値が変わってしまう

langhtorn

総合スコア105

C

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

0グッド

0クリップ

投稿2020/12/21 06:09

編集2020/12/21 06:10

###実現したいこと
点が多角形に含まれるか判定するプログラムを作っています。
含まれないとき0,含まれたら1を出力したいです。
###問題点
if(flag==1){ //交差するの上の今コメント文にしている、printf("flag=%d\n",flag);を入れるか入れないかで値が変わってしまう。
例えば、以下の出力結果で0.585022 0.479889 0を見る。ここでは0が出力されている。

4 0.1 0.1 0.9 0.1 0.9 0.9 0.1 0.9 0.100000 0.100000 0.900000 0.100000 0.900000 0.900000 0.100000 0.900000 0.100000 0.100000 0.001282 0.563599 0 0.193329 0.808746 1 0.585022 0.479889 0 0.350311 0.895966 1 0.822845 0.746613 0 0.174133 0.858948 1 0.710510 0.513550 0 0.304016 0.015015 1 0.091431 0.364471 0 0.147339 0.165924 1

しかし、flagの一文をコメントではなく出力するようにすると0.585022 0.479889の判定は1になっている。単位正方形を考えると0.585022 0.479889は含まれるので1になるはず。。。どうしてprintf一つで変わってしまうのでしょうか。

4 0.1 0.1 0.9 0.1 0.9 0.9 0.1 0.9 0.100000 0.100000 0.900000 0.100000 0.900000 0.900000 0.100000 0.900000 0.100000 0.100000 0.001282 0.563599 flag=0 flag=0 flag=1 flag=1 0 0.193329 0.808746 flag=0 flag=0 flag=1 flag=0 1 0.585022 0.479889 flag=0 flag=1 flag=0 flag=0 1 0.350311 0.895966 flag=0 flag=0 flag=1 flag=0 1 0.822845 0.746613 flag=0 flag=1 flag=0 flag=0 1 0.174133 0.858948 flag=0 flag=0 flag=1 flag=0 1 0.710510 0.513550 flag=0 flag=1 flag=0 flag=0 1 0.304016 0.015015 flag=1 flag=1 flag=0 flag=0 0 0.091431 0.364471 flag=0 flag=0 flag=1 flag=1 0 0.147339 0.165924 flag=0 flag=0 flag=1 flag=0 1

###コード

C

1#include<stdio.h> 2#include<stdlib.h> 3#include<time.h> 4 5//左折なら1,右折なら-1を返す関数 6int ccw(double p0_x,double p0_y,double p1_x,double p1_y,double p2_x,double p2_y) 7{ 8 double p=(p1_x-p0_x)*(p2_y-p0_y)-(p1_y-p0_y)*(p2_x-p0_x); 9 //printf("p=%f\n",p); 10 int flag=0; 11 if(p>=0){ 12 flag=1; 13 }else{ 14 flag=-1; 15 } 16 return flag; 17} 18 19 20//交差判定する関数 21int intersect(double p0_x,double p0_y,double p1_x,double p1_y,double q0_x,double q0_y,double q1_x,double q1_y) 22{ 23 int ppq1,ppq2; 24 ppq1=ccw(p0_x,p0_y,p1_x,p1_y,q0_x,q0_y); 25 ppq2=ccw(p0_x,p0_y,p1_x,p1_y,q1_x,q1_y); 26 int qqp1,qqp2; 27 qqp1=ccw(q0_x,q0_y,q1_x,q1_y,p0_x,p0_y); 28 qqp2=ccw(q0_x,q0_y,q1_x,q1_y,p1_x,p1_y); 29 30 int flag; //判定 31 if(ppq1!=ppq2){ 32 if(qqp1!=qqp2){ //両方成り立つとき交差する 33 flag=1; 34 } 35 }else{ //交差しない 36 flag=0; 37 } 38 39 return flag; 40} 41 42int main(void) 43{ 44 int n; //多角形の頂点数 45 scanf("%d",&n); 46 double x[10],y[10]; 47 int i; 48 for(i=0;i<n;i++){ 49 scanf("%lf %lf",&x[i],&y[i]); 50 } 51 printf("\n"); 52 53 for(i=0;i<n;i++){ 54 printf("%f %f\n",x[i],y[i]); 55 } 56 printf("%f %f\n",x[0],y[0]); 57 printf("\n"); 58 printf("\n"); 59 60 //多角形の外部の点 61 double x0=2.0; 62 double y0=2.0; 63 int flag,j; 64 double qx,qy; 65 int cnt=0; 66 for(i=0;i<10;i++){ 67 qx=((double)rand()+1.0)/((double)RAND_MAX+1.0); 68 qy=((double)rand()+1.0)/((double)RAND_MAX+1.0); 69 printf("%f %f ",qx,qy); 70 cnt=0; 71 for(j=0;j<n;j++){ 72 if(j==n-1){ 73 flag=intersect(x[j],y[j],x[0],x[0],x0,y0,qx,qy); 74 }else{ 75 flag=intersect(x[j],y[j],x[j+1],y[j+1],x0,y0,qx,qy); 76 } 77 //printf("flag=%d\n",flag); 78 if(flag==1){ //交差する 79 cnt++; 80 } 81 } 82 //printf("cnt=%d\n",cnt); 83 //printf("i=%d\n",i); 84 if(cnt%2==0){ //交差する辺の数が偶数個 85 printf("0\n"); 86 }else{ //奇数個 87 printf("1\n"); 88 } 89 } 90}

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

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

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

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

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

ozwk

2020/12/21 06:19

なにか警告出てません?
guest

回答2

0

ベストアンサー

ppq1!=ppq2 かつ qqp1==qqp2のときflagはどうなるでしょうか

C

1 int flag; //判定 2 if(ppq1!=ppq2){ 3 if(qqp1!=qqp2){ //両方成り立つとき交差する 4 flag=1; 5 } 6 }else{ //交差しない 7 flag=0; 8 } 9 10 return flag;

多分そのあたりでコンパイラが警告を出していると思います。

C

1warning: variable 'flag' is used uninitialized whenever 'if' condition is false

とかなんとか。

で、初期化してない変数の中身を使おうとすると未定義動作になります。
未定義動作なので、何が起こるかわかりません。

今回は未定義動作により、たまたま「printfの有無で動作が変わるコード」になりました。


ちなみにpaiza.ioで実行してみたところ、

ppq1!=ppq2 かつ qqp1==qqp2のとき、未初期化の変数flagが返される。
未定義動作は起こるはずはないので、qqp1==qqp2はありえない。
したがって、if(qqp1!=qqp2)は省略してif(ppq1!=ppq2)だけ判定する。
という愉快な最適化をカマしてくれました。

投稿2020/12/21 06:29

編集2020/12/21 06:36
ozwk

総合スコア13551

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

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

langhtorn

2020/12/23 03:54

なるほど、そのようなことが、、、。解決しました。ありがとうございます。
guest

0

動作確認はしていませんし、これが原因かはわかりませんが、問題点をひとつ指摘します。
intersect関数でflagが初期化されないパターンがあります。
ppq1!=ppq2でqqp1==qqp2のとき。

c

1 int flag; //判定 2 if(ppq1!=ppq2){ 3 if(qqp1!=qqp2){ //両方成り立つとき交差する 4 flag=1; 5 } 6 }else{ //交差しない 7 flag=0; 8 }

こんな感じにしてみたらどうでしょうか。

c

1 int flag = 0; //判定 2 if(ppq1!=ppq2 && qqp1!=qqp2){ //両方成り立つとき交差する 3 flag=1; 4 }

投稿2020/12/21 06:32

ttyp03

総合スコア17000

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

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

langhtorn

2020/12/23 03:54

解決できました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問