为什么fread(fmtChunkId,sizeof(char),4,fp);读了11个字符?

时间:2016-08-19 22:08:10

标签: c++ char declaration fread

以下是我遇到问题的代码部分:

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;
}

1 个答案:

答案 0 :(得分:1)

字符串文字"WAVE"实际上是5个字节长,因为C风格的字符串必须以空字符\0结尾。由于您仅使用4个字符声明typefmtChunkId,因此strcmp函数和cout <<语句实际上会一直读取超过4个字节的结尾,直到它达到{{1 }}。 (如果它在遇到未经授权的内存之前没有遇到\0,则会导致段错误。)

因此,对于\0,它打印出一些额外的垃圾字符,因为它是在下一个fmtChunkId之前在内存中找到的内容。使用\0时,下一个字节恰好是type,因此无意中有效。

正如其他评论者所提到的,一个解决方案是将字符串初始化为5的长度,并在\0之后但fread之前将最后一个字节设置为0。

更有说服力的解决方案是使用memcmp,它直接比较字节(这是你真正想要的)而不是字符串:

strcmp