CS50 Lab4:CS50 IDE (Codespaces) 工作正常,而 Windows 10 下的本地编译失败

CS50 Lab4: CS50 IDE (Codespaces) works correct, while local compilation under Windows 10 fails

CS50 Lab4 改变 .wav 文件音量的代码:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

const int HEADER_SIZE = 44;
uint8_t header[HEADER_SIZE];
int16_t buffer;

int main(int argc, char *argv[])
{
    // Check command-line arguments
    if (argc != 4)
    {
        printf("Usage: ./volume input.wav output.wav factor\n");
        return 1;
    }

    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    float factor = atof(argv[3]);

    fread(header, 1, HEADER_SIZE, input);

    fwrite(header, 1, HEADER_SIZE, output);

    int n = 0; // for debug purpose

    while (fread(&buffer, 2, 1, input))
    {
        buffer = buffer * (float)factor;
        fwrite(&buffer, 2, 1, output);
        if (n == 2115) // for debug purpose
        {
         if (n == 2111) // for debug purpose
         ;
        }
        printf("%d\n", n++); // for debug purpose
    }

    // Close files
    fclose(input);
    fclose(output);
}

问题是..它在 CS50 代码空间中完美运行 IDE:

但我所有的本地编译器(我试过:bcc32、cpp32、tcc、gcc、clang)给出了相同的结果——这个损坏文件的输出(必须是 345kb 的文件,但它是 5kb): https://cdn.discordapp.com/attachments/792992622196424725/964833387363852308/output.wav

我尝试了一些调试:

根据调试,它总是停在 2117 步(4608 缓冲区值)。

我想再次指出,在 CS50 IDE 中它工作正常并且它经历了所有 176399 个步骤:)

feof(input) 和 ferror() 调试:

请帮忙解开这个谜题!我不能休息,直到我明白那里出了什么问题..

在 Windows 上,您必须使用模式 rb(或 wb 用于写入)打开二进制文件。在 Unix 上,你应该这样做是为了可移植性,但实际上它可以以任何一种方式工作。 (而且跟编译器没有关系)

原因是在文本文件中,Windows将值为0x1A(即Ctl-Z)的字节视为EOF指示符。 Unix 不这样做;在 Unix 上,文件结尾是文件结束的地方。

此外,Windows 使用 two-character end-of-line 指示符 (\r\n),必须将其转换为单个 \n,因为 C 标准要求将文本文件中的 multi-character end-of-line 指示符转换为单个换行符(并在写入文件时转换回来)。这在 Unix 上也不会发生,因为 Unix 行尾已经是一个换行符。

所以在Windows,如果你读一个二进制文件没有指定b-for-binary打开模式,那么读会在文件的第一个0x1A处停止。在您的情况下,这似乎发生在第 2117 个字符读取时,但请注意,由于换行符转换,这可能不是文件中的第 2117 个字符。您可以尝试使用二进制编辑器查看您的文件,但最重要的是,如果您认为您的程序可能在 Windows 下 运行,那么您应该始终使用 rbwb 用于二进制文件。 Unix 忽略 b 并告诉 Windows 停止弄乱你的文件。