如何在C中逐行读取已知格式的文件

时间:2017-09-28 14:35:54

标签: c file input io output

文件格式如下

month day hour:min:sec process: message

示例:

Aug 13 12:20:34 automount[1478]: add_host_addrs: hostname lookup failed

我试图逐行读取并读取每行,确定'message'是否包含单词“fail”。

运行时我没有输出,请告诉我出错的地方,谢谢!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define INPUT_SIZE 80

int main()
{
    FILE* file = fopen("logfile", "r");

    char month;
    int day, hour, min, sec;
    char process[INPUT_SIZE];
    char message[INPUT_SIZE];
    char line[INPUT_SIZE];


    if (fgets(line, INPUT_SIZE, file) == NULL)
    {
        perror("Error opening file");
    }
    else
    {
        sscanf("%3s %2d %2d:%2d:%2d %s %s", &month, &day, &hour, &min, &sec, &process, &message);
        printf("%3s %2d %2d:%2d:%2d %s %s\n", month, day, hour, min, sec, process, message);

        while (strstr(message, "fail"))
        {
            /* do something */
        }
    }


    fclose(file);
    if(line == NULL)
    {
        free(line);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:2)

您对sscanf()的使用不正确。

使用

sscanf(line, "%3s %2d %2d:%2d:%2d %s %[^\n]", month, &day, &hour, &min, &sec, process, message);

其中line是您要扫描的字符串。

而不是

sscanf("%3s %2d %2d:%2d:%2d %s %s", &month, &day, &hour, &min, &sec, &process, &message);

请注意,为了读入字符串(使用%s),您使用的是字符数组而不是单个字符。 由于month必须包含多个字符,因此它应该是一个字符数组。

当数组的名称衰减到其基址时,在提供字符串的地址时不需要&运算符。
即,...%s %s", month, ...process, message)

输入字符串的message部分由多个单词组成。通常fscanf()会在第一个空格或换行符后停止读取。要继续扫描到换行符,您可以使用%[^\n]。它将读取直到遇到换行符。这种方式message将包含整个hostname lookup failed,而不仅仅是hostname

现在message有完整的消息,strstr(message, "fail")将返回非NULL,控件将进入while循环。

line已在堆栈上分配,而不是在堆上。你不应该做free(line)

缓冲区line的大小将大于其他字符串,这些字符串应该将部分数据保存为line fgets()。因此,可能不需要对所有字符串使用相同的大小。

编辑:您可以使用printf()输出

printf("%s %02d %02d:%02d:%02d %s %s\n", month, day, hour, min, sec, process, message);

%02d表示如果数字少于2位,则在数字前加零,以使总数位数为2.

Artemy Vysotsky所述,可以检查sscanf()的返回值,以查找是否所有分配都成功。 sscanf()返回成功分配的数量(或输入失败时EOF)。在这种情况下,它必须是7。如果没有发生错误。

答案 1 :(得分:0)

想象一下,我正在阅读&#34; .csv&#34;的第一行。包含您正在寻找的数据的文件,只需执行此操作即可。如果它不是第一行,我想你可以设法解析文件的其余部分,直到你得到“#34;失败&#34;或者你想要的任何其他词语。

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
  int len = sending();
  char *firstline;
  int i = 0;
  char buf[0];
  int rd ;
  int fd = open("test.csv", O_RDONLY);

  rd = read(fd, buf, 1);    
  firstline = malloc(sizeof(char) * len);
  while (i != len)
    {
      firstline[i] = buf[0];
      i++;
      rd = read(fd, buf, 1);
    }
  firstline[i] = '\0';
  printf("%s\n", firstline);
  int contains = 0;
  i = 0;
  while (firstline[i]) //loop that verifies if it contains the word "fail"
  {
     if (firstline[i] == 'f' && firstline[i + 1] == 'a' && firstline[i + 2] == 'i' && firstline[i + 3] == 'l')
      ++contains;
     i++;
  }
  return (0);
}

int sending()
{
  int fd = open("test.csv", O_RDONLY);
  char buf[1];
  int r = 0;
  r = read(fd, buf, 1);
  int len = 0;

  while (buf[0] != '\n')//reading until '\n' and getting size to malloc
    {
      len++;
      r = read(fd, buf, 1);    
    }
  return len;
}