繁体   English   中英

在 C 中使用 Unix 系统调用计算文件中的总行数

[英]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 );

使用openreadwrite与使用fopenfreadfwrite (或fgetsfprintf )实际上没有太大区别,除了任何转换、字节计数和设置创建的文件权限位的负担都在你身上。 write将诸如1020的值写入文件时,它正在写入您告诉它写入的bytes数,并且该数字将以与您的硬件使用的相同字节顺序存在于文件中。

例如,如果您有unsigned v = 1020; ( 0x3fc in hex) 然后write (fd, &v, sizeof v); , 当您使用hexdumpod (或类似)查看您的文件时,它将包含fc 03 00 00 (假设您的硬件是小端)。 这些是您的4-bytes unsigned1020 您无法在文本编辑器中打开文件并期望看到 ASCII 字符,因为这不是写入文件的内容。

要使用openread查找文件中的行数,您基本上要open文件,将文件一次读入缓冲区一些合理数量的字节并计算文件中的'\\n'字符。

注意:您还需要检查从文件中读取的最后一个字符是否不是'\\n' 。如果是,您需要将+1添加到您的行数以考虑非 POSIX 行最后一行的结尾。)

唯一的其他警告是注意您open用于写入的任何新创建文件的mode (权限)。 否则,您会发现自己无法访问新创建的文件。 这就是为什么在提供O_CREAT标志的情况下 open 提供mode_t mode作为第三个参数的原因。

如果您打算坚持只对程序 I/O 使用open, read, write ,那么您将必须在出现错误时向终端STDERR_FILENO提供错误消息输出。 您可能需要一个简短的辅助函数来为此目的编写字符串消息。

将各个部分放在一起,您可以在忠于自己的事业的同时执行以下操作。 以下代码将infileoutfile名称作为程序的前两个参数,一次读取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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM