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

Print only first and last line that contains a key word in C

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

scanf 函数族不知道换行符,它们被视为普通的白色 space。如果您有基于行的格式,最好使用 fgets 读取 while 行,然后进一步处理这些行,也许使用 sscanf,它会扫描一个字符串。

不需要使用feof。用于读取的库函数提供指示文件结尾的特殊值。例如,fgets 将 return 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;
}