C言語で振幅の最大値を求める方法について

このQ&Aのポイント
  • C言語でdatファイルから時間と振幅のデータを読み込み、振幅の最大値とその時間を求める方法について教えてください。
  • 質問者はdatファイルに時間と振幅のデータが入っており、振幅の最大値の2割に達した時間を出力したいとしています。
  • サンプルプログラムを提供することで具体的なアドバイスをしてください。
回答を見る
  • ベストアンサー

c言語についての質問です

あるdatファイルに時間と振幅のデータが入っているんですが振幅のデータのみを2乗してから2乗したものに1/2乗し正のものだけから振幅の最大値を求め、振幅の最大値の2割に達した時間を出力したいのですが、どのようにすればよいか分かりません。 サンプルプログラムを載せますのでおねがいします。 ちなみにdatファイルには 時間 振幅 時間 振幅 … となっています。 #include <stdio.h> int main(void) { const char * fname = "C2.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &amp); if (amp > max) { max = amp; } } fclose(fp); printf("max: %.7lf\n", max); fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line, "%lf%lf" , &time, &amp); if(amp > max*0.2){ arrival = time; break; } } fclose(fp); printf("arrival:%.16lf\n",arrival); return 0; }

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

  • ベストアンサー
noname#217196
noname#217196
回答No.4

振幅の最大値を求める計算は、2乗してから1/2乗して正の値で比較するってことは、単純に振幅値がマイナスのときはマイナス1をかけて正の値にして比較すれば良さそうだけど。C言語仕様書なりで数学関数を調べておけば、累乗、平方根を求めるときに使う関数はわかるよね。 まず、振幅の最大値を求める。これは、最大値を代入する変数を用意して、初期値0か負の値で初期化しておいて、一行ずつ読み込んでは比較用の正の値に直した振幅値と比べて読み込んだほうが大きければ最大値用の変数に代入。という繰り返し処理で、ファイルの終わりに到達したら繰り返し処理を終了。 次に、振幅の最大値の2割に達した時間を求める。たぶんぴったり2割という値じゃないときもありそうだから、振幅の最大値の2割以上で最小値になる時間を求めることになるだろう。最小値を求める変数を用意して、振幅の最大値かその変数のデータ型でとりうる最大値で初期化しておいて、ファイルの先頭から一行ずつ読み込んでは、振幅の値が振幅の最大値の2割以上だったら最小値の変数と比較して、最小値の変数の値のほうが大きければ最小値の変数へ代入して更新。並行して、振幅の最大値の2割に達した時間を代入しておく変数の値も更新とともに出力。これをファイルの終わりまで繰り返し。 ひとつの振幅周期しかファイルに記録されていなければ、こんな感じで処理できると思うよ。 構造体、構造体を入れる配列、クイックソートを勉強すると、もっとうまく処理できるプログラムになるだろう。 ほかに細かな注意事項を挙げておくと、変数のデータ型、特に数値データ型は表現できる値の下限値、上限値、オーバーフロー、アンダーフローに注意。また、異なる数値データ型での型変換(cast)で情報落ちしないかに注意。 ファイル操作では、ファイルのオープン、クローズ、読み込み、書き込みのときにエラーが起きたときの処理も追加するのが安全。ファイルを作ったOS 環境とプログラムを動かすOS 環境とで文字コードの違いがないか、改行コードの違いがないか、ファイル先頭のBOM情報に適した処理にしなくてはならないのか注意。エスケープシークエンス文字の使い方にも注意。時間データ値が数値データなのか、文字列データなのか、時間データと振幅データを区切るのはTABコードなのかホワイトスペースなのかなど。 サンプルプログラムはパッと見、arrival 変数が振幅の最大値の2割を超えていればどんどん更新され続けるバグがある。ほかに、sscanf の書式指定で、時間データと振幅データを区切るセパレータ文字列の扱いが抜けているから、正しい振幅データがamp 変数に取り込めていなそう。この辺は、デバッガを使って変数の値をトレースするやり方を身につけるか、デバッグ用のprintfを付け足して確認するのがいいでしょう。

その他の回答 (3)

回答No.3

