C - 从文件中读取特定行

时间:2011-04-12 14:28:14

标签: c programming-languages

我正在尝试从文件中读取特定行,我可以获取行号,但我不知道如何去做,这是我到目前为止:

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

int main(int argc, char **argv)
{
  FILE *file;
  file = fopen("temp.txt","r");
  char tmp[256]={0x0};
  char *tmpline;
  int numline = 1;
  while(file != NULL && fgets(tmp, sizeof(tmp),file) !=NULL)
  {
    tmpline = strstr(tmp,"status:green");

    if(tmpline) {
      printf("%d - %s", numline, tmpline);
    }

    numline++;
  }
  if (file != NULL) fclose(file);

  return 0;
}

测试文件如下:

s1.server.com
127.0.0.1 
status:green

s2.server.com
127.0.0.1 
status:red

s3.server.com
127.0.0.1 
status:red

s4.server.com
127.0.0.1 
status:green

我的输出是:

3 - status:green 
15 - status:green

但我真正想要表现的是:

s1.server.com
s4.server.com

我希望它搜索“status:green”然后返回几行以显示它属于哪个服务器

3 个答案:

答案 0 :(得分:1)

听起来好像你需要做两件事之一。

更简单的选项:保持一个小的循环缓冲线。读入第0行,第1行,第2行,...,第n-1行,第0行,第1行等。然后,当您看到所需的文本时,请查看条目(current_index - 2)mod buffer_size。 (听起来好像缓冲区大小为3就足够了。)

更复杂的选项:实际解析输入,以便为每个块计算服务器名称,IP地址和状态,然后使用它显示所需的信息。

“更复杂的选项”将会更加有效,但如果您的输入语法发生变化(例如,使用可选的额外行以及有关服务器的更多信息 - 可能是多个IP地址或多个名称),则会更加健壮

我认为还有其他一些我认为更糟糕的事情。 (1)在每一行上调用ftell并将 的结果放在循环缓冲区中,然后在看到“status:green”时使用fseek。 (2)使用您当前拥有的代码读取整个文件,构建“好”服务器的行号列表。然后再次浏览该文件并报告好的文件。我认为这些都比我上面列出的方法更丑陋,效率更低。有一个可能的优点:你可以调整它们来计算用空行分隔的“节”,而不需要正确解析事物。这将使您获得我提到的“更复杂”方法的灵活性,而无需正确的解析器。

这是一种混合的可能性:不要使用循环缓冲区,但如果需要,可以增加其大小。每次看到空白行时,从缓冲区中的第一个条目开始。如果有“长”节,请让缓冲区增长。然后,当您看到“状态:绿色”时,对缓冲区中现有的(可能是完整的)节做任何处理。

当然,如果您确定文件格式永远不会改变,则上述所有内容都不是必需的。

答案 1 :(得分:1)

如果测试文件(和生产文件)格式正确,那么您可以执行以下操作(为简洁起见,我们会遗漏错误检查!):

typedef struct _SERVERSTATUS
{
    char* name;
    char* ip;
    char* status;
} SERVERSTATUS;


SERVERSTATUS ss;

ss.name = calloc(256);
ss.ip = calloc(256);
ss.status = calloc(256);

while (!feof(file))
{
    fgets(ss.name, file);
    fgets(ss.ip, file);
    fgets(ss.status, file);

    if (!strcmp(ss.status, "status:green"))
       printf("%s\n", ss.name);
}

free(ss.name);
free(ss.ip);
free(ss.status);

编辑:您还必须处理文件条目之间的空白!那是,嗯,留下作为提问者的练习

答案 2 :(得分:0)

阅读每组中的第一行和第三行。搜索status:green,如果找到,则打印服务器名称。