使用C计算ASCII文件中的行数

时间:2015-05-16 16:30:35

标签: c ascii text-files

我想计算ASCII文本文件中的行数。 我认为最好的方法是计算文件中的换行符:

for (int c = fgetc(fp); c != EOF; c = fgetc(fp)) {  /* Count word line endings. */
    if (c == '\n') ++lines;
}

但是,我不确定这是否会占据MS Windows和Linux上的最后一行。也就是说,如果我的文本文件如下所示完成,没有明确的换行符,那么还是有一个编码在那里,还是应该在for循环后添加额外的++lines;

cat
dog

那么如果 在文件末尾有一个显式换行符怎么办?或者我只需要通过跟踪先前读取的值来测试这种情况吗?

7 个答案:

答案 0 :(得分:3)

如果没有换行符,则无法生成。 C告诉你那里到底是什么。

答案 1 :(得分:3)

文本文件始终以换行符结束。没有规范的处理文件的方法。

以下是一些工具在最后一次换行后如何选择处理字符:

  • wc并不将其视为一条线(因此您有优先权)
  • Vim将文件标记为[noeol],并保存文件而不使用尾随换行符
  • GNU sed将文件视为最后一次换行
  • sh' read退出时出错,但仍会返回数据

由于行为几乎未定义,您可以随心所欲地为您做任何事情。

答案 2 :(得分:3)

首先,在最后一行的末尾不会有任何隐式编码的换行符。新行的唯一方法是生成该文件的软件或人员将其放在那里。然而,把它放在那里通常被认为是良好的做法。

您应该报告的行数的最终答案取决于您需要遵循的软件或将使用此行数的人员的惯例,以及您可能对输入源的行为假设的内容同样。

大多数命令行工具将使用换行符终止其输出。在这种情况下,明智的答案可能是将换行符的数量报告为实际行数。

另一方面,当文本编辑器显示文件时,您将看到边距中的行编号(如果支持)包含最后一行的编号,无论它是否为空。这部分是为了告诉用户那里有一个空白行,但是如果你想计算边距中显示的行数,那么它就是一个加上文件中换行符的数量。一些编码人员通常不会使用换行符来终止他们的最后一行(有时是由于邋iness),因此在这种情况下,这种约定实际上是正确答案。

我不确定任何其他惯例是否有意义。例如,如果您选择不计算最后一行,除非它是非空的,那么什么算作非空?换行后的文件?如果该行上有空格怎么办?如果文件末尾有几个空行怎么办?

答案 3 :(得分:2)

如果你打算使用这种方法,你可以随时为你所在线上的字母数量保留一个单独的计数器。如果最后的计数大于1,那么你知道最后一行的东西没有被计算在内。

int letters = 0

for (int c = fgetc(fp); c != EOF; c = fgetc(fp)) {  /* Count word line endings. */
    letters++; // Increase count on character

    if (c == '\n')
    {
        ++words;
        letters = 0; // Set back to 0 after new line
    }
}

if (letters > 0)
{
    ++words;
}

答案 4 :(得分:2)

您的担忧是真实的,文件中的最后一行可能缺少行标记的最后一行。行尾标记是Linux中的单个'\n',Windows中的CR LF对,C运行时自动转换为'\n'

您可以简化代码并处理最后一行错过换行符的特殊情况:

int c, last = '\n', lines = 0;

while ((c = getc(fp)) != EOF) {  /* Count word line endings. */
    if (c == '\n')
        lines += 1;
    last = c;
}
if (last != '\n')
    lines += 1;

由于您关注速度,因此使用getc而不是fgetc将有助于将其定义为直接处理流结构的宏并仅调用函数来重新填充缓冲区的平台,每个BUFSIZ个字符左右,除非流是无缓冲的。

答案 5 :(得分:1)

这个怎么样:

为自己创建一个标记,以跟踪在\n时重置\n后的任何非c=='\n'个字符。 在EOF之后,检查标志是否为真,如果是,则检查是否增加。

bool more_chars = false;
for (int c = fgetc(fp); c != EOF; c = fgetc(fp)) {  /* Count word line endings. */
            if (c == '\n') {
              more_chars = false;
              ++words;
            } else more_chars = true;
 }
 if(more_chars) words++;

答案 6 :(得分:-1)

Windows和UNIX / Linux样式换行符在这里没有区别。在任一系统上,文本文件在最后一行的末尾可能有也可能没有换行符。

如果你总是在行数上加1,那么当 结尾的换行符时,这会有效地计算文件末尾的空行(即文件"foo\n"将算作有两行:"foo""")。这可能是一个完全合理的解决方案,具体取决于您想要如何定义一条线。

" line"的另一个定义;是它始终以换行符结束,即文件"foo\nbar"只有一行("foo")。此定义由wc使用。

当然,您可以跟踪换行是否是文件中的最后一个字符,并且只有在它不是的情况下才添加1。然后是"线"将被定义为以换行结尾或在文件末尾非空,这对我来说听起来很复杂。