大学卒業間近の大学4年生です。
現在、卒業研究の一環でシリアル通信でGPSの構文をテキストファイルに書き込むプログラムを作成しています。
生データをテキストファイルに書き込むまではできたのですが…
なにぶん中途半端にプログラムの勉強をしていたのでそこから大事な部分を抜き出す作業がわからなくて困っています。(サイトにあるサンプルプログラムを参考にしてもエラーばかりが出てしまいます。)
北緯と東経の数値のみを抜き出して書き込むプログラムを作成したいのですがどの部分にどういう文を打ち込めばいいのでしょうか?
お分かりの方、どうか教えて貰えませんでしょうか?
ちなみに環境はC++で使っているソフトはMicrosoft Visual Studioです。
現在出来ているプログラムは以下のとおりです。
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int main(void)
{
printf("program start\n");
/// 変数宣言
int i=0;
/// シリアル通信データ用変数宣言
char sBuf[100]; //char sBuf[1]; //char str[100];
char strT[50] = {0};
char strN[20] = {0};
char strE[20] = {0};
unsigned char flag_data = 0;
/// シリアル通信設定用変数宣言
HANDLE hComm;
int baudRate = 9600; /// ボーレート9600bps
unsigned long nn;
DCB dcb;
COMMTIMEOUTS cto;
///データ保存用変数宣言
FILE *ofile;
errno_t err;
///
/// シリアルポートの初期化、オープン
///
printf("Open Serial Port\n");
BOOL InitComPort();
hComm = CreateFile(
"\\\\.\\COM3",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
/// ポートオープンエラー処理
if ( hComm == INVALID_HANDLE_VALUE )
{
printf("Serial Port Open Error!\n");
exit(1);
}
else {}
///
/// シリアルポートの設定
///
printf("Setup Serial Port\n");
GetCommState( hComm, &dcb ); // シリアルポートの状態を取得
dcb.BaudRate = baudRate;
SetCommState( hComm, &dcb ); // シリアルポートの状態を設定
GetCommTimeouts( hComm, &cto ); // タイムアウトの設定状態を取得
cto.ReadIntervalTimeout = 1000;
cto.ReadTotalTimeoutMultiplier = 0;
cto.ReadTotalTimeoutConstant = 1000;
cto.WriteTotalTimeoutMultiplier = 0;
cto.WriteTotalTimeoutConstant = 0;
SetCommTimeouts( hComm, &cto ); // タイムアウトの状態を設定
///
/// シリアルポート通信
///
while(1)
{
///
/// データ受信
///
/*
/// シリアルポートから一文字受信して表示
ReadFile( hComm, sBuf, 1, &nn, 0 );
if(nn != 0)
{
printf("%c",sBuf[0]);
}
*/
/// シリアルポートから一行受信して表示
memset(sBuf, NULL, sizeof(sBuf)); /// sBufの初期化
ReadFile( hComm, sBuf, sizeof(sBuf), &nn, 0); /// sBufで一行分データを受信
printf("%s", sBuf); /// 受信したデータを表示
for(i=0; i<sizeof(sBuf); i++)
{
if(sBuf[i] != NULL)
{
printf("%c", sBuf[i]);
}
else{}
}
///
/// 生データの保存
///
err = fopen_s(&ofile,"puredata.txt","a"); ///"a":追加書き込み専用
if(err != 0)
{
printf("ERROR! puredata was not opened\n");
exit(1);
}
else
{
while(1)
{
ReadFile( hComm, sBuf, 1, &nn, 0 ); // シリアルポートに対する読み込み
printf("%c",sBuf[0]);
if(sBuf[0] != EOF)
{
fprintf(ofile,"%c",sBuf[0]); //fprintf(stdout,"%s",str);
}
else
{
printf("\n");
break;
}
///
/// データ処理
///
///
/// 処理データの保存
///
}
printf("program end\n");
return(0);
}
出力結果
(例 ※場所特定防止のためGPSがうまく受信されていないパターンを載せています)
program start
program end
$GPRMC,120004.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7B
$GPRMC,120005.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7A
$GPRMC,120006.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*79
$GPRMC,120007.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*78
書き込まれたテキストファイル
$GPRMC,120004.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7B
$GPRMC,120005.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*7A
$GPRMC,120006.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*79
$GPRMC,120007.000,V,0000.0000,N,00000.0000,E,000.0,000.0,280606,,,N*78
出力してほしい数値は構文の最初のV,後の0000.0000と、そのあとのN,後の00000.0000です。
なるべく生データも別に保存しておきたいので下にある「データ処理」「処理データの保存」の中で処理したいのですが……
何卒、よろしくお願いします。
お礼
返信が遅くなってしまい申し訳ありませんでした。 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]; と打ち込んでみたところ上手く抜き出すことができました。 ご多忙の中、回答していただきまことにありがとうございました。 ベストアンサーに選ばせていただきます。