• 締切済み

プログラム

以前ファイルからXとYの値だけ取り出し図形を作る質問をした者ですが void Ctest::OnOK() { FILE *fp; char *str,buf[1000];     char buf3[100],*s3; char buf4[100],*s4; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; CDC *v; GetDC(); MoveTo(0,0); LineTo(atof(buf3),atof(buf4)); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } でコンパイルはできるのですが直線の作図がされません。 どこが間違ってるのでしょうか。VC+6.0のMFC使ってます

  • zaqwe
  • お礼率15% (19/123)

みんなの回答

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.6

データの値域と描画する範囲はどの程度なのでしょう? 1000x1000画素の中に ±10の値域を持つデータを小数点以下2位までを使って描画したいってことなら LineToの引数を (int)atof(buf3)*100 などといった具合に下駄を履かせてやれば良いでしょう

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.5

あー、なるほど、座標に小数以下も使いたいって話ですか。 であればそれは#3でも言われるとおり「無理」ですね。 まず、MFCのLineTo()のプロトタイプは BOOL CDC::LineTo(int x, int y) もしくは BOOL CDC::LineTo(POINT point) です。 http://msdn.microsoft.com/ja-jp/library/wzc1344s.aspx で、POINTは struct POINT { LONG x; LONG y; } です。 http://msdn.microsoft.com/ja-jp/library/8kk2sy33.aspx 見ての通りすべて整数型であり、小数を扱うことはできません。 #2でも言いましたが、小数を渡そうとしても勝手に整数(int)に変換され、小数以下は切り捨てられます。 従って、関数へ渡す前段階で小数値が問題なく取れていたとしても無意味な訳です。 ただ、線描が出来ない理由は別なところにあるようです。 > buf3の中身は"-12.04" > buf4の中身は"-7.01" 最初のv->MoveTo(0, 0)は描画領域の左上に移動しますが、ここからマイナスの座標となると、さらに左上で描画領域の外になります。 buf3、buf4(終点座標)を正の値になるようにして試してください。

  • arain
  • ベストアンサー率27% (292/1049)
回答No.4

http://okwave.jp/qa4511580.html から移動したようなので、こっちに。 なぜ数値の取り出しにピリオドも含めていたのかの理由については、 No.1の >この時点では文字列として扱われるのでatofで数字に変換する >XとY座標は浮動少数も扱うのでdouble型にしたい。 で納得しました。 で問題のほう。 No.3より >ファイルからの読み込みじゃなく >入力打ちなら浮動少数でも表示できるので >そんなことは無いと思いますが・・・ ファイルだろうが手入力だろうが、全く一緒です。 LineTo()はどのAPIを使用していますか? No.3氏の推測のとおり >BOOL LineTo(int nXEnd , int nYEnd); であれば、絶対にできていません。 >入力打ちなら浮動少数でも表示できるので この「表示」とは、まさかprintf("%f")ではないですよね? 変数の型が片方は「実数」でもう一方は「整数」です。 この状態では実数の少数部位は桁落ちしてしまうため意味を持ちません。 実数で「1.0」でも「1.9」でも整数では「1」として扱われます。 逆に、intの範囲を超えた場合もオーバーフローとしておかしな値を示すことになります。 (本当に引数と使用する型が違っていたら、コンパイル時にワーニングエラーが出てるはずだけど) 少数位まで扱うのであれば、No.3氏が回答しているとおり、一旦整数に変換する必要があります。 また、単純に整数に変換しただけでは座標は描画面のサイズをオーバーする可能性があるので、描画面の範囲も同様に等比倍して、 その上で実描画のための相対的な座標点を算出する必要があります。 それと、起点は左上が(0,0)等になっていませんか? であれば、そのままではマイナス座標は使用できません(使用できる環境でも論理座標扱いなら表示されない) この場合も同様に、起点を論理的に変更する処理を作成するか、開発環境が対応していれば、起点を動かす処理が必要になります。

zaqwe
質問者

補足

