• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:GPS受信の抜き出しについて)

GPS受信の抜き出しについて

επιστημη(@episteme)の回答

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

strtok() 使えば','区切りで文字列を抽出できるので、 'V'/'N'の直後を取り出せるでしょ。

gmwvmmgm
質問者

お礼

返信が遅くなってしまい申し訳ありませんでした。 strtok()ですか… 盲点でした。 試しにstrtok()を使って if((p = strtok(sBuf,",")) == NULL); if(strcmp(p,"$GPRMC") != 0); /*センテンスの先頭は$GPRMCか?*/ if ((p=strtok(NULL,","))==NULL); /*utc:世界標準時*/ sscanf(p,"%d",&utc); if ((p=strtok(NULL,","))==NULL); /*stat:ステータス*/ stat=p[0]; if ((p=strtok(NULL,","))==NULL); /*lat:緯度*/ sscanf(p,"%lf",&lat); if ((p=strtok(NULL,","))==NULL); /*ns:南北*/ ns=p[0]; if ((p=strtok(NULL,","))==NULL); /*lon:経度*/ sscanf(p,"%lf",&lon); if ((p=strtok(NULL,","))==NULL); /*ew:東西*/ ew=p[0]; と打ち込んでみたところ上手く抜き出すことができました。 ご多忙の中、回答していただきまことにありがとうございました。 ベストアンサーに選ばせていただきます。

