C 字符串比较中的十六进制文字问题
我正在读取一个NES ROM文件,其中前四个字节是“\x4e\x45\x53\x1a”或NES\x1a。在我的实际代码中,给定的文件可以是任意的,因此我想检查以确保该头文件在这里。但是,我遇到了一些问题,下面的代码演示了这一点:C 字符串比较中的十六进制文字问题,c,hex,fopen,strcmp,C,Hex,Fopen,Strcmp,我正在读取一个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];
#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;
}
其中问号为\x1a
我是C新手,所以我可能遗漏了一些微妙的(或明显的)东西,关于为什么两个字符串不匹配,以及为什么打印行D时问号不显示,以表示\x1a在字符串的末尾,而B行似乎表示它应该在那里。一些评论和建议:
- 以二进制模式打开文件-否则,在非POSIX系统上可能会发生有趣的事情(已修复)
- 如果要打印或比较缓冲区,或使用诸如
之类的函数(这些函数接受字符串的长度作为额外参数),请使用null终止缓冲区strncmp()
printf("C: %.4s\n", nes); printf("D: %.4s\n", real_nes); if (strncmp(nes, real_nes, 4) != 0) {
是非图形替换字符'\x1a'
^Z
- 检查io函数的返回值是否存在错误
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;
}
按如下方式更改代码:
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;
}
看看它是否有效。代码中的主要问题是:
char real_nes[4] = "NES\x1a";
这不是字符串,因为它不以nul终止符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.不要在非零终止字节数组上使用字符串函数 问题是您有两个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");
}
inti;
printf(“读取字节:0x”);
对于(i=0;i
可能有点晚了,但我是这样做的:
// 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时,您不需要考虑空终止符。毕竟,您实际上并没有使用字符串,而是更像是字符数组,这与空终止符不同。由于除了调试之外,您实际上不需要打印签名,因此您根本不应该关心使用字符串函数。strncmp()比较正确,因此我将其归因于一些奇怪之处,因为没有空终止符。谢谢。谢谢你对字符串的更全面的解释。即使在这个例子中,当执行
fread(nes,4,1,fp)时代码>您没有将空终止符添加到nes[4],因此比较可能也不起作用<代码>网元[4]=0应该添加code>。Pablo,你为什么用fread(nes,4,1,fp)
纠正fread(nes,1,4,fp)
,它们不都读取4字节吗?(这是一个问题,不是挑战)是的,他们都在读4个字节。但您应该将每个成员的大小放在第一个参数上,并在第二个参数上读取count。因为他正在读取字符(1字节),所以第一个参数应该是1。这样,如果捕获fread的返回值(读取的元素数),您将获得正确的大小。