我发现strpbrk 是在haystack 中搜索多个needles 的最有用的功能之一。您的 needles 集是数字字符 "0123456789",如果从您的文件读取的行中存在这些字符,则将计为一行。我也更喜欢 POSIX getline 的行数,以正确处理最后一行具有非 POSIX 行结尾的文件(fgets 和 wc -l 省略最后一行的文本(和计数),如果它不包含 POSIX 行尾 ('\n')。也就是说,一个小函数在行中搜索包含在作为参数传递的 trm 中的字符可以写成:
/** open and read each line in 'fn' returning the number of lines
* continaing any of the characters in 'trm'.
*/
size_t nlines (char *fn, char *trm)
{
if (!fn) return 0;
size_t lines = 0, n = 0;
char *buf = NULL;
FILE *fp = fopen (fn, "r");
if (!fp) return 0;
while (getline (&buf, &n, fp) != -1)
if (strpbrk (buf, trm))
lines++;
fclose (fp);
free (buf);
return lines;
}
只需传递感兴趣的文件名和要在每一行中搜索的术语。一个简短的测试代码,默认术语为"0123456789",将文件名作为第一个参数,术语作为第二个参数,可以编写如下:
#include <stdio.h> /* printf */
#include <stdlib.h> /* free */
#include <string.h> /* strlen, strrchr */
size_t nlines (char *fn, char *trm);
int main (int argc, char **argv) {
char *fn = argc > 1 ? argv[1] : NULL;
char *srch = argc > 2 ? argv[2] : "0123456789";
if (!fn) return 1;
printf ("%zu %s\n", nlines (fn, srch), fn);
return 0;
}
/** open and read each line in 'fn' returning the number of lines
* continaing any of the characters in 'trm'.
*/
size_t nlines (char *fn, char *trm)
{
if (!fn) return 0;
size_t lines = 0, n = 0;
char *buf = NULL;
FILE *fp = fopen (fn, "r");
if (!fp) return 0;
while (getline (&buf, &n, fp) != -1)
if (strpbrk (buf, trm))
lines++;
fclose (fp);
free (buf);
return lines;
}
试一试,看看这是否是您所期望的,如果不是,请告诉我,我很乐意为您提供进一步的帮助。
输入文件示例
$ cat dat/linewno.txt
The quick brown fox
jumps over 3 lazy dogs
who sleep in the sun
with a temp of 101
使用/输出示例
$ ./bin/getline_nlines_nums dat/linewno.txt
2 dat/linewno.txt
$ wc -l dat/linewno.txt
4 dat/linewno.txt