fgetpos()行为取决于换行符

mil*_*aki 7 c windows newline file

考虑这两个文件:

file1.txt(Windows换行符)

abc\r\n
def\r\n
Run Code Online (Sandbox Code Playgroud)

file2.txt(Unix换行)

abc\n
def\n
Run Code Online (Sandbox Code Playgroud)

我注意到对于file2.txt,获得的位置fgetpos没有正确递增.我在Windows上工作.

让我举个例子.以下代码:

#include<cstdio>

void read(FILE *file)
{
    int c = fgetc(file);
    printf("%c (%d)\n", (char)c, c);

    fpos_t pos;
    fgetpos(file, &pos); // save the position
    c = fgetc(file);
    printf("%c (%d)\n", (char)c, c);

    fsetpos(file, &pos); // restore the position - should point to previous
    c = fgetc(file);     // character, which is not the case for file2.txt
    printf("%c (%d)\n", (char)c, c);
    c = fgetc(file);
    printf("%c (%d)\n", (char)c, c);
}

int main()
{
    FILE *file = fopen("file1.txt", "r");
    printf("file1:\n");
    read(file);
    fclose(file);

    file = fopen("file2.txt", "r");
    printf("\n\nfile2:\n");
    read(file);
    fclose(file);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

得出这样的结果:

file1:
a (97)
b (98)
b (98)
c (99)


file2:
a (97)
b (98)
  (-1)
  (-1)
Run Code Online (Sandbox Code Playgroud)

file1.txt按预期工作,而file2.txt表现很奇怪.为了解释它有什么问题,我尝试了以下代码:

void read(FILE *file)
{
    int c;
    fpos_t pos;
    while (1)
    {
        fgetpos(file, &pos);
        printf("pos: %d ", (int)pos);
        c = fgetc(file);
        if (c == EOF) break;
        printf("c: %c (%d)\n", (char)c, c);
    }
}

int main()
{
    FILE *file = fopen("file1.txt", "r");
    printf("file1:\n");
    read(file);
    fclose(file);

    file = fopen("file2.txt", "r");
    printf("\n\nfile2:\n");
    read(file);
    fclose(file);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到了这个输出:

file1:
pos: 0 c: a (97)
pos: 1 c: b (98)
pos: 2 c: c (99)
pos: 3 c:
 (10)
pos: 5 c: d (100)
pos: 6 c: e (101)
pos: 7 c: f (102)
pos: 8 c:
 (10)
pos: 10

file2:
pos: 0 c: a (97) // something is going wrong here...
pos: -1 c: b (98)
pos: 0 c: c (99)
pos: 1 c:
 (10)
pos: 3 c: d (100)
pos: 4 c: e (101)
pos: 5 c: f (102)
pos: 6 c:
 (10)
pos: 8
Run Code Online (Sandbox Code Playgroud)

我知道这fpos_t不是由编码员解释的,因为它取决于实现.但是,上面的例子解释了fgetpos/ 的问题fsetpos.

换行序列如何影响文件的内部位置,甚至在遇到该字符之前?

tep*_*pic 3

我想说这个问题可能是由第二个文件混淆实现引起的,因为它是在文本模式下打开的,但它不符合要求。

在标准中,

文本流是由行组成的有序字符序列,每行由零个或多个字符加上一个终止换行符组成

您的第二个文件流不包含有效的换行符(因为它\r\n在内部寻找转换为换行符)。因此,实现可能无法正确理解行长度,并且当您尝试在行中移动时会感到非常困惑。

此外,

可能必须在输入和输出时添加、更改或删除字符,以符合在主机环境中表示文本的不同约定。

请记住,库不会只是在您调用时从文件中读取每个字节fgetc- 它会将整个文件(对于这么小的文件)读入流的缓冲区并对其进行操作。