おそらくは、 http://okwave.jp/qa/q8756335.html からの続きだと思います。 で、想像すると、 ・振幅データには、正のものと負のものがある。 ・上記の質問の方法では、負のデータは対応できない ・振幅の絶対値を取って、処理する必要がある ・ちなみに、絶対値をとる方法(のひとつ)は、自乗してから、開平すること。 という流れなのかなという。 で、この通りなら、既に回答がありますが、fabs() という関数で絶対値がとれます。 amp の値が決まった直後(入力された後)に、amp = fabs(amp); としておけば良いです。 (最大値を求める方も、0.2倍を超えたか判断する方も) ※ fabs() を使うには、math.h が必要 でも、振幅データだと、複数の波のデータがあると思うのですが、一回の処理でOKなのかな。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

計算プログラムなら、まずは、数式にしてみましょう。 もともと計算するために作られたのがコンピュータで、その制御用に作られたのがプログラミング言語です。 ほとんどの言語では、数式をそのまま、あるいは少し変えるだけで表現できるように作られています。 > 振幅のデータのみを2乗してから2乗したものに1/2乗し正のものだけから振幅の最大値を求め 言葉からだけでは判断が難しいです。 ファイルの振幅データは、変数ampに格納されている、というのは理解できていますね? ならば、上で「最大値」を求めたい「値」って何なのですか? val = sqrt( amp * amp ) /* ampの2乗の1/2乗(sqrtは非負の引数から√を求める標準関数) */ val = sqrt( amp * amp * amp * amp ) /*「2乗してから2乗したもの」=4乗とも解釈できる */ また「正のもの」とは?amp > 0 の意味ですか、 val > 0 の意味ですか? ampが実数なので、 √(amp*amp) は非負ですが。 さらに言えば、 「val = ampの絶対値 」ではありませんか? 実数の絶対値を求めるfabsという関数がありますし、自作も簡単です。

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

プログラムにする以前の問題として, 何をどう計算したいのかがさっぱりわからない.

