(1)以前GPSで取得した測位データをRS232C通信でPCに表示するプログラムを作成するに当たって、多くの方に助言を頂けたことでなんとかNMEAデータを表示できるようになりました。
(2)そこで次の段階として、取得したNMEAデータに含まれる”緯度””経度””時刻”の要素のみ取り出して表示する方法として、strtok関数を用いたプログラムを教わり、用意した文章から必要な要素のみを出力する方法も確認できました。
(1)と(2)のプログラムをあわせて、受信したデータから緯度経度時刻のみを表示するプログラムを作成したいのですが、
assignment makes pointer from integer without
とコンパイル時に表示されてしまいます。ポインタの受け渡しに問題があるということでしょうか?どのように組み合わせれば受信データから必要なデータを表示できるようになるでしょうか。方法があればご教授お願いします。
以下が(1)と(2)のプログラムです。
(1)受信したデータをRS232C通信でPCに指定した行数表示するプログラム
#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;
unsigned 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);/*ボー:4800*/
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; j++;
printf("%s\n",buf);
//j++;
if(j==48)i++;/*NMEAセンテンス1セットは24行(12種と1行ずつのスペース)なのでここでは48行で2セット分のループ*/
}
tcsetattr(fd, TCSANOW, &oldtio);
close(fd);
return(0);
}
(1)実行結果
$GPRMC,081312,A,3428.9433,N,13549.4905,E,0.0,0.0,060808,6.7,W,A*06
$GPRMB,A,,,,,,,,,,,,A,A*
$GPGSA,A,3,03,06,07,,16,,21,,25,27,,,2.3,2.0,1.0*34
・・と48行このようなNMEAセンテンスを表示します。
(2)NMEAセンテンスから時刻、緯度、経度のみを出力
#include <stdio.h>
#include <string.h>
#include <math.h>
char buf[512]="$GPRMC,143514,A,3428.9468,N,13549.4507,E,0.0,196.2,180708,6.7,W,A*05"; /*緯度経度時刻がすべて含まれているGPRMCからデータを取得したいのでGPRMCのモデルを1行用意*/
void pnmea(void) {
int utc;
double lat; /*緯*/
double lon; /*経*/
char ew; /*東西*/
char ns; /*南北*/
char stat;
char *p;
/*一行のNMEAセンテンスから時刻緯度経度のみを取り出すために、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",&lat);
if ((p=strtok(NULL,","))==NULL) return;
ns=p[0];
if ((p=strtok(NULL,","))==NULL) return; /*経度*/
sscanf(p,"%lf",&lon);
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(lat/100.0), fmod(lat,100.0));
if (ew=='E') printf("東経"); else if (ns=='W') printf("西経");
printf("%.0lf度%.4lf分",floor(lon/100.0), fmod(lon,100.0));
printf("\n");
}
int main(void) {
pnmea();
return 0;
}
(2)実行結果
14時35分14秒(UTC) 北緯34度28.9468分東経135度49.4507分
(1)で得たデータを(2)でGPRMCか判別し、必要な部分を取り出し表示 したいと考えています。よろしくお願いします。
No.5ベストアンサー
- 回答日時:
こんな感じでどうでしょう?
#includeいろいろ
#include <strings.h> → #include <string.h>
#define いろいろ
char buf[512]; /* グローバル変数 */
void pnmea(void) {
関数の内容(bufの定義は消す)
}
int main(void) {
関数の内容(bufの定義は消す。pnmeaを呼び出す)
}
No.4
- 回答日時:
自分の勉強のためにNMEAパーサを書いてみるならそれはそれとして、私なら世の中にオープンソースで出ているNMEAパーサのソースコード見ちゃいます。
例えば http://sourceforge.net/projects/nmeap/ とか。この回答への補足
>Interestさん回答ありがとうございます。
そのような方法でも学習できるのですね。勉強になりました。ありがとうございます。
そのページはひらくとエラーが発生してしまうので、他のサイトも探して勉強してみます。
No.3
- 回答日時:
#include<string.h>
がインクルードされていないためstrtok( )関数の引数がint型と仮定されてしまっているようです
#include<strings.h>
がタイプミスではないでしょうか
この回答への補足
>php504さんありがとうございます。
本当ですね。すぐに変更して確認してみます。include文の誤りはエラーとして捕らえられないものなのでしょうか?
また、(1)と(2)を組み合わせたプログラムのとき、(2)の部分で扱われる”buf”は
res = read(fd,buf,512);
buf[--res]=0;
j++;
printf("%s\n",buf);
とあったprintf文に(2)のプログラムをほぼそのまま追加して表示方法を変更させたかったので、
res = read(fd,buf,512);
buf[--res]=0; /* 文字列終端をセット */
j++;
/*一行のNMEAセンテンスから時刻緯度経度のみを取り出すために、strtokで”,”ごとのトークンを得る*/
if ((p=strtok(buf,","))==NULL) return;
・・・・
のような形に変えたのですがこのような書き方で問題ないのでしょうか?
No.2
- 回答日時:
Cは「関数を呼び出す際は、実体を宣言するか、実体を宣言しないならプロトタイプを宣言してから呼び出す」事になっています。
ライブラリ関数の実体やプロトタイプは、通常「#include文」で指定した、ライブラリヘッダファイルの中で行われています。
で、Cは「実体もプロトタイプも宣言されてない関数が呼び出された場合、関数へのすべての引数は、取りあえず、仮にすべてint型だと思っておく」と言う事をします。
その後で、関数の実体が現れたり、プロトタイプ宣言に出くわすと、引数の引き渡しを、その宣言部に書かれている引数の型に合わせ、暗黙のキャストを行います。
この時「仮にすべてint型だと思っていたら、実はポインタだった」と言う事が起き、それが原因で「引数にポインタを要求している関数で(実はポインタだったけど、仮にint型だと思われてしまい、結局はint型になっちゃった)int型の引数が渡されているので、キャストも何もしないでint型をポインタだと思いこんで渡したぞ」と言う警告が出ます。
たぶん「main関数は下に書く」と覚えたでしょうが、これは「呼ばれる関数を上に、呼び出している部分を下に書く事になり、関数の実体が宣言されたあとで、関数が呼び出されるので、いちいちプロトタイプ宣言しなくても済むから」です。
そういう訳で、
assignment makes pointer from integer without
の警告が出るのは
・「#include文」でヘッダファイルを読み込むのを忘れた
・プロトタイプ宣言するのを忘れている
・関数を宣言している部分よりも上(前)で、宣言前の関数を呼び出している
・関数に渡す引数の個数、タイプを間違っている
などです。
この回答への補足
>chie65536さん回答いただきありがとうございます。
assignment makes pointer from integer withoutを出してしまう要因についてとても参考になりました。
>(1)「#include文」でヘッダファイルを読み込むのを忘れた
>(2)プロトタイプ宣言するのを忘れている
>(3)関数を宣言している部分よりも上(前)で、宣言前の関数を呼び出している
>(4)関数に渡す引数の個数、タイプを間違っている
以下が組み合わせてつくってみたプログラムになります。
chie65536さんに頂いた例で確認すると(3)(4)に問題があるのでしょうか?
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<strings.h>
#include<termios.h>
#include<stdio.h>
#include<math.h>
#define BAUDRATE B4800
#define MODEMDEVICE "/dev/ttyS0"
int main()
{
int fd, c, res;
int i=0;
int j=0;
int utc;
char stat;
char ns;
char ew;
char *p;
double lat;
double lon;
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);/*ボー:4800*/
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; /* 文字列終端をセット */
j++;
/*一行のNMEAセンテンスから時刻緯度経度のみを取り出すために、strtokで”,”ごとのトークンを得る*/
if ((p=strtok(buf,","))==NULL) return;
if (strcmp(p,"$GPRMC")!=0) return; /*センテンスの先頭は$GPRMCか?*/
if ((p=strtok(NULL,","))==NULL) return; /*utc:世界標準時*/
sscanf(p,"%d",&utc);
if ((p=strtok(NULL,","))==NULL) return; /*stat:ステータス*/
stat=p[0];
if ((p=strtok(NULL,","))==NULL) return; /*lat:緯度*/
sscanf(p,"%lf",&lat);
if ((p=strtok(NULL,","))==NULL) return; /*ns:南北*/
ns=p[0];
if ((p=strtok(NULL,","))==NULL) return; /*lon:経度*/
sscanf(p,"%lf",&lon);
if ((p=strtok(NULL,","))==NULL) return; /*ew:東西*/
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(lat/100.0), fmod(lat,100.0));
if (ew=='E') printf("東経"); else if (ns=='W') printf("西経");
printf("%.0lf度%.4lf分",floor(lon/100.0), fmod(lon,100.0));
printf("\n");
printf("%d周目\n",j);
if(j==48)i++;/*NMEAセンテンス1セットは24行(12種と1行ずつのスペース)なのでここでは48行で2セット分のループ*/
}
tcsetattr(fd, TCSANOW, &oldtio); /* 退避させた設定に戻す */
close(fd); /* COM1のシリアルポートを閉じる */
return(0);
}
出力結果
rsgps.c: In function ‘main’:
rsgps.c:47: 警告: assignment makes pointer from integer without a cast
rsgps.c:49: 警告: assignment makes pointer from integer without a cast
rsgps.c:51: 警告: assignment makes pointer from integer without a cast
rsgps.c:53: 警告: assignment makes pointer from integer without a cast
rsgps.c:55: 警告: assignment makes pointer from integer without a cast
rsgps.c:57: 警告: assignment makes pointer from integer without a cast
rsgps.c:59: 警告: assignment makes pointer from integer without a cast
No.1
- 回答日時:
その警告が出てるのはどの行?
この回答への補足
>Tacosanさん回答ありがとうございます。
(1)のprintf("%s\n",buf);
部分のかわりに(2)を入れてコンパイルしてみました。
while (i==0) {
res = read(fd,buf,512);
buf[--res]=0; /* 文字列終端をセット */
j++;
/*一行のNMEAセンテンスから時刻緯度経度のみを取り出すために、strtokで”,”ごとのトークンを得る*/
47行目→if ((p=strtok(buf,","))==NULL) return;
if (strcmp(p,"$GPRMC")!=0) return; /*センテンスの先頭は$GPRMCか?*/
if ((p=strtok(NULL,","))==NULL) return; /*utc:世界標準時*/
sscanf(p,"%d",&utc);
if ((p=strtok(NULL,","))==NULL) return; /*stat:ステータス*/
stat=p[0];
if ((p=strtok(NULL,","))==NULL) return; /*lat:緯度*/
sscanf(p,"%lf",&lat);
if ((p=strtok(NULL,","))==NULL) return; /*ns:南北*/
ns=p[0];
if ((p=strtok(NULL,","))==NULL) return; /*lon:経度*/
sscanf(p,"%lf",&lon);
if ((p=strtok(NULL,","))==NULL) return; /*ew:東西*/
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(lat/100.0), fmod(lat,100.0));
if (ew=='E') printf("東経"); else if (ns=='W') printf("西経");
printf("%.0lf度%.4lf分",floor(lon/100.0), fmod(lon,100.0));
printf("\n");
printf("%d周目\n",j);
if(j==48)i++;/*NMEAセンテンス1セットは24行(12種と1行ずつのスペース)なのでここでは48行で2セット分のループ*/
}
tcsetattr(fd, TCSANOW, &oldtio); /* 退避させた設定に戻す */
close(fd); /* COM1のシリアルポートを閉じる */
return(0);
}
gcc -lm rsgps.c
rsgps.c: In function ‘main’:
rsgps.c:47: 警告: assignment makes pointer from integer without a cast
rsgps.c:49: 警告: assignment makes pointer from integer without a cast
rsgps.c:51: 警告: assignment makes pointer from integer without a cast
rsgps.c:53: 警告: assignment makes pointer from integer without a cast
rsgps.c:55: 警告: assignment makes pointer from integer without a cast
rsgps.c:57: 警告: assignment makes pointer from integer without a cast
rsgps.c:59: 警告: assignment makes pointer from integer without a cast
で以上のように出力されました。どのように組み合わせれば解決できるでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
ftoa の作り方
-
C言語のfor文です。 繰り返しの...
-
エンディアン:2バイトのデー...
-
絶対パスからのファイル名の切...
-
テキストデータをそのままバイ...
-
charでの計算?
-
strtol関数 自作
-
C言語の入力した文字を反転させ...
-
3桁区切(コンマ)記号をつけ...
-
「ポインタのポインタ」を使っ...
-
【C言語】文字型と整数型の違い
-
コマンドラインに入力されてい...
-
c言語配列の結合についてです。...
-
配列をnビットシフトする
-
str系関数を使わずに二つの文字...
-
【C言語】構造体内の領域解放(...
-
文字列から空白を取り除きたい...
-
atoi( ) の反対をやりたい
-
OpenCVで32bit ヘッダ無しRaw画...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
charからLPTSTRへの変換方法
-
charでの計算?
-
配列をnビットシフトする
-
'const char *' 型は 'char *' ...
-
型変換
-
テキストデータをそのままバイ...
-
文字列から空白を取り除きたい...
-
CStringをwchar_tに変換したい
-
絶対パスからのファイル名の切...
-
fgetsなどのときのstdinのバッ...
-
ネットワークにつながっている...
-
str系関数を使わずに二つの文字...
-
3桁区切(コンマ)記号をつけ...
-
atoi( ) の反対をやりたい
-
double型の値をchar配列に変換...
-
C言語のfor文です。 繰り返しの...
-
switch文で文字を比較すること...
-
ファイル名である文字列からbas...
-
c++ 文字列を入力して、一文字...
-
strncpyと_tcsncpy_sのヌルの扱...
おすすめ情報