为什么 fread(fmtChunkId, sizeof(char), 4, fp);读11个字符?
Why does fread(fmtChunkId, sizeof(char), 4, fp); read 11 characters?
这是我遇到问题的代码部分:
fread(fmtChunkId, sizeof(char), 4, fp);
if(strcmp(fmtChunkId, "WAVE") != 0) {
cout << "Not WAVE format: " << fmtChunkId << endl;
return 0;
}
当我 运行 程序时,它打印 Not WAVE format: WAVE e∞@
,它有 11 个字符长,而不是 4 个字符。但是,当我将 fmtChunkId
替换为 type
时,它可以正常工作,这让我感到困惑,因为我将这两个变量声明为相同。
#include <iostream>
#include <string.h>
using namespace std;
int main() {
/*Get file path*/
char filepath[261];
cout << "Please enter the file path of a .wav file: ";
cin.getline(filepath, sizeof(filepath));
FILE *fp = NULL;
fp = fopen(filepath, "rb");
if(!fp) {
cout << "Failed to open file: " << filepath;
return 0;
}
cout << endl;
/*Declarations*/
char type[4];
char riffChunkId[4];
int riffChunkSize;
char fmtChunkId[4];
int fmtChunkSize;
short audioFormat;
short numChannels;
int sampleRate;
int byteRate;
short blockAlign;
short bitsPerSample;
int dataSize;
/*Read file data*/
fread(riffChunkId, sizeof(char), 4, fp);
if(strcmp(riffChunkId, "RIFF") != 0) {
cout << "Not RIFF format: " << riffChunkId << endl;
return 0;
}
fread(&riffChunkSize, sizeof(int), 1, fp);
fread(fmtChunkId, sizeof(char), 4, fp);
if(strcmp(fmtChunkId, "WAVE") != 0) {
cout << "Not WAVE format: " << fmtChunkId << endl;
return 0;
}
fread(type, sizeof(char), 4, fp);
if(strcmp(type, "fmt ") != 0) {
cout << "Not fmt: " << type << endl;
return 0;
}
fread(&fmtChunkSize, sizeof(int), 1, fp);
fread(&audioFormat, sizeof(short), 1, fp);
fread(&numChannels, sizeof(short), 1, fp);
fread(&sampleRate, sizeof(int), 1, fp);
fread(&byteRate, sizeof(int), 1, fp);
fread(&blockAlign, sizeof(short), 1, fp);
fread(&bitsPerSample, sizeof(short), 1, fp);
fread(type, sizeof(char), 4, fp);
if(strcmp(type, "data") != 0) {
cout << "Not data: " << type << endl;
return 0;
}
fread(&dataSize, sizeof(int), 1, fp);
/*Print file data*/
cout << "RIFF Chunk Size: " << riffChunkSize << endl;
cout << "fmt Chunk Size: " << fmtChunkSize << endl;
cout << "Audio Format: " << audioFormat << endl;
cout << "Number of Channels: " << numChannels << endl;
cout << "Sample Rate: " << sampleRate << endl;
cout << "byteRate: " << byteRate << endl;
cout << "blockAlign: " << blockAlign << endl;
cout << "Bits Per Sample: " << bitsPerSample << endl << endl;
return 0;
}
字符串文字 "WAVE"
实际上是 5 个字节长,因为 C 风格的字符串必须以空字符 [=12=]
结尾。由于您声明 type
和 fmtChunkId
只有 4 个字符,因此 strcmp
函数和 cout <<
语句实际上会继续读取超过 4 个字节的末尾,直到它遇到 [=12 =]
. (如果它在进入未经授权的内存之前没有命中 [=12=]
,这可能会导致段错误)。
因此,对于 fmtChunkId
,它会打印出一些额外的垃圾字符,因为这是它在下一个 [=12=]
之前在内存中找到的内容。对于 type
,下一个字节恰好是 [=12=]
,所以它意外地工作了。
正如其他评论者提到的,一个解决方案是将字符串初始化为 5 的长度,并在 fread
之后但在 strcmp
.
之前将最后一个字节设置为 0
一个更eloquent的解决方案是使用memcmp
,它直接比较字节(这是你真正想要的)而不是字符串:
fread(fmtChunkId, sizeof(char), 4, fp);
if(memcmp(fmtChunkId, "WAVE", 4) != 0) {
cout << "Not WAVE format" << endl;
return 0;
}
这是我遇到问题的代码部分:
fread(fmtChunkId, sizeof(char), 4, fp);
if(strcmp(fmtChunkId, "WAVE") != 0) {
cout << "Not WAVE format: " << fmtChunkId << endl;
return 0;
}
当我 运行 程序时,它打印 Not WAVE format: WAVE e∞@
,它有 11 个字符长,而不是 4 个字符。但是,当我将 fmtChunkId
替换为 type
时,它可以正常工作,这让我感到困惑,因为我将这两个变量声明为相同。
#include <iostream>
#include <string.h>
using namespace std;
int main() {
/*Get file path*/
char filepath[261];
cout << "Please enter the file path of a .wav file: ";
cin.getline(filepath, sizeof(filepath));
FILE *fp = NULL;
fp = fopen(filepath, "rb");
if(!fp) {
cout << "Failed to open file: " << filepath;
return 0;
}
cout << endl;
/*Declarations*/
char type[4];
char riffChunkId[4];
int riffChunkSize;
char fmtChunkId[4];
int fmtChunkSize;
short audioFormat;
short numChannels;
int sampleRate;
int byteRate;
short blockAlign;
short bitsPerSample;
int dataSize;
/*Read file data*/
fread(riffChunkId, sizeof(char), 4, fp);
if(strcmp(riffChunkId, "RIFF") != 0) {
cout << "Not RIFF format: " << riffChunkId << endl;
return 0;
}
fread(&riffChunkSize, sizeof(int), 1, fp);
fread(fmtChunkId, sizeof(char), 4, fp);
if(strcmp(fmtChunkId, "WAVE") != 0) {
cout << "Not WAVE format: " << fmtChunkId << endl;
return 0;
}
fread(type, sizeof(char), 4, fp);
if(strcmp(type, "fmt ") != 0) {
cout << "Not fmt: " << type << endl;
return 0;
}
fread(&fmtChunkSize, sizeof(int), 1, fp);
fread(&audioFormat, sizeof(short), 1, fp);
fread(&numChannels, sizeof(short), 1, fp);
fread(&sampleRate, sizeof(int), 1, fp);
fread(&byteRate, sizeof(int), 1, fp);
fread(&blockAlign, sizeof(short), 1, fp);
fread(&bitsPerSample, sizeof(short), 1, fp);
fread(type, sizeof(char), 4, fp);
if(strcmp(type, "data") != 0) {
cout << "Not data: " << type << endl;
return 0;
}
fread(&dataSize, sizeof(int), 1, fp);
/*Print file data*/
cout << "RIFF Chunk Size: " << riffChunkSize << endl;
cout << "fmt Chunk Size: " << fmtChunkSize << endl;
cout << "Audio Format: " << audioFormat << endl;
cout << "Number of Channels: " << numChannels << endl;
cout << "Sample Rate: " << sampleRate << endl;
cout << "byteRate: " << byteRate << endl;
cout << "blockAlign: " << blockAlign << endl;
cout << "Bits Per Sample: " << bitsPerSample << endl << endl;
return 0;
}
字符串文字 "WAVE"
实际上是 5 个字节长,因为 C 风格的字符串必须以空字符 [=12=]
结尾。由于您声明 type
和 fmtChunkId
只有 4 个字符,因此 strcmp
函数和 cout <<
语句实际上会继续读取超过 4 个字节的末尾,直到它遇到 [=12 =]
. (如果它在进入未经授权的内存之前没有命中 [=12=]
,这可能会导致段错误)。
因此,对于 fmtChunkId
,它会打印出一些额外的垃圾字符,因为这是它在下一个 [=12=]
之前在内存中找到的内容。对于 type
,下一个字节恰好是 [=12=]
,所以它意外地工作了。
正如其他评论者提到的,一个解决方案是将字符串初始化为 5 的长度,并在 fread
之后但在 strcmp
.
一个更eloquent的解决方案是使用memcmp
,它直接比较字节(这是你真正想要的)而不是字符串:
fread(fmtChunkId, sizeof(char), 4, fp);
if(memcmp(fmtChunkId, "WAVE", 4) != 0) {
cout << "Not WAVE format" << endl;
return 0;
}