仅打印包含C中关键字的第一行和最后一行

时间:2015-09-24 10:35:42

标签: c pointers extract keyword

我上周开始学习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;
}

1 个答案:

答案 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