• ベストアンサー

データから必要な部分だけ出力したいのですが

作成したプログラムにおいて、受信しているデータから必要な部分だけを取り出して表示ができるようなプログラムに変更したいのですが、とても難易度の高い技術なのでしょうか?方法や参考になる資料をご存知の方がいらっしゃれば是非ご教授ください。よろしくお願いします。

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

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

> 世界標準時と緯度経度の間のステータスや経度以降の情報は不要な場合どうにかするにはどうすればよいでしょうか? いろいろやり方はあると思いますが、 ・切り出した文字列を全部文字列の配列にstrncpyでコピーして必要なとこだけ使う とか、 ・必要な分だけ、strtokで切り出して変数に代入を繰り返す とか。 こんな感じ?(表示の部分は自信なし) #include <stdio.h> #include <string.h> #include <math.h> /* floor, fmod */ char buf[512]="$GPRMC,093514,A,3428.9468,N,13649.4907,E,0.0,196.2,180708,6.7,W,A*05"; void printgps(void) { /* エラーなら 何もしない */ int utc; /* 世界標準時 */ char stat; /* ステータス */ double latitude; /* 緯度 */ char ns; /* 南北 */ double longitude; /* 経度 */ char ew; /* 東西 */ char *p; /* strtok用ポインタ */ /* 切り出し */ if ((p=strtok(buf,","))==NULL) return; if (strcmp(p,"$GPRMC")!=0) return; /* 先頭が $GPRMC か? */ if ((p=strtok(NULL,","))==NULL) return; /* 世界標準時 */ sscanf(p,"%d",&utc); if ((p=strtok(NULL,","))==NULL) return; /* ステータス */ stat=p[0]; if ((p=strtok(NULL,","))==NULL) return; /* 緯度 */ sscanf(p,"%lf",&latitude); if ((p=strtok(NULL,","))==NULL) return; /* 南北 */ ns=p[0]; if ((p=strtok(NULL,","))==NULL) return; /* 経度 */ sscanf(p,"%lf",&longitude); if ((p=strtok(NULL,","))==NULL) return; /* 東西 */ ew=p[0]; /* 表示 */ if (stat!='A') return; /* ステータス有効チェック */ printf("%02d時%02d分%02d秒(UTC) ",utc/10000, (utc%10000)/100, utc%100); if (ns=='N') printf("北緯"); else if (ns=='S') printf("南緯"); printf("%.0lf度%.4lf分 ",floor(latitude/100.0), fmod(latitude,100.0)); if (ew=='E') printf("東経"); else if (ns=='W') printf("西経"); printf("%.0lf度%.4lf分",floor(longitude/100.0), fmod(longitude,100.0)); printf("\n"); } int main(void) { printgps(); return 0; }

abcmottu
質問者

お礼

>JaritenCatさん お礼が遅れてしまい申し訳ありません。非常にわかりやすいプログラムをわざわざ作成してくださり助かりました。 本当にありがとうございました。

すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.3

strtokを使ってみてはどうでしょう。 こんな感じ? #include <stdio.h> #include <string.h> char buf[512]="$GPRMC,093514,A,3428.9468,N,13649.4907,E,0.0,196.2,180708,6.7,W,A*05"; int main(void) { char *p; if ((p=strtok(buf,","))!=NULL) { /* カンマまでの文字を取得 */ if (strcmp(p,"$GPRMC")==0) { /* 先頭が$GPRMCなら */ while((p=strtok(NULL,","))!=NULL) { /* カンマ区切りの文字を切り出す */ printf("[%s]",p); /* とりあえず表示 */ } } } return 0; }

abcmottu
質問者

補足

JaritenCatさん回答ありがとうございます。 なるほど勉強になります。strtokで取得してstrcmpで比較?して必要な部分を表示すればよいのですね。 ただ順番が$GPRMCの場合ですと $GPRMC,093514,A,3428.9468,N,13649.4907,E,0.0,196.2,180708,6.7,W,A*05 $GPRMC,世界標準時(UTC),ステータス(有効ならA、無効ならV),緯度,経度,対地速度(ノット),進行方向(度),日付(UTC),地磁気の偏角 と対応しており、世界標準時と緯度経度の間のステータスや経度以降の情報は不要な場合どうにかするにはどうすればよいでしょうか?

