计算文件中的行数,不包括 C 中的空行

Counting lines in a file excluding the empty lines in C

我们有一个程序将一个文件作为输入,然后计算该文件中的行数,但不计算空行数。

Stack Overflow 中已经有一个 post 这个问题,但这个问题的答案没有涵盖我。

举个简单的例子

文件:

I am John\n
I am 22 years old\n
I live in England\n

如果最后一个'\n'不存在,那么计数就很容易了。我们实际上已经有一个函数在这里执行此操作:

/* Reads a file and returns the number of lines in this file. */
uint32_t countLines(FILE *file) {
  uint32_t lines = 0;
  int32_t c;
  while (EOF != (c = fgetc(file))) {
    if (c == '\n') {
      ++lines;
    }
  }
  /* Reset the file pointer to the start of the file */
  rewind(file);
  return lines;
}

这个函数,当把上面的文件作为输入时,一共是4行。但我只想要 3 行。

我尝试通过多种方式解决这个问题。

首先,我尝试在每一行中执行 fgets 并将该行与字符串“\0”进行比较。如果一行只是“\0”而没有其他任何东西,那么我认为这将解决问题。

我也尝试了其他一些解决方案,但我真的找不到。

我基本上想要的是检查文件中的最后一个字符(不包括'\0')并检查它是否为'\n'。如果是,则从它先前计算的行数中减去 1(使用原始函数)。我真的不知道该怎么做。还有其他更简单的方法吗?

我将不胜感激任何类型的帮助。 谢谢

首先,检测仅由空格组成的行。因此,让我们创建一个函数来执行此操作。

bool stringIsOnlyWhitespace(const char * line) {
    int i;
    for (i=0; line[i] != '[=10=]'; ++i)
        if (!isspace(line[i]))
            return false;
    return true;
}

现在我们有了一个测试函数,让我们围绕它构建一个循环。

while (fgets(line, sizeof line, fp)) {
    if (! (stringIsOnlyWhitespace(line)))
        notemptyline++;
}

printf("\n The number of nonempty lines is: %d\n", notemptyline);

来源是 Bill Lynch,我稍作改动。

我认为您使用 fgets() 的方法完全没问题。尝试这样的事情:

char line[200];

while(fgets(line, 200, file) != NULL) {
    if(strlen(line) <= 1) {
        lines++;
    }
}

如果您不知道文件中行的长度,您可能需要检查 line 是否确实包含整行。

编辑:

当然这取决于你如何定义空行。如果将只有空格的行定义为空,则上述代码将不起作用,因为 strlen() 包含空格。

您实际上可以通过仅跟踪最后一个字符来非常有效地修正此问题。

这是有效的,因为空行有 属性,前一个字符必须是 \n

/* Reads a file and returns the number of lines in this file. */
uint32_t countLines(FILE *file) {
  uint32_t lines = 0;
  int32_t c;
  int32_t last = '\n';
  while (EOF != (c = fgetc(file))) {
    if (c == '\n' && last != '\n') {
      ++lines;
    }
    last = c;
  }
  /* Reset the file pointer to the start of the file */
  rewind(file);
  return lines;
}

这里有一个稍微好一点的算法。

#include <stdio.h>

// Reads a file and returns the number of lines in it, ignoring empty lines
unsigned int countLines(FILE *file)
{
    unsigned int  lines = 0;
    int           c = '[=10=]';
    int           pc = '\n';

    while (c = fgetc(file), c != EOF)
    {
        if (c == '\n'  &&  pc != '\n')
            lines++;
        pc = c;
    }
    if (pc != '\n')
        lines++;

    return lines;
}

只计算任何换行序列中的第一个换行符,因为除第一个换行符外的所有换行符都表示空行。

请注意,如果文件不以 '\n' 换行符结尾,则遇到的任何字符(最后一个换行符之后)都被视为部分最后一行。这意味着读取一个完全没有换行符的文件 returns 1.

读取空文件将 return 0.

读取以单个换行符结尾的文件将 return 1.

(我删除了 rewind(),因为它不是必需的。)