• 締切済み

関数

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'; } の部分は変数が違うだけでほとんど同じ文ですよね。 関数を作ってこの処理のときに呼び出せれば応用が利くと思い 考えてみたのですが中々できません。よろしければ教えて下さい。 まだ戻り値や関数の理解が今ひとつです。

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

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.6

これって、もしかして kadai.txt の内容が、例えば、   XA=-10.3YA=21   XB=-23.9*YB=-11.7   XZ=624,YZ=4.3.5 のとき、不要な文字( A B * , = X Y Z ◆)以外を、bx, by に数値化して入れる、ということですよね。  1行目の bx は -10.3、by は 21.0 と言う具合に?? ↑この想像が誤っていましたら、以降スルーしてください。 ---------------------------------------------------- >の部分は変数が違うだけでほとんど同じ文ですよね。 >関数を作ってこの処理のときに呼び出せれば応用が利くと思い  確かにそのとおりなのですが・・。    一度も、ソースを実行していませんよね。  「ポインタ」の扱いを勉強し、正常に動いてから関数化でも遅くないかと・・。 ---------------------------------------------------- 「ポインタの勉強」を棚上げにしたソースを・・(BorlandC++5.5.1)  (上の想像データで動作確認済み) >まだ戻り値や関数の理解が今ひとつです。  「戻り値・関数の型」を受け側( bx by )と同じの double としています。   http://www.bohyoh.com/CandCPP/C/Library/atof.html #include <stdio.h> #include <ctype.h> #include <stdlib.h> double GetVal( char cTop, char cBtm, char buf[] ) {  int i, iSw = 0, nn = 0, iOk;  char cTarget[ 16 ] = "-999.9";  for( i = 0; buf[ i ]; i++ ){   if( cTop == buf[ i ] ) iSw = 1;   if( cBtm == buf[ i ] ) break;   if( 0 == iSw ) continue;   iOk = 0;   if( isdigit( buf[ i ] ) ) iOk = 1;   if( '-' == buf[ i ] ) iOk = 1;   if( '.' == buf[ i ] ) iOk = 1;   if( 0 == iOk ) continue; // ◆不要文字除外   cTarget[ nn++ ] = buf[ i ];   cTarget[ nn ] = '\0';  // 文字列終端処理  }  return( atof( cTarget ) ); // 数値化 } int main() {  FILE *fp;  char buf[ 128 ];  double bx, by;  if( ( fp = fopen( "Z:\\kadai.txt", "r" ) ) == NULL ){   printf( "ファイルが開けません\n" );   return( 256 );  }  while( fgets( buf, 128, fp ) != NULL ){   bx = GetVal( 'X', 'Y', buf );   by = GetVal( 'Y', '\n', buf );   printf( "X=%6.1lf,Y=%6.1lf\n", bx, by );  }  fclose( fp );  return( 255 ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。

  • chie65535
  • ベストアンサー率43% (8519/19367)
回答No.5

関数に渡すべき物 ・呼び出しごとに値が異なる物 ・呼び出し後に値が変わる物のポインタ 関数から返すべきもの ・実行したか、しなかったかの結果 int func(char n,char **str,char *nbuf) { char *nstr; if(**str==n){ (*str)++; if(isdigit(**str) || **str=='-' || **str=='.') nstr=nbuf; if(isdigit(**str) || **str=='-' || **str=='.') while(isdigit(**str) || **str=='-' || **str=='.') { *nstr++=**str; (*str)++; } *nstr='\0'; return 0; } else return 1; } FILE *fp; char *str,buf[1000]; char xbuf[100]; char ybuf[100]; 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'){ func('X',&str,xbuf); //if(*str=='X'){...}の代わり if (func('Y',&str,ybuf)) str++;//if(*str=='Y'){...}else str++;の代わり。1が返ってきたらelseの次の文のstr++;を行う } } 検証してないので上手く動かないかも知れない。

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

こんなソースがあるとします。 #include <stdio.h> int main(void) { int a, b, c, x, y, z; a = 10; x = 2 * a + 3; printf("%d\n", x); b = 200; y = 2 * b + 3; printf("%d\n", y); c = 3000; z = 2 * c + 3; printf("%d\n", z); return 0; } x, y, zを求める文は、使っている変数(a, b, c)こそ異なりますが、 2に何かを掛けて3を足すという形は共通していますね。 この共通している部分を、関数として切り出してみましょう。

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

どういった方法で勉強していますか? 何か一冊、しっかりした入門書をお読みになるのがよいと 思いますけれど…。

noname#88772
noname#88772
回答No.2

 こんにちは。 >まだ戻り値や関数の理解が今ひとつです。  この部分をクリアすればできますよ。  中身はほとんど出来ているも同然ですので。  ご参考までに。

zaqwe
質問者

補足

その部分がわかればわかるのはわかりますよ。 わからないから質問しているのです。

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

「なかなかできません」と書かれているということは, いくつか挑戦しているわけですよね? よければ, それらを出してもらえますか?

zaqwe
質問者

補足

できないというのはプログラムが思い浮かばないという意味です。

