2011-04-12 191 views
0

我想从文件中读取特定行,并且可以获取行号,但我不知道如何去做,这是迄今为止:C - 从文件中读取特定行

#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 

我希望它搜索“状态:绿色”再回去了几行,以显示它属于

+1

为什么要重新发明轮子?这可以通过一个awk单行程来解决 - 例如'awk tdammers 2011-04-12 14:32:03

+0

@tdammers,不完全是这样:zoite想要在他看到时显示一个*更早的*行“状态:绿色”。你仍然可以通过简单的awk调用来实现,但并不那么容易。 – 2011-04-12 14:36:38

+1

这可能是如此,但他问如何在C. – James 2011-04-12 14:39:33

回答

1

听起来好像你需要做两件事情之一的服务器。

简单选项:保留一些循环的缓冲区行。读入第0行,第1行,第2行,...,第n-1行,第0行,第1行等。然后,当你看到你想要的文本时,查看条目(current_index - 2)mod buffer_size。 (这听起来好像3缓冲区大小就足够了。)

更复杂的选项:其实解析输入,使每个块你的工作的服务器名,IP地址和它的状态,然后使用它显示您需要的信息。

“更复杂的选项”将会有更多的工作,但如果输入的语法发生变化(例如,通过可选的额外的行以及更多关于服务器的信息 - 多个IP地址或多个名称) )。

还有一些其他的事情我可以做,我认为更糟。 (1)在每行上调用ftell,将的结果放入循环缓冲区,然后在看到“status:green”时使用fseek。 (2)使用你现有的代码阅读整个文件,建立一个“好”的服务器行号列表。然后再次浏览文件并报告好的文件。我认为这些都比我上面列出的方法更丑陋,效率更低。有一个可能的优点:你可以使它们适应计数在由空行分隔的“节”,而不需要正确地解析事情。这会让你成为我提到的“更复杂”方法的灵活性的一部分,而不需要适当的解析器。

这里是一个混合的可能性:不要使用循环缓冲区,但是如果需要可以增加大小。每次看到空行时,从缓冲区中的第一个入口开始。如果有“长”节,让缓冲区增长。然后,当你看到“状态:绿色”时,在缓冲区中保存的(可能是完整的)节上进行所需的任何处理。

当然,如果您确定文件格式永远不会改变,以上都不是必需的。

+0

我很确定这是在2点之前,现在是1。如果谁低估了这一点,那么我会非常有兴趣知道你认为哪些是错误的(误导性的,不清楚的,无聊的),以便我可以改进它,并且/或者在下一次做的更好。谢谢! – 2011-04-12 14:56:19

+0

谢谢,这应该完美。不知道为什么我没有想到之前 – zoite 2011-04-12 15:03:48

0

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

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); 

编辑:您还必须处理文件条目之间的空白!那就是这个,留给练习者

+0

感谢您的代码,我将与您和Gareths的解决方案一起工作,我应该很乐意去 – zoite 2011-04-12 15:05:02