我上周开始学习C,即使是简单的任务对我来说也是一个挑战。目前我遇到了这个问题:我有一个包含许多行的txt文件,每个行都以一个关键字开头(对于那些知道它的人来说是NMEA格式):
$GPGGA,***001430.00***,.......
$GPRMC,001430.00,.......
$GPGSV,................ 1st time the message arrives
$GPGSA,................
----------
$GPGGA,***005931.00***,...............
$GPRMC,005931.00,............... last time
$GPGSV,.........................
$GPGSA,.........................
我想提取$ GPGGA行的最后一次出现的时间戳。直到现在我才能提取文件的第一行和最后一行(不幸的是,最后一行不是GPGGA消息)。我试图在文件中查找关键字 $ GPGGA ,然后从特定字节中查找字符串并将值存储在某些变量中(小时,分钟,秒) )。
任何建议都将不胜感激。非常感谢你的时间和帮助。
这是我的代码:
entint main(int argc, char **argv) {
FILE *opnmea;
char first[100], last[100]; //first and last time the message arrives
int hour,min;
float sec; // time of observation
char year[4], month[2], day[2]; // date of obs campaign
char time[7];
opnmea = fopen(argv[1], "r");
if (opnmea != NULL ) {
fgets(first, 100, opnmea); // read only first line of the file
if (strstr(first, "$GPGGA") != NULL)
{
sscanf(first + 7, "%2d%2d%f", &hour, &min, &sec);
printf("First arrival of stream: %d%d%f \n", hour, min, sec);
}
fseek(opnmea, 0, SEEK_SET);
while (!feof(opnmea)) {
if (strstr(first, "$GPGGA") != NULL) {
memset(last, 0x00, 100); // clean buffer
fscanf(opnmea, "%s\n", last);
}
}
printf("Last arrival of stream: %s\n", last);
fclose(opnmea);
}
else
{
printf("\nfile %s not found", argv[1]);
}
return 0;
}
答案 0 :(得分:3)
scanf
系列函数不了解换行符,它们被视为常规空格。如果您使用基于行的格式,最好在使用fgets
的行时读取,然后进一步处理这些行,可能使用sscanf
来扫描字符串。
无需使用feof
。用于读取的库函数提供指示文件末尾的特殊值。例如,fgets
将在出错时返回NULL
,或者如果已到达文件的末尾,则会返回#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *opnmea;
float first = -1; // first and ...
float last = -1; // ... last timestamp in seconds
char line[100];
if (argc != 2) {
fprintf(stderr, "Usage: prog nmeafile\n");
exit(1);
}
opnmea = fopen(argv[1], "r");
if (opnmea == NULL) {
fprintf(stderr, "Can't open '%s'.\n", argv[1]);
exit(1);
}
while (fgets(line, sizeof(line), opnmea)) {
int hrs, min;
float sec;
if (sscanf(line, "$GPGGA,%2d%2d%f", &hrs, &min, &sec) == 3) {
sec = hrs * 3600.0 + min * 60.0 + sec;
if (first < 0) first = sec;
last = sec;
}
}
printf("first: %8.2f sec\n", first);
printf("last: %8.2f sec\n", last);
printf("diff: %8.2f sec\n", last - first);
fclose(opnmea);
return 0;
}
。
如果您只对时间戳感兴趣,则不必保存这些行。特别是,不需要两个行缓冲器。提取信息并存储就足够了。
这是一个示例,显示了查找时间戳的第一个和最后一个匹配项的基本工作方式。我把小时,分钟和秒组合成单个值几秒钟。
table_1
ID | A
------
1 | a
2 | b
3 | c
table_2
ID | B
------
1 | x
1 | y
3 | z