有没有办法找到从文件中读取的当前行的行号?
Is there a way to find the line number of the current line being read from a file?
1) 在 C 中有没有一种方法可以找到我们正在从文件中读取的行的行号。
2) 我还想知道除了创建一个在每一行中查找 EOF
直到到达结束。
我还想知道是否有另一种方法可以找出文件中的总行数,而不是通过创建一个循环在每一行中查找 EOF 直到它到达末尾.
您可以将 popen
与命令一起使用
wc -l filename
或命令
sed -n '$=' loop.c
要了解更多信息,请阅读如何使用 popen
函数。这是一个例子
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
FILE* p;
int a;
char str[10];
p = popen("sed -n '$=' loop.c", "r");
fgets(str, 10, p);
a = atoi(str);
printf("%d", a);
}
您可以数一数行尾经过的行数。当然,行结尾因平台而异。 UNIX 使用 \n,Mac 使用 \r(或者至少他们曾经使用),Windows 使用 \r\n.
您可以查看 wc 的源代码(一个标准的 UNIX 实用程序,用于计算文件中的行数、字符数等)。这里是 OpenBSD's wc source.
1)Is there a way in C that we could find the line number of a line that we are reading from a file.
除非您从文件开头计算行数,否则不会。您不能随意将自己置于文件中并知道您所在的文本行,除非文件本身有信息告诉您,或者您已经通过先前遍历文件创建了某种索引。通常的方法是在处理文件中的行时累积行数。
2)I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.
没有。您必须 运行 遍历整个文件并计算行数。任何外部工具(例如 wc
)都在这样做。您需要了解不同的 line-ending 风格。根据您用来读取文件的功能,您可能有也可能没有自动换行符翻译。
1) Is there a way in C that we could find the line number of a line
that we are reading from a file.
是也不是。正如其他人所说,没有任何机制,仅通过文件位置就可以在读取文件时找到在任何给定时间点读取的行号。这并不意味着您无法轻松跟踪您当前正在阅读的那一行并编写一个条件以应用于任何给定的行。例如,一种从文件中读取(或默认 stdin
)并跟踪 当前 以及查找总行数的简单方法可能类似于以下:
#include <stdio.h>
#define MAXS 256
int main (int argc, char **argv)
{
char line[MAXS] = {0}; /* line buffer for fgets */
long long unsigned index = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
while (fgets (line, MAXS, fp))
{
printf (" line[%3llu] : %s", index++ + 1, line);
}
if (fp != stdin) fclose (fp);
printf ("\n total : %llu lines\n\n", index);
return 0;
}
Use/Output
$ ./bin/fgets_min_count dat/captnjack.txt
line[ 1] : This is a tale
line[ 2] : Of Captain Jack Sparrow
line[ 3] : A Pirate So Brave
line[ 4] : On the Seven Seas.
total : 4 lines
2) I would also like to know if there is another way to find out the
total number of lines in a file other than by creating a loop which
looks for EOF in each line until it reaches the end.
根据文件大小和需要统计的行数,尽量减少读取次数可以大大提高统计效率。由于缺少更好的词,您可以在一次读取中将整个文件读入缓冲区(对于 INT_MAX
字节或更少的所有文件)或在有限数量的 INT_MAX
大小的读取中然后简单地计数'\n'
个字符(testing/adjusting 表示没有 '\n'
的文本(作为第一行,或者最后没有 POSIX line-end)。
考虑到 fread
:
的大小限制,代码略长
#include <stdio.h>
#include <stdlib.h>
#include <limits.h> /* for INT_MAX */
char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp);
long buf_lines (char *s, long len);
int main (int argc, char **argv) {
char *filebuf = NULL;
long fplen = 0, nlines = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open */
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}
/* read entire file into filebuf*/
if (!read_file_into_buf (&filebuf, &fplen, fp)) return 1;
if (fp != stdin) fclose (fp);
nlines = buf_lines (filebuf, fplen); /* count lines */
printf ("\n total : %ld lines read (from '%s')\n\n",
nlines, argc > 1 ? argv[1] : "stdin");
free (filebuf);
return 0;
}
/** read file from 'fp' into 'filebuf', update 'fplen'.
* memory is allocated for filebuf sufficient to hold
* contents of 'fp'. returns pointer to 'filebuf' on
* success, NULL otherwise. reads at most INT_MAX bytes
* at a time from file.
*/
char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp)
{
if (!fp) return NULL;
size_t nbytes = 0, readsz = 0;
long bytecnt = 0;
fseek (fp, 0, SEEK_END);
if ((*fplen = ftell (fp)) == -1) { /* get file length */
fprintf (stderr, "error: unable to determine file length.\n");
return NULL;
}
fseek (fp, 0, SEEK_SET); /* allocate memory for file */
if (!(*filebuf = calloc (*fplen, sizeof **filebuf))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
/* read entire file into filebuf reading a
* maximum of INT_MAX bytes at a time */
readsz = *fplen > INT_MAX ? INT_MAX : *fplen;
while ((nbytes = fread ((*filebuf + bytecnt),
sizeof **filebuf, readsz, fp))) {
bytecnt += nbytes;
if (nbytes != readsz) fprintf (stderr, "warning: short read.\n");
if (bytecnt == *fplen) break;
readsz = *fplen - bytecnt > INT_MAX ? INT_MAX : *fplen - bytecnt;
}
if (bytecnt != *fplen) {
fprintf (stderr, "error: file read failed.\n");
return NULL;
}
return *filebuf;
}
/** count lines in buffer
* (line with non-POSIX line end counted as 1)
*/
long buf_lines (char *fb, long len)
{
long i = 0, lns = 0;
for (;;) {
if (fb[0] == '\n') lns++;
if (++i == len) { if (fb[0] != '\n') lns++; return lns; }
if (fb[1] == '\n') lns++;
if (++i == len) { if (fb[1] != '\n') lns++; return lns; }
if (fb[2] == '\n') lns++;
if (++i == len) { if (fb[2] != '\n') lns++; return lns; }
if (fb[3] == '\n') lns++;
if (++i == len) { if (fb[3] != '\n') lns++; return lns; }
fb += 4;
}
}
Use/Output
$ ./bin/fread_file_count dat/captnjack.txt
total : 4 lines read (from 'dat/captnjack.txt')
1) 在 C 中有没有一种方法可以找到我们正在从文件中读取的行的行号。
2) 我还想知道除了创建一个在每一行中查找 EOF
直到到达结束。
我还想知道是否有另一种方法可以找出文件中的总行数,而不是通过创建一个循环在每一行中查找 EOF 直到它到达末尾.
您可以将 popen
与命令一起使用
wc -l filename
或命令
sed -n '$=' loop.c
要了解更多信息,请阅读如何使用 popen
函数。这是一个例子
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
FILE* p;
int a;
char str[10];
p = popen("sed -n '$=' loop.c", "r");
fgets(str, 10, p);
a = atoi(str);
printf("%d", a);
}
您可以数一数行尾经过的行数。当然,行结尾因平台而异。 UNIX 使用 \n,Mac 使用 \r(或者至少他们曾经使用),Windows 使用 \r\n.
您可以查看 wc 的源代码(一个标准的 UNIX 实用程序,用于计算文件中的行数、字符数等)。这里是 OpenBSD's wc source.
1)Is there a way in C that we could find the line number of a line that we are reading from a file.
除非您从文件开头计算行数,否则不会。您不能随意将自己置于文件中并知道您所在的文本行,除非文件本身有信息告诉您,或者您已经通过先前遍历文件创建了某种索引。通常的方法是在处理文件中的行时累积行数。
2)I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.
没有。您必须 运行 遍历整个文件并计算行数。任何外部工具(例如 wc
)都在这样做。您需要了解不同的 line-ending 风格。根据您用来读取文件的功能,您可能有也可能没有自动换行符翻译。
1) Is there a way in C that we could find the line number of a line that we are reading from a file.
是也不是。正如其他人所说,没有任何机制,仅通过文件位置就可以在读取文件时找到在任何给定时间点读取的行号。这并不意味着您无法轻松跟踪您当前正在阅读的那一行并编写一个条件以应用于任何给定的行。例如,一种从文件中读取(或默认 stdin
)并跟踪 当前 以及查找总行数的简单方法可能类似于以下:
#include <stdio.h>
#define MAXS 256
int main (int argc, char **argv)
{
char line[MAXS] = {0}; /* line buffer for fgets */
long long unsigned index = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
while (fgets (line, MAXS, fp))
{
printf (" line[%3llu] : %s", index++ + 1, line);
}
if (fp != stdin) fclose (fp);
printf ("\n total : %llu lines\n\n", index);
return 0;
}
Use/Output
$ ./bin/fgets_min_count dat/captnjack.txt
line[ 1] : This is a tale
line[ 2] : Of Captain Jack Sparrow
line[ 3] : A Pirate So Brave
line[ 4] : On the Seven Seas.
total : 4 lines
2) I would also like to know if there is another way to find out the total number of lines in a file other than by creating a loop which looks for EOF in each line until it reaches the end.
根据文件大小和需要统计的行数,尽量减少读取次数可以大大提高统计效率。由于缺少更好的词,您可以在一次读取中将整个文件读入缓冲区(对于 INT_MAX
字节或更少的所有文件)或在有限数量的 INT_MAX
大小的读取中然后简单地计数'\n'
个字符(testing/adjusting 表示没有 '\n'
的文本(作为第一行,或者最后没有 POSIX line-end)。
考虑到 fread
:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h> /* for INT_MAX */
char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp);
long buf_lines (char *s, long len);
int main (int argc, char **argv) {
char *filebuf = NULL;
long fplen = 0, nlines = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open */
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}
/* read entire file into filebuf*/
if (!read_file_into_buf (&filebuf, &fplen, fp)) return 1;
if (fp != stdin) fclose (fp);
nlines = buf_lines (filebuf, fplen); /* count lines */
printf ("\n total : %ld lines read (from '%s')\n\n",
nlines, argc > 1 ? argv[1] : "stdin");
free (filebuf);
return 0;
}
/** read file from 'fp' into 'filebuf', update 'fplen'.
* memory is allocated for filebuf sufficient to hold
* contents of 'fp'. returns pointer to 'filebuf' on
* success, NULL otherwise. reads at most INT_MAX bytes
* at a time from file.
*/
char *read_file_into_buf (char **filebuf, long *fplen, FILE *fp)
{
if (!fp) return NULL;
size_t nbytes = 0, readsz = 0;
long bytecnt = 0;
fseek (fp, 0, SEEK_END);
if ((*fplen = ftell (fp)) == -1) { /* get file length */
fprintf (stderr, "error: unable to determine file length.\n");
return NULL;
}
fseek (fp, 0, SEEK_SET); /* allocate memory for file */
if (!(*filebuf = calloc (*fplen, sizeof **filebuf))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
/* read entire file into filebuf reading a
* maximum of INT_MAX bytes at a time */
readsz = *fplen > INT_MAX ? INT_MAX : *fplen;
while ((nbytes = fread ((*filebuf + bytecnt),
sizeof **filebuf, readsz, fp))) {
bytecnt += nbytes;
if (nbytes != readsz) fprintf (stderr, "warning: short read.\n");
if (bytecnt == *fplen) break;
readsz = *fplen - bytecnt > INT_MAX ? INT_MAX : *fplen - bytecnt;
}
if (bytecnt != *fplen) {
fprintf (stderr, "error: file read failed.\n");
return NULL;
}
return *filebuf;
}
/** count lines in buffer
* (line with non-POSIX line end counted as 1)
*/
long buf_lines (char *fb, long len)
{
long i = 0, lns = 0;
for (;;) {
if (fb[0] == '\n') lns++;
if (++i == len) { if (fb[0] != '\n') lns++; return lns; }
if (fb[1] == '\n') lns++;
if (++i == len) { if (fb[1] != '\n') lns++; return lns; }
if (fb[2] == '\n') lns++;
if (++i == len) { if (fb[2] != '\n') lns++; return lns; }
if (fb[3] == '\n') lns++;
if (++i == len) { if (fb[3] != '\n') lns++; return lns; }
fb += 4;
}
}
Use/Output
$ ./bin/fread_file_count dat/captnjack.txt
total : 4 lines read (from 'dat/captnjack.txt')