C++如何在switch-case中使用char缓冲区数组匹配wav文件头标识
现有代码的核心问题
- 数组越界访问:你定义的
Buffer长度为4,合法下标范围是0~3,代码中switch(Buffer[4])访问的是数组之外的内存,拿到的完全是随机垃圾值,不可能匹配上预设的case。 - 匹配逻辑错误:
'R'+'I'+'F'+'F'是四个字符的ASCII码数值相加的和,不同字符组合很容易出现相同的和,完全无法用来匹配固定的4字节序列。 - 缺少break语句:switch的每个case结束后如果不加break,就算命中了当前case,也会继续执行后面所有case的逻辑。
- 读写逻辑有漏洞:没有判断文件是否打开成功,循环读也没有判断fread的返回值,文件读结束后不会退出循环,还会导致资源泄漏。
正确实现方案
要使用switch匹配4字节固定序列,可以将4个char拼接为一个4字节无符号整数,再匹配对应的常量值即可。移位拼接的写法不受系统端序影响,兼容性最好,修正后的代码如下:
#include <iostream> #include <string> #include <cstdint> using namespace std; int main() { string filename; cout << "First Input filename:" << endl; cin >> filename; #pragma warning (disable : 4996) FILE* InFile = fopen(filename.c_str(), "rb"); if (!InFile) { cout << "文件打开失败" << endl; return -1; } char Buffer[4]; // 读取前4字节,确认读取成功 if (fread(Buffer, sizeof(Buffer[0]), 4, InFile) == 4) { // 将4个char拼接为uint32_t类型整数 uint32_t magic_num = static_cast<uint32_t>(Buffer[0]) | (static_cast<uint32_t>(Buffer[1]) << 8) | (static_cast<uint32_t>(Buffer[2]) << 16) | (static_cast<uint32_t>(Buffer[3]) << 24); switch (magic_num) { // 匹配RIFF序列 case static_cast<uint32_t>('R') | (static_cast<uint32_t>('I') << 8) | (static_cast<uint32_t>('F') << 16) | (static_cast<uint32_t>('F') << 24): cout << "Riff is found " << endl; break; // 匹配crif序列 case static_cast<uint32_t>('c') | (static_cast<uint32_t>('r') << 8) | (static_cast<uint32_t>('i') << 16) | (static_cast<uint32_t>('f') << 24): cout << "CRiff is found " << endl; break; default: cout << "未匹配到预期序列,读取到的前4字节为:" << Buffer[0] << Buffer[1] << Buffer[2] << Buffer[3] << endl; } } fclose(InFile); return 0; }
如果确认运行环境为小端架构(普通x86/x64的Windows、Linux系统都属于小端),也可以直接用多字符字面量简化case的写法:case 'FFIR':,效果和上面的移位写法完全一致。
内容的提问来源于stack exchange,提问作者Omar
相关产品推荐
相关产品推荐