関連するQ&A

  • プログラム

    { 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 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の値を使うように 変更したいのですがどのように変更すればいいのかがわかりません。 教えてください。

  • プログラム

    以前ファイルから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使ってます

  • ファイル

    ファイルを読み込み単語ごとに表示するプログラムです。 例 ファイル データ 形式 歴史・・ のように単語の後には空白がありますファイルです 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"になっていますが・・ 教えて下さい。

  • 関数化

    #include <ctype.h> #include <string.h> #include <stdlib.h> void swap(char p[], char q[]); char *get(char *str, char buf[], int line, int field); typedef struct { int number; char *class_type; char* name; char *subject; } my; my *data; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufG; int line2 = 0; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); printf("%d\n", line2); if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ str = buf; while(*str != '\0'){ bufG = get(str, buf, line, field); switch(field){ case 0: data[line].number = atoi(bufG); break; case 1: data[line].class_type = (char *)malloc(strlen(bufG) +1); strcpy(data[line].class_type, bufG); break; case 2: data[line].name = (char *)malloc(strlen(bufG) + 1); strcpy(data[line].name, bufG); break; case 3: data[line].subject =(char *)malloc(strlen(bufG) + 1); strcpy(data[line].subject, bufG); break; } str++; field++; } line++; field = 0; } fclose(fp);     for(int m = 1; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject);     } return 0; } char *get(char *str, char buf[], int line, int field) { char bufG[1111]; int i; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前回の質問 http://okwave.jp/qa5094929.html で提示していただいたサンプルの関数化をはかりましたが うまくいきません。これを実行すると1しか表示されません。 原因はおそらくポインタだと思いますがどうすればいいのか わかりません。教えて下さい。bufを引数にする意味ないのでは という意見は今の所はとりあえずなしで fieldの値によってbufGが色々とってくる。 例えば1,A,山田,数学の場合 field = 0のときbufGは1 filed=1のときbufGはA field=2のときbufGは山田 filed=3のときbufGは数学という ような値が返ってくるようにしたいです。

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

    #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);    }

  • このプログラムは

    どこかおかしいですか? 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 のコンソールアプリケーション。

  • 配列を返す

    ファイルから読み込んだ一行の文字列を読み込みカンマごとに区切って 返すというプログラムを関数化することで効率を図りたいと思います。 int main() { char buf[1000]; char *str; char *bufG; //ファイルを読み込む  while(fgets(buf,1000,fp) != NULL){//一行ずつ読む str = buf;//先頭アドレスを指す     bufG = //文字列を返す関数  ・  ・  ・ } } //文字列を返す関数 {    for(i = 0; *str != ',' && *str != '\0'; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前の質問で自動変数でこの関数を抜けたら廃棄になるというのは わかったんですが(そういう警告がでました) ここからどのようにすれば求めるプログラムになりますか? 引数とかちょとわからないので関数定義を書きませんでした。 (1)ファイルをよみこむ (2)一行ずつ読み込み文字列をbufにいれる (3)ポインタstrをbufの先頭アドレスにする (4)get_word関数にてポインタをずらしていき カンマがあればそこまでの文字列を返す (5)main関数に戻り変数に代入する (6)終端文字があるまで(4)ー(5)を繰り返す。 (7)さらに行数分繰り返す これらの一連の流れをやりたいのですが わかりません。

  • malloc関数(strtok関数の自作版)につきまして分からないこと

    malloc関数(strtok関数の自作版)につきまして分からないことがあります。 以下のプログラムにmallo関数がフリーする最適な位置を明示しなさいといわれました。 文字が分離した時にfreeすると助言されたのですが いまいち理解できません・・・。 条件式の中で使用するともいわれていました。(おそらくif文・・・。) 色んな意見を参考にしたいので詳しい方助言のほうよろしくおねがいします。 なおプログラムはほかの箇所を変更したり、他の場所でもmalloc関数を使用することが認められています。 またfreeする場所はメイン関数ではなくあくまでもstrtok関数の中で宣言するようです。 よろしくお願いします。 #include <string.h> #include <stdio.h> #include <stdlib.h> main(){ char* s2 = ",/"; char* result; char* r1; char* r2; char* r3; char* r4; result = strtok("//123//,45/,678,9/","/,"); r1 = strtok(NULL, s2); r2 = strtok(NULL, s2); r3 = strtok(NULL, s2); r4 = strtok(NULL, s2); printf("%s\n",result); printf("%s\n",r1); printf("%s\n",r2); printf("%s\n",r3); printf("%s\n",r4); return; } char *strtok(char *s1, const char *s2) { int i,len; char *str1, *str2 , *str3; static char *tok ; static char* mstr; if(s1 != NULL) { str1 = s1; } else { str1 = tok; } str2 = str1 + strspn(str1, s2); /* strspnを利用 */ if (*str2 == '\0') { return (NULL); } len = 1; i = 0; while(*(str2 + i) != '\0'){ len++; i++; } mstr = (char*)malloc(sizeof(char)*len); if(mstr == (NULL)) { return 0; } i = 0; while(*(str2 + i) != '\0'){ *(mstr + i) = *(str2 + i ); i++; } *(mstr + i ) = '\0'; str3 = mstr + strcspn(mstr, s2); /* strcspnを利用 */ if (*str3 != '\0'){ *str3 = '\0'; str3 = str3 + 1; } tok = str3; return (mstr); }

  • 関数について

    char *str_char(const char *str, int c) { while (*str++) if (*str == c) return ((char *)str); return (NULL); } /*文字列strから文字cを検索し最初に存在する文字へのポインターを返す*/ 上記関数なのですが 5行目を return (str); にしてはなぜいけないのでしょうか。

専門家に質問してみよう