すると、全ての回答が全文表示されます。
  • masa6272
  • ベストアンサー率66% (93/140)
回答No.2

カンマで区切られているんですね。 http://d.hatena.ne.jp/hakobe932/20060422/1145705391 に、文字列の分解のプログラムが載ってます。 近頃の言語はsplitって関数が最初からあるのが多いんですが。

abcmottu
質問者

補足

回答ありがとうございます。 splitというものが他の言語にはあるのですね。 strtokを活用すればよいのでしょうか。

すると、全ての回答が全文表示されます。
  • masa6272
  • ベストアンサー率66% (93/140)
回答No.1

言語は? ・C? ・C++? ・C#? 受信しているデータは、 ・テキスト ? バイナリ ? ・テキストだったら、形式は?  ・csvのような形式?  ・XML?  ・自然言語? 必要な部分はどう決まるのか この辺を書かないと答えようもないでしょう・

abcmottu
質問者

補足

迅速に回答頂きありがとうございます。重要な情報が抜けており、申し訳ありませんでした。開発環境はLINUXでC言語を使用しております。プログラムはGPS端末で受信したNMEAデータをRS232Cで接続したPCに表示する というものです。 そのとき得られるNMEAデータは $GPRMC,093514,A,3722.8568,N,13549.4907,E,0.0,196.2,1807… や、$GPRMB,A,,,,,,,,,,,,A,A* といったASCIIコードの文字列です。 このNMEAデータでは、 $GPRMC,世界標準時(UTC),ステータス(有効ならA、無効ならV),緯度,経度,対地速度(ノット),進行方向(度),日付(UTC)のようにそれぞれ対応するパラメータがあり上記の$GPRMCにあてはめると、 $GPRMC,9時35分14秒,有効,北緯37度22.8568分,…となっております。 今回はこのプログラムで受信したNMEAデータから時刻,緯度,経度のみ表示させたいと考えているのですが、複数の文字列が存在する中から必要な部分のみ抜き出すにはどうすれば良いのかわからず質問させていただきました。何か良い方法があればよろしくお願いします。 以下は現在のプログラムと出力結果です。 #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<strings.h> #include<termios.h> #include<stdio.h> #define BAUDRATE B4800 #define MODEMDEVICE "/dev/ttyS0" int main() { int fd, c, res; int i=0; int j=0; struct termios oldtio, newtio; char buf[512]; if((fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ))==-1){ perror(MODEMDEVICE); exit(-1); } tcgetattr(fd, &oldtio); /*シリアルポートの設定を退避*/ bzero(&newtio, sizeof(newtio)); /*新しいポート設定の構造体クリア*/ newtio.c_cflag = (BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD); newtio.c_iflag = (IGNPAR | ICRNL); newtio.c_oflag = 0; newtio.c_lflag = ICANON; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); while (i==0) { res = read(fd,buf,512); buf[--res]=0; /* 文字の終端をセット*/ printf("%s\n",buf); j++; if(j==24)i++; /* 取得するNMEAセンテンス12種類と1行ずつの改行で、1セット24行のNMEAデータを得るために24行で出力終了/ } tcsetattr(fd, TCSANOW, &oldtio); /* 退避させた設定に戻す*/ close(fd); /* ポートを閉じる*/ return(0); } 出力結果(以下のNMEAデータが出力) $GPRMC,093514,A,3428.9468,N,13649.4907,E,0.0,196.2,180708,6.7,W,A*05 $GPRMB,A,,,,,,,,,,,,A,A*0B $GPGGA,093514,3428.9468,N,13649.4907,E,1,07,2.1,13.2,M,35.9,M,,*7E $GPGSA,A,3,03,06,07,,16,,21,,25,27,,,2.3,2.1,1.0*35 $GPGSV,3,1,11,03,76,315,47,06,72,017,51,07,21,318,47,13,24,282,00*7D $GPGSV,3,2,11,16,51,064,51,19,55,246,00,21,20,048,43,23,23,245,00*7C $GPGSV,3,3,11,25,40,311,46,27,14,320,44,31,19,149,00*4C $GPGLL,3428.9468,N,13649.4907,E,093514,A,A*40 $GPBOD,,T,,M,,*47 $PGRME,16.1,M,11.7,M,20.0,M*1D

すると、全ての回答が全文表示されます。

関連するQ&A