関連するQ&A

  • c言語についての質問です

    c言語についての質問です。あるdatファイルに振幅と時間のデータが保存されています。 このdatファイルを読み込み振幅の最大値を求めてから振幅の2割の値を求めます。 そこから再度読み込み振幅の2割を超える時間まで読み込み越えた際の時間を出力したいのですが上手くいきません。途中がけのプログラムをのせるのでお願いします。 datファイルには 時間 振幅 時間 振幅 … のようになっています。 #include <stdio.h> #include <math.h> int main(void) { const char * fname = "C1rbc1(50,0)sq,almi00001.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &amp); if (amp > max) { max = amp; max20=max*0.2; } } fclose(fp); printf("max: %.7lf\n", max); printf("0,2*max:%.7lf\n",max20); int main(void) { FILE *fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line,"%lf%lf",&time,&amp); if(amp>max20){ arrival=time; break; } } fclose(fp); printf("arrival:%.7lf\n",arrival); return 0; } }

  • 【c言語】ファイルの読み込みエラーについて

    自然言語処理について勉強しています。 Wikipediaのdumpデータからタイトルと本文を抜き出して処理をしようと思ってます。 xmlの処理について試しているのですが、エラーに見舞われて困っています。 プログラミングはあまり得意ではないです。 以下にソースコードとエラー部分を貼り付けます。 ご助力お願いします。 ============================ #include <stdlib.h> #include <string.h> int main (){ size_t p; char pb[5]; char line[BUFSIZ]; FILE *fp = fopen("//Wikipediaの分割ファイル//.xml", "r");//xmlファイルのアドレス char title[BUFSIZ]; //FILE *gt=fopen("list_1.txt","r"); FILE *fw = fopen("get_text_c.txt", "w"); if ((NULL == fp)||(NULL== fw )){ printf("aboooooooooooooooooooooooooooot") abort();//終了、ここがうまくいってない? } while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { if (strstr(line, "<title>")){ pb[0] = p;//タイトルの始点 } else if (strstr(line, "</title>")){  pb[3]=p;//タイトルの終点   pb[2]=p-pb[0];//タイトルのバイト数  fprintf(fw, "%zu \t %zu \n", pb[2], pb[3]); //pb2とpb3の観察。  fgets(line,pb2[2],pb[0]);//タイトルを取得  printf("%s",line);//表示  fprintf(fw,"%s",line);//書き込み } else if (strstr(line, "</page>")) {  pb[1] = p - pb[0];  //fwrite(pb, sizeof(size_t), 2, fw); // ...  fprintf(fw, "%zu \t %zu \n", pb[0], pb[1]); //... テキスト形式で観察可能 } } } fclose(fw); fclose(fp); } エラー(ファイル名は get_うぃき.c としてます。) =========================== get_うぃき.c:10:16: warning: declaration of built-in function 'fopen' requires inclusion of the header <stdio.h> [-Wbuiltin-requires-header] get_うぃき.c:11:16: error: use of undeclared identifier 'BUFSIZ' char title[BUFSIZ]; ^ get_うぃき.c:14:5: error: use of undeclared identifier 'FILE' FILE *fw = fopen("get_text_c.txt", "w"); ^ get_うぃき.c:14:11: error: use of undeclared identifier 'fw' FILE *fw = fopen("get_text_c.txt", "w"); ^ get_うぃき.c:15:18: error: use of undeclared identifier 'fp' if ((NULL == fp)||(NULL== fw )){ ^ get_うぃき.c:15:31: error: use of undeclared identifier 'fw' if ((NULL == fp)||(NULL== fw )){ ^ get_うぃき.c:16:13: warning: treating Unicode character <U+FF08> as identifier character rather than as '(' symbol [-Wunicode-homoglyph] printf("aboooooooooooooooooooooooooooot") ^~ get_うぃき.c:16:7: error: use of undeclared identifier 'printf(' printf("aboooooooooooooooooooooooooooot") ^ get_うぃき.c:16:49: warning: treating Unicode character <U+FF09> as identifier character rather than as ')' symbol [-Wunicode-homoglyph] printf("aboooooooooooooooooooooooooooot") ^~ get_うぃき.c:20:16: error: implicit declaration of function 'ftell' is invalid in C99 [-Werror,-Wimplicit-function-declaration] while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { ^ get_うぃき.c:20:27: error: implicit declaration of function 'fgets' is invalid in C99 [-Werror,-Wimplicit-function-declaration] while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { ^ get_うぃき.c:20:39: error: use of undeclared identifier 'BUFSIZ' while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { ^ get_うぃき.c:20:47: error: use of undeclared identifier 'fp' while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { ^ get_うぃき.c:20:12: error: use of undeclared identifier 'p' while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { ^ get_うぃき.c:20:22: error: use of undeclared identifier 'fp' while (p = ftell(fp), fgets(line, BUFSIZ, fp)) { ^ get_うぃき.c:22:15: error: use of undeclared identifier 'p' pb[0] = p;//タイトルの始点 ^ get_うぃき.c:25:7: warning: treating Unicode character as whitespace [-Wunicode-whitespace]  pb[3]=p;//タイトルの終点 ^~ get_うぃき.c:26:6: warning: treating Unicode character as whitespace [-Wunicode-whitespace]   pb[2]=p-pb[0];//タイトルのバイト数 ^~ get_tokuhisa.c:25:16: error

  • C言語でファイルを出力

    ファイルの中に変数をいれて複数のファイルをつくろうとしたのですが、 できたファイルの後に?マークがついてきます。 file = fopen("filename.txt", "w"); for(j=0; j<30; j++){ fprintf(file ,"%d.dat\n",j ); } fclose(file); file2 = fopen("filename.txt", "r"); として、ファイル名を書いたファイルをつくってから、 for(k=0; k<30; k++){ fgets(fp,sizeof(fp),file2); file_out = fopen(fp,"w"); 省略 fprintf(file_out, %e %e \n",a ,b); fclose(file_out); } fclose(file2); をして、30個のファイルを出力すると、 0.dat? 1.dat? 2.dat? . . . 29.dat? というファイルができてしまいます。 ファイルの中はしっかりできています。 なにか解決法を知っている方がおりましたら、どうか教えて下さい。

  • c言語 sscanf の書式についての質問です

    C言語でCSVファイルの読み込みをしようとしています。CSVの中身は以下の2通りあります。 ・[ ] で囲った文字列(1行に1つだけ) ・データの並び(1行に2つ以上) 具体的には、[ ] で囲った文字列と、最初の2つのデータのみが抽出対象です。そこで以下のコードを書いてみましたが、最後に示すように、[ ] で囲った文字列がうまく抽出できません。以下のコードのようなsscanfの使い方は間違っているのでしょうか?正しく動作するにはどうすればよいか、教えて下さい。 ---------- 以下、ソースコード #include <stdio.h> #include <string.h> int main(void) {  FILE *fp;  char *fname = "test.csv";  char s1[32], s2[16];  int ret;  char str[128];    /* csvファイルの一行 */  char structName[32];  /* セパレータ名 */  fp = fopen( fname, "r" );  if( fp == NULL ){   printf( "%sファイルが開けません\n", fname );   return -1;  }  while( fgets( str, 128, fp ) != NULL ){      /* セパレータ */   if( str[0] == '[' ){    printf( "str = %s\n", str );    ret = sscanf( str, "[%s]\n", structName );    printf( "structName = %s\n", structName );    continue;   }      ret = sscanf( str, "%[^,],%[^,]", s1, s2 );      printf( "s1 = %s\n", s1 );   printf( "s2 = %s\n", s2 );  }  fclose( fp );  return ret; } ---------- 以下、"test.csv"の中身 [ABC] test01,10,11,1.0,1.1 test02,20,21,2.0,2.1 test03,30,31,3.0,3.1 [DEF] test04,40,41,4.0,4.1 ---------- 以下、実行結果 str = [ABC] structName = ABC] s1 = test01 s2 = 10 s1 = test02 s2 = 20 s1 = test03 s2 = 30 str = [DEF] structName = DEF] s1 = test04 s2 = 40

  • c言語プログラミング実行時エラーについて質問です。

    c言語プログラミングを実行しようとすると、 エラーが出て次のようなメッセージが出てしまいました。 「「7行目」で記述エラーを発見しました。「constant expression」を付け忘れています。」 どなたか原因を教えてください。よろしくお願いいたします。 以下が失敗したプログラムです。 #include <stdio.h> int main(int argc, const char * argv[]) { const char FILENAME[] = "/Users/user/Desktop/date3.txt"; const int LEN = 100; char line [LEN]; char name [LEN]; char birth [LEN]; char address [LEN]; FILE *dat; dat = fopen(FILENAME, "r"); if ( dat == NULL ) { printf(" ファイル %s がオープンできません. ", FILENAME); return -1; } while( fgets( line, LEN, dat) != NULL ) { sscanf( line "%s, %s, %s", name ,birth, address ); printf("name = %s, address = %s\n", name, address ); } fclose(dat); return 0; }

  • C言語 CSVからTXTへ書き込み

    CSVファイルのデータを配列に格納してtest.txtに書き込みたいです。 その際、指定した列だけを書き込むのですが、うまくいきません。 a.txtの中身が a1,a2,a3,a4,a5 b1,b2,b3,b4,b5 c1,c2,c3,c4,c5 だとしたら、a1,a2,a3,a4,a5だけしか書き込めていません。 test.txtに書き込みたいのは、 a3 b3 c3 のようにしたいです。 初心者ですが、なかなかうまくいかないのでくやしいです。。。 お詳しい方、ご教授よろしくお願いします。 #define LINE_MAX 1024 #define ITEM_MAX 200 FILE *fp; char in_file[] = "a.txt"; char line[LINE_MAX]; char delmit[] = ",\n";      char item[ITEM_MAX][100]; char *item_p; int item_idx,ii; if((fp = fopen(fnamebuff, "r")) != NULL) { while(fgets(line, LINE_MAX, fp) != NULL) { if((item_p = strtok(line, delmit)) != NULL) { strcpy(&item[0][0], item_p); for(item_idx = 1; item_idx < ITEM_MAX; ++item_idx) { if((item_p = strtok(NULL, delmit)) != NULL) { strcpy(&item[item_idx][0], item_p); } else { item[item_idx][0] = '\0'; } } } FILE *fl; fl=fopen("test.txt","w"); for(ii=0;ii<200;ii++){ fprintf(fl," %s ", &item[ii][0]); } fclose(fl); fclose(fp); } }

  • C言語のファイル入出力の問題です

    C言語の課題です ファイルの入出力を応用した関数の総和と平均値を求める問題です。 総和がどうしても0になります 原因を教えて下さい 前問にy=x/(1+x^2)を-10.0≦x≦10.0(xは0.01刻み)の範囲で計算して結果をsp4_rslt.datに出力せよという問題があります。これはそのsp4_rslt.datを最初に読み込んで、今度は0≦x≦10.0の範囲でyの総和と平均を求めなければなりません。 なのでfor文でループしてあとは計算というプログラムにしました。最後に結果をsp6_rslt.datに出力しろというものです。 けれどいくらやっても0にしかなりません。どこを修正すればいいのか教えて下さい #include <stdio.h> #include <stdlib.h> int main(void) { double x,y; double Summation, Average; FILE *fp; fp = fopen("sp4_rslt.dat", "r"); if (fp == NULL) { puts("can't open file!"); exit(-1); } for(x=0.; x<=10.0; x+=0.01){ y = x/(1+x×x); fscanf(fp,"%lf %lf",&x,&y); Summation = Summation + y ; Average = Summation / 1000.0; } fp = fopen("sp6_rslt.dat","w"); fprintf(fp,"Summation is %lf\nAverage is %lf\n",Summation ,Average); fclose(fp); return 0; }

  • C言語の質問です。

    前にも質問したのですがなかなかうまくいかないのでよろしくお願いします。 データの書いてあるファイルを読み込んで処理するプログラムを書きたいと考えています。 読み込むデータ 0.012500 0.499167 1.382500 1.534444 2.489167 3.635000 3.775000 5.407500 5.705000 5.916667 6.115833 6.295278 6.825278 7.079722 . . . . この様な数値のかいてあるデータを使って0.5ずつに区切ってその中に何個データがあるか数えたいと考えています。(データは1万5千個以上あります) 例えば上のデータで考えると 0~0.5の範囲のデータは2個 0.5~1の範囲のデータは0個 1~1.5の範囲のデータは1個 1.5~2の範囲のデータは1個 2~2.5の範囲のデータは0個。。。 という風に数えるプログラムにしたいです。 僕が分からないところはどのように場合分けしていくか。。。です。 #include<stdio.h> //#include<process.h> int main(void) { FILE *fp; double n; int cnt,i,Cnt; fp=fopen("1.dat","r"); if(fp==NULL) { printf("file open error!!\n"); exit(1); } i=0; cnt=0; Cnt=0; while(fscanf(fp,"%lf\n",&n)!=EOF){ if(i<=n<(i+0.5)){ cnt++; printf("%lf %d\n",i,cnt); } else if((i+0.5)<=n<(i+1)){ Cnt++; printf("%lf %d\n",i,Cnt); } else{ i++; } } fclose(fp); return 0; } 僕の考えはデータを読み込む 変数 i を使って if文で i <= n <i+0.5の範囲のときはcntを足していく     i+0.5<= n <i+1の範囲のときはCntを足していく それ以外のときは i を+1して同じことを繰り返す というようなやり方を考えました。 しかしうまくいきませんでした。 どのようにすればよいでしょうか。 よろしくお願いします。

  • fgetsについて質問です;;

    すいません質問です fgets(str,255,fp)で読み込んだ一行が、取り出せずdmy配列に入れることができません これは何故でしょうか? fp = fopen("aaa.dat","r"); for(ss;fgets(str,255,fp) != NULL;ss++ ){ dmy[ss] = str[ss]; printf("%s\n",str); } printf("%s\n",dmy[5]); fclose(fp); }

  • どうしてもわかりません2

    #include <stdio.h> #include <string.h> #define MAX_LINE_SIZE 1024 #define NN 1000000 main(int argc, char* argv[]) { char fname[256]; char buf[MAX_LINE_SIZE]; int i; FILE *fp; for(i=1; i<argc; i++) { bzero(fname, 256); strcpy(fname, argv[i]); if( !(fp = fopen(fname, "r"))) { printf("File Open Error.\n"); exit(1); } while( fgets(buf, MAX_LINE_SIZE, fp ) ) { printf("%s", buf); } fclose(fp); } } このプログラムをコンパイルして(実行形式はa.out)コマンドラインから 以下のようなデータのテキストファイルna.txtを実行しました。./a.out na.txtするとこのソースだとbufに一行目がすべて文字列として入ってしまうと思います。そうではなく、1行目の数字ひとつずつを取り出す方法が知りたいです。たしか数字とか空白とかを判定する関数があったともうのですが、どうしてもわかりません。 ちなみにこの問いかけからこの問いがきています。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=1577294 1 2 3 4 5 6 2 3 4 5

専門家に質問してみよう