2015-11-24 41 views
-1

我有一个包含10次匹配的日志文件,例如一行是:计算IP号码在文本文件中出现的次数 - C程序

127.0.0.1 - - [10/Oct/2007:13:55:36 ­0700]"GET /index.html HTTP/1.0" 200 2326 "http://www.example.com/links.html" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)" 

每行的格式都是相同的,即IP地址始终处于开始位置。

我目前使用fopen和fgets读取了文件,但现在我想要统计文件中有多少个唯一的IP地址,以及计算IP“点击次数”的次数。不知道我会如何尝试这个..关于如何去做这件事的任何提示?

+1

这取决于如果文件格式是固定和OU知道在哪里查找IP地址,或者如果您需要扫描模式,*外观*如IP地址线。这将是近似值,因为URL可能包含产生误报的模式。 – chqrlie

+0

如果IP地址始终在开头,那么在检查正确的格式后,用'sscanf'解析它们是相对容易的。 – chqrlie

+0

“例如** 1 ** **行是:** ** ** **行数据? – chux

回答

2

代码可以通过寻找ddd.ddd.ddd.ddd模式的文件行进。

避免使用"%d""%u",因为它们接受领先空格,并且'-''+'

伪代码

Read from a file until EOF found 
    repeatedly look for a digit 
    if it is found 
    note position 
    put digit back into stream 
    look for ddd.ddd.ddd.ddd 
    if found 
     decode (and test for values > 255) 
     if successful return result 
    go back to position 

return fail value; 

示例代码。还应该有IO错误检查。

unsigned long Parse_IP(FILE *inf) { 
    int ch; 
    for ((ch = fgetc(inf)) != EOF) { 
    if (isdigit(ch)) { 
     long pos = ftell(inf); 
     ungetc(ch, inf); 
     char buf[4][4]; 
     int count = fscanf(inf, "%3[0-9].%3[0-9].%3[0-9].%3[0-9]", 
      buf[0], buf[1], buf[2], buf[3]); 
     if (count == 4) { 
     unsigned long ip = 0; 
     int i; 
     for (i=0; i<4; i++) { 
      int digit = atoi(buf[i]); 
      if (digit > 255) break; 
      ip = ip*256 + digit; 
     } 
     if (i == 4) return ip; 
     } 
     fseek(inf, pos, SEEK_SET); 
    } 
    } 
    return 0; 
} 

使用范例

unsigned long ip; 
while ((ip = Parse_IP(inf)) != 0) { 
    printf("ip %08lX\n", ip); 
} 
+0

您的代码可能会失败的管道或控制台输入,你可以将'fseek'倒退,并且它会错误地匹配这些模式的IP地址:'9127.0.0.1','0.0.0.2550'等。 – chqrlie

+0

我很挑剔,但为什么不接受'0.0。 0.0'作为一个有效的IP地址模式? – chqrlie

+1

@chqrlie发布的方法返回一个32位整数,使用_some_值作为失败指示。代码可以很容易地修改为返回一个'long long'作为坏男孩,或者将IP地址保存在传递的指针位置并返回一个'int'或者0或1.'0'似乎是“无效的值”。没有令人信服的理由'0' – chux

相关问题