我正在尝试从文件中读取特定行,我可以获取行号,但我不知道如何去做,这是我到目前为止:
#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”然后返回几行以显示它属于哪个服务器
答案 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
,如果找到,则打印服务器名称。