CEdit *p,*q,*r,*s,*t; CDC *v; CString a,b,c,d,z; p=(CEdit *)GetDlgItem(IDC_EDIT1); q=(CEdit *)GetDlgItem(IDC_EDIT2); r=(CEdit *)GetDlgItem(IDC_EDIT3); s=(CEdit *)GetDlgItem(IDC_EDIT4); t=(CEdit *)GetDlgItem(IDC_EDIT5); p->GetWindowText(a); q->GetWindowText(b); r->GetWindowText(c); s->GetWindowText(d); t->GetWindowText(z); int Z=atoi(z); double A=atof(a); double B=atof(b); double C=atof(c); double D=atof(d); switch(Z){ case 92: v=GetDC(); v->MoveTo((int)(A),(int)(B)); bx=A; by=B; ReleaseDC(v); break; case 01: v=GetDC(); v->MoveTo((int)(bx),(int)(by)); v->LineTo((int)(A),(int)(B)); bx=A; by=B; ReleaseDC(v); break; } }というVisualC++6.0のMFCダイアログベースで書かれたプログラムで Editボックス1にGの数字を Editボックス2にXの数字を Editボックス3にYの数字を入力して OKを押すと図形が作成される。 このプログラムをファイルから一行ずつ読み込んで 図形を書く、のが求めるプログラムです。 上記のプログラムなら小数点もいけました。 ただ小さくて線がみえないなんてこともしばしばですので5倍にしたりすれば普通に見えます。 原点は上記の手入力のプログラムは、ですが入力する全ての座標を ずらすことでなんとかできました。オフセットというのかな

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

>XとY座標は浮動少数も扱うのでdouble型にしたい。 >でこういう風にしたのですがそこも間違ってるのかな 貴方が「こうしたい」と期待しても、API関数は「貴方の期待通り」の引数は期待していない。 たぶん、LineToは BOOL LineTo(int nXEnd , int nYEnd); とかって定義されてて「引き数はintが2個だ」って決まってる。 なので、貴方がatofを呼んだり、floatでどうこうしようと思っても、すべて無駄。 最後の最後は「intの値を2つ渡す」のだから、座標が浮動少数になってようが整数になってようが、そんな事はすべて忘れ去られ「整数部分だけが使われてしまう」のはどうしようもない。 座標を浮動少数で扱う意味があるとしたら「座標値を100倍して、0.00は0の位置、1.00は100の位置、0.50は50の位置に拡大して描画する」と言う場合のみ。 等倍で描画している限りは、小数点はまったく無意味。デバイス座標系では「点の座標は整数」なので「1.5とか、小数点の付く位置」には点は存在しない。

zaqwe
質問者

補足

ファイルからの読み込みじゃなく 入力打ちなら浮動少数でも表示できるので そんなことは無いと思いますが・・・

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.2

double値を扱ってもどうせLineTo()に渡す際にはintにキャストされます。なのでまぁオーバーフロー注意、以外は問題ないといえばないんですが気になったので。 で、ブレークポイントとウォッチ式、デバッグ用変数等を使って「別環境ではなくこのコード内で期待通りになっているか」を確認してください。 追加でもう一つですが、 ・atof()の結果をintにキャストしたときに期待通り(小数点以下が落ちるだけ)の結果になっているか も確認をお願いします。

zaqwe
質問者

補足

buf3の中身は"-12.04" buf4の中身は"-7.01" になってました

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

数値切り出しならsscanf()とかfscanf()とか使った方が楽だと思いますがそれはさておき。 あとデバイスコンテキストまわりのコードが微妙におかしいようです。 > CDC *v; > GetDC(); > MoveTo(0,0); > LineTo(atof(buf3),atof(buf4)); > ReleaseDC(v); CDC *v = GetDC(); v->MoveTo(0, 0); v->LineTo(atof(buf3), atof(buf4)); ReleaseDC(v); でないとコンパイルできない気が。 GetDC()も描画対象のCWnd *を使う必要がありますし。 とは言うものの、前回の質問によるとこの辺は出来てるんですよね? てな訳で確認事項。 ・buf3、buf4の値はatof()の結果も含めて正常というか期待通りですか? ・LineTo()の引数x, yはint型ですが、なぜfloatで渡していますか?

zaqwe
質問者

補足

コピペできないものでミスが少しあったようで申し訳ない。 確認事項なんですが >buf3、buf4の値はatof()の結果も含めて正常というか期待通りですか? 試しに タイプが違うのですがコンソールで試した所buf3,buf4には 期待通りの値でした。 2個目の方がよくわからないんですが 文字列を一行よんで XとYの座標を取り出してbuf3,buf4に格納する この時点では文字列として扱われるのでatofで数字に変換する XとY座標は浮動少数も扱うのでdouble型にしたい。 でこういう風にしたのですがそこも間違ってるのかな

