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 下 运行,那么您应该始终使用 rb
和 wb
用于二进制文件。 Unix 忽略 b
并告诉 Windows 停止弄乱你的文件。
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 下 运行,那么您应该始终使用 rb
和 wb
用于二进制文件。 Unix 忽略 b
并告诉 Windows 停止弄乱你的文件。