我正在读NES ROM文件,其中前四个字节是“\ x4e \ x45 \ x53 \ x1a”或NES \ x1a。在我的实际代码中,给定的文件可以是任意的,所以我想检查以确保此标头在这里。但是,我遇到了一些麻烦,以下代码演示了:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
fp = fopen("mario.nes", "rb");
char nes[4];
char real_nes[4] = "NES\x1a";
fread(nes, 4, 1, fp);
printf("A: %x\n", nes[3]);
printf("B: %x\n", real_nes[3]);
printf("C: %s\n", nes);
printf("D: %s\n", real_nes);
if (strcmp(nes, real_nes) != 0) {
printf("not a match\n");
}
fclose(fp);
return 0;
}
返回:
A: 1a
B: 1a
C: NES?
D: NES
not a match
问号是\ x1a。
我是C的新手,所以我可能会遗漏一些微妙的(或明显的)两个字符串不匹配的原因,以及为什么在打印D行时没有显示问号,以表示\ x1a位于字符串的末尾,B行似乎表明它应该是。
答案 0 :(得分:4)
一些评论和建议:
以二进制模式打开文件 - 否则,非POSIX系统上可能会发生有趣的事情(已修复)
fp = fopen("mario.nes", "rb");
如果要打印或比较缓冲区,请使用null终止缓冲区,或使用接受字符串长度作为额外参数的strncmp()
等函数
printf("C: %.4s\n", nes);
printf("D: %.4s\n", real_nes);
if (strncmp(nes, real_nes, 4) != 0) {
'\x1a'
是非图形替代字符^Z
答案 1 :(得分:2)
嗯,一个问题是你使用 strcmp 。此函数需要一个ZERO-TERMINATED字符串( nes 和 real_nes 都不是代码中以零结尾的字符串)。
另一个问题是 fread 。像这样使用它:
fread(nes, 1, 4, fp); // first size_t param is size and second is member count
更改您的代码:
int main()
{
FILE *fp;
fp = fopen("mario.nes", "rb");
char nes[5];
char real_nes[5] = "NES\x1a";
fread(nes, 1, 4, fp);
nes[4] = '\0';
printf("A: %x\n", nes[3]);
printf("B: %x\n", real_nes[3]);
printf("C: %s\n", nes);
printf("D: %s\n", real_nes);
if (strcmp(nes, real_nes) != 0) {
printf("not a match\n");
}
fclose(fp);
return 0;
}
看看它是否有效。
答案 2 :(得分:1)
代码中的主要问题是:
char real_nes[4] = "NES\x1a";
这不是字符串,因为它不以nul-terminator char('\ 0')结尾。 对于'nes'来说,这是同样的问题。
只需声明它们:
char real_nes[] = "NES\x1a"; /* this is a string, ended by '\0' */
char nes[sizeof real_nes];
确保'\ 0'的位置正确。
现在您可以使用%s说明符或strcmp()。无论如何,我建议改为使用strncmp(),比如:
if(0 != strncmp(real_nes, nes, sizeof real_nes)) { /* some stuff */ }
HTH。
答案 3 :(得分:1)
不要在非零终止的字节数组上使用字符串函数。
问题是你有两个4字节数组,它们应该包含字符串“NES \ x1a”('\ 0'没有剩余空间,因为它已经是4个字节长),但%s格式和strcmp需要一个'\ 0'结束时终止知道字符串结束。这就是它无法正常工作的原因。
1:不要在此字节数组上使用%s格式的printf。 2:使用memcmp比较字节。
请改为尝试:
int i;
printf("Read bytes: 0x");
for(i = 0; i < sizeof(nes); i ++)
printf("%02X", nes[i]);
printf("\n");
if (memcmp(nes, real_nes, sizeof(nes)) != 0) {
printf("not a match\n");
}
答案 4 :(得分:1)
可能有点太晚了,但我的方法就是这样:
// Read the 16 byte iNES header
char header[16];
fread( header, 16, 1, file );
// Search for the "NES^Z" signature
if( memcmp( header, "NES\x1A", 4 ) )
{
正如Xeno所建议的,使用memcmp你不关心null终止符。毕竟,你并没有真正使用字符串,而是更像char数组,由于null终止符而不一样。因为除了调试之外你真的不需要打印签名,所以你根本不应该使用字符串函数。