[英]To count the total number of lines in a file using Unix system call in C
我是 C 语言的初学者,unix 没有太多经验。 我正在尝试使用 unix 系统调用计算文件内的总行数,但没有得到任何结果。 我的 lineCount 总是显示为 0 我不知道为什么? 如果可能的话,我希望有人帮我算出行数。谢谢
int lineCount = 0;
while (*buffer != '\0') // to check the end of the file
{
read( in_fd, buffer, BUFFERSZ);
if (*buffer == '\n')
{
lineCount++;
}
}
printf("Linecount: %i \n", lineCount );
使用open
、 read
和write
与使用fopen
、 fread
和fwrite
(或fgets
和fprintf
)实际上没有太大区别,除了任何转换、字节计数和设置创建的文件权限位的负担都在你身上。 当write
将诸如1020
的值写入文件时,它正在写入您告诉它写入的bytes
数,并且该数字将以与您的硬件使用的相同字节顺序存在于文件中。
例如,如果您有unsigned v = 1020;
( 0x3fc
in hex) 然后write (fd, &v, sizeof v);
, 当您使用hexdump
或od
(或类似)查看您的文件时,它将包含fc 03 00 00
(假设您的硬件是小端)。 这些是您的4-bytes
unsigned
值1020
。 您无法在文本编辑器中打开文件并期望看到 ASCII 字符,因为这不是写入文件的内容。
要使用open
和read
查找文件中的行数,您基本上要open
文件,将文件一次读入缓冲区一些合理数量的字节并计算文件中的'\\n'
字符。
(注意:您还需要检查从文件中读取的最后一个字符是否不是'\\n'
。如果是,您需要将+1
添加到您的行数以考虑非 POSIX 行最后一行的结尾。)
唯一的其他警告是注意您open
用于写入的任何新创建文件的mode
(权限)。 否则,您会发现自己无法访问新创建的文件。 这就是为什么在提供O_CREAT
标志的情况下 open 提供mode_t mode
作为第三个参数的原因。
如果您打算坚持只对程序 I/O 使用open, read, write
,那么您将必须在出现错误时向终端STDERR_FILENO
提供错误消息输出。 您可能需要一个简短的辅助函数来为此目的编写字符串消息。
将各个部分放在一起,您可以在忠于自己的事业的同时执行以下操作。 以下代码将infile
和outfile
名称作为程序的前两个参数,一次读取infile
65K bytes
,计算文件中的'\\n'
数,然后将结果写入outfile
占任何非 POSIX 行文件结束。 writeliteral
作为错误消息的帮助程序提供:
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
enum { BUFFERSZ = 1 << 16 }; /* 65K buffer size */
void writeliteral (int fildes, const char *s);
int main (int argc, char **argv) {
if (argc < 3) {
writeliteral (STDERR_FILENO, "error: insufficient input.\n");
writeliteral (STDERR_FILENO, "usage: progname infile outfile\n");
return 1;
}
char buf[BUFFERSZ] = "";
unsigned i = 0, nlines = 0;
ssize_t n = 0;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open (argv[1], O_RDONLY);
if (fd == -1) { /* validate file open for reading */
writeliteral (STDERR_FILENO, "error: infile open failed.\n");
return 1;
}
while ((n = read (fd, buf, sizeof buf)) > 0) /* read 65k chars */
for (i = 0; i < n; i++) /* count newlines in buf */
if (buf[i] == '\n')
nlines++;
if (buf[i - 1] != '\n') /* account for non-POSIX line end */
nlines++;
close (fd); /* close file */
/* open outfile for writing, create if it doesn't exist */
if ((fd = open (argv[2], O_WRONLY | O_CREAT, mode)) == -1) {
writeliteral (STDERR_FILENO, "error: outfile open failed.\n");
return 1;
}
write (fd, &nlines, sizeof nlines); /* write nlines to outfile */
close (fd); /* close file */
return 0;
}
/** write a string literal to 'fildes' */
void writeliteral (int fildes, const char *s)
{
size_t count = 0;
const char *p = s;
for (; *p; p++) {}
count = p - s;
write (fildes, s, count);
}
示例输入文件
$ nl -ba ../dat/captnjack.txt
1 This is a tale
2 Of Captain Jack Sparrow
3 A Pirate So Brave
4 On the Seven Seas.
示例使用/输出
$ ./bin/readwrite_lineno ../dat/captnjack.txt ../dat/jacklines.dat
$ hexdump -n 16 -C ../dat/jacklines.dat
00000000 04 00 00 00 |....|
00000004
看看它,如果您有任何问题,请告诉我。 它向您展示了为什么您在完成后可能会更喜欢printf
系列函数格式说明符。
您的代码只检查*buffer
的换行符,这是您读取的每个BUFFERSZ
块的第一个字符,即您的代码甚至不查看大部分输入。 (它也不会正确检查文件结尾:您需要查看read
的返回值。)
这是一个使用read
模拟fgetc
的简单解决方案:
size_t lines = 0;
char c;
while (read(in_fd, &c, 1) == 1) {
if (c == '\n') {
lines++;
}
}
printf("Linecount: %zu\n", lines);
如果您也不能使用printf
,一个快速的解决方法是:
static void print_n(size_t n) {
if (n / 10) {
print_n(n / 10);
}
char c = '0' + n % 10;
write(1, &c, 1);
}
...
write(1, "Linecount: ", strlen("Linecount: "));
print_n(lines);
write(1, "\n", 1);
参考: 使用C计算行数使用代码
FILE *fp = fopen("myfile.txt");
int ch;
int count=0;
do { ch = fgetc(fp);
if( ch== '\n')
count++;
}while( ch != EOF );
printf("Total number of lines %d\n",count);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.