関連するQ&A

  • プログラム

    { FILE *fp; char *str,buf[1000];   char subbuf[100],*s1; char buf2[100],*s2;   char buf3[100],*s3; char buf4[100],*s4; static double bx=0; static double by=0; if ((fp = fopen("test.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='G'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s2=buf2; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0'&&(isdigit(*str) || *str=='-' || *str=='.')) *s2++=*str++; *s2='\0'; } if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s3=buf3; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *s3++=*str++; *s3='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) s4=buf4; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *s4++=*str++; *s4='\0'; } CDC *v; v=GetDC(); if((int)atof(buf2)==92){ MoveTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else if((int)atof(buf2)==01){ MoveTo((int)bx,(int)by); LineTo((int)atof(buf3),(int)atof(buf4)); bx=(int)atof(buf3); by=(int)atof(buf4); ReleaseDC(v); } else str++; } } fclose(fp); return 0; } という風なプログラムになっているのですが 今現在 G01X30Y30 G01X30Y120というファイルをこのプログラムにて実行すると (0,0)→(30,30)→(30,120)というような直線が引かれます。 しかしこれを G01X30Y30 Y120 とかかれたときも同様の結果がでるようにしたいです。 つまり最初のG○○が省略されているときは前回のGの値を X○○が省略されているときは前回のXの値を使うように 変更したいのですがどのように変更すればいいのかがわかりません。 教えてください。

  • プログラム

    { FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str!='\0' && *str=='X'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) xstr=xbuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) *xstr++=*str++; *xstr='\0'; } if(*str!='\0' && *str=='Y'){ *str++; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) ystr=ybuf; if((*str!='\0' &&(isdigit(*str) || *str=='-' || *str=='.')) while(*str!='\0' &&(isdigit(*str) |*str=='||*str=='.')) *ystr++=*str++; *ystr='\0'; } else str++; } pDC->MoveTo((int)bx,(int)by); pDC->LineTo((int)atof(xbuf),(int)atof(ybuf)); bx=(int)atof(xbuf); by=(int)atof(ybuf); } } fclose(fp); return 0; } とテキストファイルを読み込みその中のXとYに付属する値を 取り出し図形を書くというプログラムなのですが X100Y100 X200Y100というファイルなら (0,0)→(100,100)→(200,100)という2つの直線が描かれます。 実行の結果正常に動きました。 str=buf; の部分ではbufの先頭要素のアドレスをstrに設定している のはわかりました。 しかしxstr=xbufの所ではわからないことがあります。 bufでfpから読み込んだ文字列1行が入っているのはわかります。 しかしxbufにはまだ何も入ってないはずなのに xstr=xbufの所でxbufにはxの値がしっかり入っていました。 これはどうしてでしょうか xbufとかybufとかいらないような気もするのですが もしそうならばどのように書き直せばいいのでしょうか? この2点について教えてください。

  • 関数

    FILE *fp; char *str,buf[1000]; char xbuf[100],*xstr;   char ybuf[100],*ystr; static double bx=0; static double by=0; if ((fp = fopen("kadai.txt", "r")) == NULL) { printf("ファイルが開けません\n"); return EXIT_SUCCESS; } while (fgets(buf, 1000, fp) != NULL) { str=buf;        while((*str!='\0'){ if(*str=='X'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') xstr=xbuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) || *str=='-' || *str=='.')*xstr++=*str++; *xstr='\0'; } if(*str=='Y'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') ystr=ybuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } else str++; } } ファイルからの一行の切り分けのプログラムなのですが if(*str=='X'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') xstr=xbuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) || *str=='-' || *str=='.')*xstr++=*str++; *xstr='\0'; } の部分と if(*str=='Y'){ *str++; if(isdigit(*str) || *str=='-' || *str=='.') ystr=ybuf; if(isdigit(*str) || *str=='-' || *str=='.') while(isdigit(*str) |*str=='||*str=='.') *ystr++=*str++; *ystr='\0'; } の部分は変数が違うだけでほとんど同じ文ですよね。 関数を作ってこの処理のときに呼び出せれば応用が利くと思い 考えてみたのですが中々できません。よろしければ教えて下さい。 まだ戻り値や関数の理解が今ひとつです。

  • このプログラムは

    どこかおかしいですか? int main(void){ FILE *str; char buf[1000]; if((fp=fopen("ファイル名","r"))=NULL){ printf("ファイルが開けません"); return EXIT_SUCCESS; } while(fgets(buf,1000,fp) !=NULL){ str=buf; printf("%s",buf); } return EXIT_SUCCESS; } で実行すると前半4割程度が表示されません。 何故だかわかる人いませんか? 使用言語:C言語 環境:visualC++6.0 のコンソールアプリケーション。

  • ファイル

    ファイルを読み込み単語ごとに表示するプログラムです。 例 ファイル データ 形式 歴史・・ のように単語の後には空白がありますファイルです FILE *fp; char buf[1000]; char buf_word[1000]; char *str; char *bufstr; if((fp = fopen("test.txt","r")) == NULL){ printf("error!"); return 0; } while(fgets(buf,1000,fp) !=NULL){ str = buf; while(*str !='\0'){ strbuf = buf_word; if(*str ==' '){ printf("%s",buf_word); } else{ *strbuf++ = *str++; } } } とプログラムしてみましたが*strの値がどうもおかしく 最初が "フ" じゃなく"・"になってます。 最初の単語がG11とかなら"G"になっていますが・・ 教えて下さい。

  • プログラムが止まってしまいます

    Visual Studio 2012 c++ でプログラムを動かそうと思っているのですが、デバッグ開始すると画像のようなウィンドウが出て実行途中で止まってしまいます。 呼び出し履歴のint mqoLoadFileのソースを貼ります. int mqoLoadFile( MQO_OBJECT *mqoobj, char *filename, double scale, unsigned char alpha) { FILE *fp; MQO_OBJDATA obj[MAX_OBJECT]; MQO_MATDATA *M = NULL; char buf[SIZE_STR]; // 文字列読み込みバッファ char path_dir[SIZE_STR]; // ディレクトリのパス char path_tex[SIZE_STR]; // テクスチャファイルのパス char path_alp[SIZE_STR]; // アルファテクスチャファイルのパス int n_mat = 0; // マテリアル数 int n_obj = 0; // オブジェクト数 int i; // MaterialとObjectの読み込み fopen_s(&fp,filename,"rb"); if (fp==NULL) return 0; mqoobj->alpha = alpha; memset(obj,0,sizeof(obj)); i = 0; while ( !feof(fp) ) { fgets(buf,SIZE_STR,fp); // Material if (strstr(buf,"Material")) { sscanf_s(buf,"Material %d", &n_mat); M = (MQO_MATDATA*) calloc( n_mat, sizeof(MQO_MATDATA) ); mqoReadMaterial(fp,M); } // Object if (strstr(buf,"Object")) { sscanf_s(buf,"Object %s", obj[i].objname);//ココの実行中に止まる mqoReadObject(fp, &obj[i]); i++; } } n_obj = i; fclose(fp);

  • ファイルを読み込むプログラムについて

    下のプログラムで分からない所がありますので、教えて頂ければと思います。宜しくお願い致します。 text = fgets(buf,256,fp);はfpのファイルから一行を読み込んでbufに格納するという処理ということは分かります。でも、while文内なので次にこの処理をする時に今度は、2行目(下の段)を読み込むはずですが、プログラム中のどこに2行目に移動させる処理があるのか分かりません。 予想ですが、text = fgets(buf,256,fp);の中にそのような意味の処理が含まれているのでしょうか? どなたかご教授お願い致します。 #include <stdio.h> int main(void) { FILE *fp; char buf[256]; char *text; char flname[256]; printf("ファイル名:"); gets(flname); fp = fopen(flname,"r"); do{ text = fgets(buf,256,fp); if(text != NULL){ printf("%s",text); } }while(text != NULL); fclose(fp); return(0); }

  • どうやってフローチャートを書きますか

    #include<stdio.h>   void main()   {   FILE*fp;   char buf[128];   char *rc;   char fname[20];   do{   printf("file name>>>");   scanf("%s",fname);   fp=fopen(fname,"r");   if=(fp==NULL) printf("File Open Err¥n");   }while(fp==NULL);   rc=fgets(buf,128,fp);   while(rc!=NULL){    printf("%s",buf);    rc=fgets(buf,123,fp);    }    fclose(fp);    }

  • C言語、fgetcを利用しファイルの内容を変数に

    C言語について質問です C言語のfgetcを利用しファイルの内容を変数にいれてそれを返す関数を作っているのですがうまくいきません <!--以下ソース--> char *file_get_contents(char *filename){ FILE *fp; int c; char *return_str; if((fp=fopen(filename,"r"))==NULL) return NULL; while((c=fgetc(fp))!=EOF ){ sprintf(return_str,"%c",c); } fclose(fp); return return_str; } 誰か理由と改善方法を教えてください!

  • _popen() のエラー取得

    WindowsNT/2000で_popen()を利用してコマンドを実行しているのですが、その際のメッセージを取得したいのですが、通常のメッセージは取得出来るのですが、エラーメッセージが取得出来ません。どうすればよいのでしょうか? 現在のソースは下記のようです。 int main(int argc, char* argv[]) { char str[512],*ptr; FILE *fp; if((fp = _popen("dir b:","rt")) == NULL) { fprintf( stderr , "error!!!\n"); return -1; } while(1) { fgets(str,512,fp); if(feof(fp)) { break; } ptr = strchr(str,'\n'); if(ptr != NULL) { *ptr='\0'; } printf("%s\n",str); } _pclose(fp); return 0; }

専門家に質問してみよう