関連するQ&A

  • PICとPCでのシリアル通信

    PICとPC間でのシリアル通信を行ってるんですけどうまくいきません。ハイパーターミナル使えばうまくいくんでPIC側のソース(C)はうまくいってると思います。ハイパーターミナルを使わずにシリアルの送受信のプログラム(C++)を組んでるんですけどうまくいかなくて。。。 アドバイスなどお願いします!!どこが違うんでしょうか。。。 ●PC側のソース(C++) #include "stdafx.h" #include <stdlib.h> #include <windows.h> #include<iostream> using namespace std; #define COM_PORT_NAME "COM1" #define BAUD_RATE 9600 #define BYTE_SIZE 8 #define PARITY EVENPARITY #define STOP_BIT TRUE #define F_PARITY ONESTOPBIT HANDLE hComm; // シリアルポートとの通信ハンドル bool ComInit() { // シリアルポートを開ける hComm = CreateFile( COM_PORT_NAME, /* シリアルポートの文字列 */ GENERIC_READ | GENERIC_WRITE, /* アクセスモード:読み書き */ 0, /* 共有モード:他からはアクセス不可 */ NULL, /* セキュリティ属性:ハンドル継承せず */ OPEN_EXISTING, /* 作成フラグ: */ FILE_ATTRIBUTE_NORMAL, /* 属性: */ NULL /* テンプレートのハンドル: */ ); if (hComm == INVALID_HANDLE_VALUE) { printf("シリアルポートを開くことが出来ませんでした。\n"); return false; } // 通信属性を設定する DCB dcb; GetCommState(hComm, &dcb); /* DCB を取得 */ dcb.BaudRate = BAUD_RATE; dcb.ByteSize = BYTE_SIZE; dcb.Parity = PARITY; dcb.fParity = STOP_BIT; dcb.StopBits = F_PARITY; SetCommState(hComm, &dcb); /* DCB を設定 */ return true; } void ComEnd() { // ハンドルを閉じる CloseHandle(hComm); } bool WriteData(char *buff, unsigned int data_size) { DWORD dwWritten; /* ポートへ書き込んだバイト数 */ WriteFile(hComm, buff, data_size, &dwWritten, NULL); if (dwWritten!=data_size) { printf("データの送信に失敗しました。\n"); return false; } return true; } bool ReadData(char *buff, unsigned int max_size) { DWORD dwErrors; /* エラー情報 */ COMSTAT ComStat; /* デバイスの状態 */ DWORD dwCount; /* 受信データのバイト数 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ClearCommError(hComm, &dwErrors, &ComStat); dwCount = ComStat.cbInQue; if (dwCount > max_size) { printf("バッファサイズが足りません。\n"); return false; } ReadFile(hComm, buff, dwCount, &dwRead, NULL); if (dwCount != dwRead) { printf("データの受け取りに失敗しました。\n"); return false; } return true; } int main(int argc, char* argv[]) { char ch; while(1){ cin >> ch; printf("入力 %c\n", ch); ComInit(); WriteData(&ch, strlen(&ch)); ReadData(&ch, strlen(&ch)); ComEnd(); } return 0; }

  • シリアル通信でのデータ受信

    シリアル通信にてデータを連続的に受信するプログラムを つくりたいと思っています. 以下のプログラムを作成して, main関数のcountを増やして,繰り返しreadを行おうとすると, 出力結果として, 時,分,秒,ID,値B,値C,値Dというフォーマットで 0, 9,30, 1,514,708,542,290 0, 9,30, 2,515,707,542,288 0, 9,30, 3,514,709,542,287 0, 9,30, 4,514,707,543,289 0, 9,30, 5,514,708,542,289 0, 9,30, 6,514,708,542,292 0, 9,30, 7,514,708,542,291 0, 9,30, 8,514,708,542,289 0, 9,30, 9,514,708,543, 0, 9,39,35,514,708,542,289 (この後フが連続) フフフフフフフフフフフフフフフ ク 0, 9,39,36,514,708,542,290 0, 9,39,37,515,709,541,291 0, 9,39,38,514,707,542,286 0, 9,39,39,514,708,542,281 0, 9,39,40,514,708,542,284 0, 9,39,41,514,707,542,286 0, 9,39,42,514,707,542,290 0, 9,39,43,514,709,542,290 0, 9,30, 9,514,708,543, 0, 9,39,35,514,708,542,289 フフフフフフフフフ・・・再びフ となってしまいます. 問題としては ・フがたくさんでてきてしまう. ・1サイクルの最後で改行ができていない ・1サイクルが終わって次のサイクルに入る時までの 間にデータが失われている. ・2サイクル目になぜか1サイクル目の値が残っている? などがあります. どなたか解決方法を教えていただけると大変助かります. よろしくお願いします. ------------------------------- #include "stdafx.h" #include <stdlib.h> #include <windows.h> #include <string.h> #include <stdio.h> #define COM_PORT_NAME "COM2" #define BAUD_RATE 57600 #define BYTE_SIZE 5000 //250 #define PARITY NOPARITY //EVENPARITY #define STOP_BIT TRUE #define F_PARITY ONESTOPBIT HANDLE hComm; // シリアルポートとの通信ハンドル bool ComInit() { // シリアルポートを開ける hComm = CreateFile( COM_PORT_NAME, /* シリアルポートの文字列 */ GENERIC_READ | GENERIC_WRITE, /* アクセスモード:読み書き */ 0, /* 共有モード:他からはアクセス不可 */ NULL, /* セキュリティ属性:ハンドル継承せず */ OPEN_EXISTING, /* 作成フラグ: */ FILE_ATTRIBUTE_NORMAL, /* 属性: */ NULL /* テンプレートのハンドル: */ ); if (hComm == INVALID_HANDLE_VALUE) { printf("シリアルポートを開くことが出来ませんでした。\n"); return false; } // 通信属性を設定する DCB dcb; GetCommState(hComm, &dcb); /* DCB を取得 */ dcb.BaudRate = BAUD_RATE; dcb.ByteSize = BYTE_SIZE; dcb.Parity = PARITY; dcb.fParity = STOP_BIT; dcb.StopBits = F_PARITY; SetCommState(hComm, &dcb); /* DCB を設定 */ return true; } void ComEnd() { // ハンドルを閉じる CloseHandle(hComm); } bool ReadData(char *buff, unsigned int max_size) { DWORD dwErrors; /* エラー情報 */ COMSTAT ComStat; /* デバイスの状態 */ DWORD dwCount; /* 受信データのバイト数 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ClearCommError(hComm, &dwErrors, &ComStat); dwCount = ComStat.cbInQue; FILE *fid; fid=fopen("test.txt", "w"); printf("%d %d\n", dwCount, max_size); fprintf(fid,"%d %d\n", dwCount, max_size); fclose(fid); if (dwCount > max_size) { printf("バッファサイズが足りません。\n"); return false; } if(hComm != NULL){ ReadFile(hComm, buff, dwCount, &dwRead, NULL); if (dwCount != dwRead) { printf("データの受け取りに失敗しました。\n"); return false; } } return dwRead; } int main(int argc, char* argv[]) { char buff[BYTE_SIZE]; int count = 0; int data_length; FILE *fid2; fid2=fopen("test2.txt","w"); ComInit(); while(1){ if(count == 2) break; count++; data_length=ReadData(buff, strlen(buff)); printf("%s ",buff); fprintf(fid2, "%s ",buff); } fclose(fid2); ComEnd(); return 0; }

  • シリアル通信の受信待ちについて

    シリアル通信で10Byte受信するまで待ち続けたいのですが、0ByteでReadFileが抜けてしまいます。 ReadFileの最後のパラメタが、NULLならば第3パラメタの値まで待ち続けると思っていたのですが、なにか設定が足りないのでしょうか? タイムアウト値は0にしています。(色々変えて見ましたが同じでした) HANDLE hComm; /* シリアルポートのハンドル */ DCB dcb; char* pszBuf="1234567890"; /* 書込・読込領域 */ hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); GetCommState(hComm, &dcb); /* DCB を取得 */ dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.ReadIntervalTimeout = 100; dcb.ReadTotalTimeoutMultiplier = 0; dcb.ReadTotalTimeoutConstant = 0; dcb.WriteTotalTimeoutMultiplier = 10; dcb.WriteTotalTimeoutConstant = 500; SetCommState(hComm, &dcb); /* DCB を設定 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ReadFile(hComm, pszBuf, 10, &dwRead, NULL);

  • C++でArduinoをコントロールしたいのですが

    VC++から数値データ(0-100)を送信し、Arduinoに接続されているファンを受信した数値でPWMコントロールしたいのですが、接続を確立したその後からプログラミングの仕方がわかりません。 どのようにしてデータを送信すればよいのでしょうか? 以下のようにして接続を行っています。 //COMポートハンドル HANDLE hComm; hComm = CreateFileA("\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); //ポートの接続確認 printf("Arduino COM") ; if (hComm == INVALID_HANDLE_VALUE) printf(":not opened\n") ; else{ DCB lpTest; GetCommState(hComm,&lpTest); lpTest.BaudRate = CBR_9600; lpTest.ByteSize = 8; lpTest.Parity = NOPARITY; lpTest.StopBits = ONESTOPBIT; SetCommState(hComm,&lpTest); printf(":OPENED\n") ; WriteFile(hComm, buf,strlen(buf),&write, NULL); } //COMポートハンドルの解放 CloseHandle(hComm); なおArduino側のプログラムは以下のものを使用しています。 //読み取り値の変数 int val=0; void setup(){ //シリアル通信開始 Serial.begin(9600); } void loop(){ //データが0個より多いときの時 if(Serial.available()>0){ //データの読み込み val=Serial.read(); //合図用データ送信(1バイト) Serial.print(65,BYTE); } //アナログ出力(11番ピン)に読み込み値を入れる analogWrite(11,val); }

  • 通信(送信)のプログラム

    bool WriteData(char *buff, unsigned int data_size) {     DWORD dwWritten; /* ポートへ書き込んだバイト数 */ WriteFile(hComm, buff, data_size, &dwWritten, NULL); if (dwWritten!=data_size) { printf("データの送信に失敗しました。\n"); return false; } return true; } 上の関数はシリアル通信の送信する関数なんですが、これに数値などを入れたいんですが、char型のため、一文字しか入れれません。たとえば、01ならchar型の0とchar型の1を別々に送らないとだめなんですが、このようにするしか無理なんでしょうか?int型の数値を好きなように入れて送りたいんですが。あと、OxFFのように16進数も入れれると便利なんですが。駄文ですいません。プログラムの知識が浅はかですいません。

  • シリアル通信プログラム(受信)について

    現在、シリアル通信をする(受信のみ)プログラムを作成しています。 接続先は1秒ごとに10バイトのデータを自動で送信してきます。 現段階でPC側でデータを受信できることは確認できました。 しかし、受信データが文字化け(出力結果が{や■などがでています)しており、その原因がわかりません。 どこが問題なのか教えていただけないでしょうか? また、接続先からは10バイトのうち最初の2バイトは固定の値(0x2b,0x22)がでてくるはずなのですが、それもでてきていません。これも文字化けで見えていないだけでしょうか? 文字化けしても周期的に固定の値に対応した文字がでてくるものだと思ったのですが、でてきていません。 (ソースで50バイトまでみているのはこの周期性を確認するためです) シリアル通信を初めてさわるので、考え方自体間違っているかもしれませんが 配列pszBufに1つずつ、受信された1バイトのデータが格納されていると思っています。 個人的にはprintfでの表記(%cがいけない?)に間違いがあるかと疑っています。 ご回答よろしくお願いいたします。 (環境) Visual C++ 2008 (C/C++) (シリアルポート設定) ボーレート 9600bps パリティ   なし ストップビット 1 データビット 8 (ソース) ※ポートの設定は省略。受信部のみ記述 HANDLE hComm; DWORD dwErrors; COMSTAT ComStat; char pszBuf[1024]; DWORD dwRead; ClearCommError(hComm, &dwErrors, &ComStat); ReadFile(hComm, pszBuf, 50, &dwRead, NULL);  //50バイトまでデータを取得 for(int i=0;i<50;i++){ printf("%c\n",pszBuf[i]); } (参考URL) http://www.geocities.jp/terukat/_geo_contents_/win/comm.html

  • char型をfloat型に変換

    GPSからシリアルポートに流れてくるコンマ区切りのフォーマットをいったんcharにいれて、トークンでぶちぶち切って、違う変数に格納したいです。 流れてくるデータは、 $GPGGA,042449.00,3449.30669291,N,13531.38645000,E,1,4,4.4,81.885,M,34.255,M,,*6D のような数値です。緯度経度や日付等のデータです。 緯度や経度の数値をfloatやdoubleに変換して変数に格納したいのですが、どうしたらよいでしょうか? そのまましたらエラーが出てしまいます。 以下は数値をブチブチ切って表示させるプログラムです。 #include <windows.h> #include <stdio.h> int main(void) { char szSend[] = "$GPGGA,000000.00,0000.00000000,N,00000.00000000,E,0,0,0.0,00.000,M,00.000,M,,*00"; char szBuf[sizeof(szSend)]="$GPGGA,042449.00,3449.30669291,N,13531.38645000,E,1,4,4.4,81.885,M,34.255,M,,*6D"; char *ptr; ptr=strtok(szBuf,","); printf("%s\n",ptr);//$GPGGA ptr=strtok(NULL,","); printf("%s\n",ptr);//時間 ptr=strtok(NULL,","); printf("%s\n",ptr);//緯度 ptr=strtok(NULL,","); printf("%s\n",ptr);//N北 ptr=strtok(NULL,","); printf("%s\n",ptr);//経度 ptr=strtok(NULL,","); printf("%s\n",ptr);//E東 ptr=strtok(NULL,","); ・ ・ ・ ・ return 0; } コンパイラはmicrosoftvisualC++6.0です。 floatとかboubleにしたいのは緯度や経度の数値を計算して扱いやすいデータにするためです。 よろしくお願いします。

  • VC++でrs232c通信

    ハイパーターミナルで試したところ、以下のプログラムにも書いてありますが C,OL,1と入力すると OKという文字が返ってくるというものなのですが、 printf("%s,オンラインに失敗しました\n",l);の所で lがnoneのままでした。 説明書にはC,OL,1[CR][LF]と入力すると OK<CR><LF>またはER,n<CR><LF>と返ってくると書いてありました。 色々調べはしたのですが、わかりません。 根本から間違っているような気もします。 何処が間違っているかご指摘をお願いします。 ************************************* HANDLE COMHandle; DWORD dwRoad,dwWrite,dwError,dwCount; COMSTAT ComStat; char *l="none"; COMHandle=CreateFile("COM3",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//ハンドルの取得 if ( COMHandle == INVALID_HANDLE_VALUE ) { printf("COMport Open Error!\n"); getch(); exit(1); } DCB dcb; GetCommState(COMHandle,&dcb);//シリアルポートの状態を取得 dcb.BaudRate=2400;//ボーレート,伝達速度,bps dcb.ByteSize = 8; // データサイズ,bit dcb.Parity = NOPARITY; // パリティ:エラー検出 dcb.StopBits = ONESTOPBIT; // ストップビット SetCommState(COMHandle,&dcb); // シリアルポートの状態を設定 ncf1="C,OL,1\r\n";//入力コマンド WriteFile(COMHandle,ncf1,strlen(ncf1),&dwWrite,NULL); ClearCommError(COMHandle,&dwError,&ComStat); dwCount=ComStat.cbInQue; ReadFile(COMHandle,l,dwCount,&dwRoad,NULL); if(l!="OK\r\n"){ printf("%s,オンラインに失敗しました\n",l); getch(); exit(1); }

  • シリアル通信のポートオープン

    シリアル通信のテストプログラムを作成中でして、一通り動作するようになったのでエラー処理を確認しようとしたところ、存在しないCOMポート?なのにオープンが成功したと処理してしまいます。 環境  P社のノートパソコン  Windows XP Pro SP3  Visual C++6.0 SP6  USB接続のRS-232C変換アダプタを使用  デバイスマネージャでは、拡張ポートはCOM4のみとなっている  ハイパーターミナルの「接続の設定」では、接続方法の選択肢にCOM3とCOM4の2つがある ・COM4を使うと、オープン後、正常に通信できます。 ・COM3を使うと、オープンは出来るが、通信は出来ません。 ソースを記載します。 if(HANDLE_CHECK(m_hComm) == FALSE){ ss.Format("COM%d", m_nRsPort); m_hComm = ::CreateFile(ss, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(HANDLE_CHECK(m_hComm) == TRUE){ dcb.DCBlength = sizeof(DCB); if(::GetCommState(m_hComm, &dcb) != FALSE){ dcb.BaudRate = m_nRsBaudrate; dcb.Parity = m_nRsParity; ・ ・ ・ ・ ・ ・ if(::SetCommState(m_hComm, &dcb) != FALSE){ COM3の場合もCOM4の場合もここを通っている。 } else{ } } } } COM3のオープン時、エラーの検知は出来ないのでしょうか? よろしくお願いします。

  • カレンダーがうまく表示されない

    開始月と終了月を指定して、3か月ごとにカレンダーを改行する プログラムを作ってみました。 ところが、動作をさせてみたところ7月が配列tuki[12]において31日 と指定しているのにも関わらず25日分しか表示されません。 それと、たまに4月分が24日分しか表示されません。(試した限りでは、 4月を終了月に指定するとそうなりました。) なにがおかしいためにこうなってしまうのでしょうか。 よろしくお願いいたします。 #include<stdio.h> #include<string.h> /*月の最初の日をメインプログラムに返す*/ int getyoubi(int year,int month,int day) { if(month==1 || month==2 ) { year--; month +=12; } return ((year+year/4-year/100+year/400+(13*month+8)/5 + day)%7); } /*カレンダーを3か月分表示させる*/ void print(char s[3][7][22],int n) { int i,j; for(i=0;i<n;i++) { printf("%s ",s[i][0]); } printf("\n"); for(i=0;i<n;i++) { printf(" 日 月 火 水 木 金 土 "); } printf("\n"); for(i=0;i<n;i++) { printf("---------------------- "); } printf("\n"); for(i=1;i<7;i++) { for(j=0;j<n;j++) { printf("%s ",s[j][i]); } printf("\n"); } printf("\n"); } int main(void) { int nen1,tuki1,nen2,tuki2,tukiho,nenho,tukih,w,j; char sbuf[3][7][22]; int tuki[12]={31,28,31,30,31,30,31,31,30,31,30,31}; int k; char tmp[4]; int count=0; printf("カレンダーを表示します。\n"); printf("開始年月を入力せよ。\n"); printf("年:"); scanf("%d",&nen1); printf("月:"); scanf("%d",&tuki1); printf("終了年月を入力せよ。\n"); printf("年:"); scanf("%d",&nen2); printf("月:"); scanf("%d",&tuki2); /*最大3カ月分のカレンダーを格納する。*/ do{ w=getyoubi(nen1,tuki1,1); sprintf(sbuf[count][0],"%10d / %02d ",nen1,tuki1); for(k=1;k<7;k++) { sbuf[count][k][0]='\0'; } sprintf(sbuf[count][1],"%*s",3*w,""); k=1; for(j=1;j<=tuki[tuki1-1];j++) { sprintf(tmp,"%3d",j); strcat(sbuf[count][k],tmp); if((j+w-1)%7==6) { k++; } } do{ if((j+w-1)%7==6) { sprintf(sbuf[count][k],"%21s",""); } else { do{ strcat(sbuf[count][k]," "); j++; }while((j+w-1)%7!=0); } k++; }while(k!=7); count++; if(count==3) { print(sbuf,count); count=0; } tuki1++; if(tuki1==13) { tuki1=1; nen1++; } }while(nen1<nen2 || nen1==nen2 && tuki1<=tuki2); if(count) { print(sbuf,count); } return 0; }