用于打印文件中的行数和列数的代码.为什么它适用于Windows Mingw gcc环境而不适用于Linux?

Nik*_*kos 0 c linux gcc cross-platform file

代码适用于Windows上的任何编译器,但不适用于Linux.在Linux上,它返回的行数超过两倍,列数为负数.Win8.1 x86_64,Linux 16.04 64位.我在Windows(MINGW)上有GCC v5.3,但在Linux上有GCC v5.4.0.

#include <stdio.h>

// count Lines of a file
size_t countLinesOfFile(char *fileName)
{
    FILE *fp = fopen(fileName, "r");
    char ch;
    size_t lines = 0;
    do {
        ch = fgetc(fp);
        if(ch == '\n' || ch == '\r')
            lines++;
    } while (ch != EOF);
    //while (!feof(fp))

    // if last line doesn't end with a new line character! augment No of lines
    if(ch != '\n' || ch != '\r')
        lines++;

    fclose(fp);
    return lines;
}

// assuming that the file has equal number of columns for all its lines
// (or just 1 line)
size_t countColumnsOfFile(char *fileName)
{
    FILE *fp = fopen(fileName, "r");
    char ch;
    size_t columns = 0;
    while ((ch != '\n' || ch != '\r') && ch != EOF) { // we only want to count one line so which ever comes first
        ch = fgetc(fp);
        columns++;
    }
    columns--;
    //feof(fp) = found end of file, returns non zero(true) if found

    fclose(fp);
    return columns;
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*mar 5

你递增lines,当你阅读这两个\r\n.在Windows上创建文本文件时,它使用CRLF作为换行符序列,但C stdio库将这些组合成单个\n字符(除非您以二进制模式打开文件).

Unix只使用LF作为换行符.如果将文件从Windows复制到Unix,它将把CR和LF中的每一个作为单独的字符读取,\r并且\n.您的代码line为每个代码递增,因此您将每行计算两次.对于在Unix上创建的文件,不会发生这种情况.

所以你应该算一下\n角色.只要您以文本模式(默认)打开文件,这是您应该看到的唯一换行符.C库需要将操作系统的换行序列转换为该字符.

顺便说一句,这条线在两个方面有误:

// if last line doesn't end with a new line character! augment No of lines
if(ch != '\n' || ch != '\r')
Run Code Online (Sandbox Code Playgroud)

首先,如果你想测试一个字符不是\n\r,你应该使用&&,不||.请参阅为什么对多个值的一个变量的非等式检查始终返回true?

其次,循环结束时ch == EOF,所以它总是不等于\r\n.如果要测试最后一行的结束方式,则需要在重复ch = fgetc(fp);赋值之前将每个字符保存到另一个变量中.

列计数代码具有测试与任何列表不匹配的字符的相同问题.它应该是

while (ch != '\n' && ch != '\r' && ch != EOF) { // we only want to count one line so which ever comes first
Run Code Online (Sandbox Code Playgroud)