字符串比较中的十六进制文字问题
我正在读取一个 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 行似乎表明它应该是。
I'm reading in an NES ROM file, where the first four bytes are "\x4e\x45\x53\x1a", or NES\x1a. In my actual code, the given file can be arbitrary, so I want to check to make sure this header is here. However, I'm running into some trouble, which the following code demonstrates:
#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;
}
which returns:
A: 1a
B: 1a
C: NES?
D: NES
not a match
where the question mark is \x1a.
I'm new to C, so it's possible I'm missing something subtle (or obvious) about why the two strings don't match, and why the question mark doesn't show when printing line D, to signify that \x1a is there at the end of the string, which line B seems to indicate it should be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
代码中的主要问题是:
这不是一个字符串,因为它不以空终止符字符('\0')结尾。
这对于“nes”来说也是同样的问题。
只需这样声明它们即可:
确保有足够的位置用于 '\0'。
现在您可以使用 %s 说明符或 strcmp()。无论如何,我建议使用 strncmp() 代替,例如:
HTH.
The major problem in your code is:
This not a string, since it does not end with the nul-terminator char ('\0').
This is the same problem for 'nes'.
Just declare them like:
To be sure that there is enouth place for the '\0'.
Now you can use the %s specifier, or strcmp(). Anyway, I recommand the use of strncmp() instead, like in:
HTH.
不要在非零终止字节数组上使用字符串函数。
问题是您有两个 4 字节数组,其中应包含字符串“NES\x1a”(没有为“\0”留下空间,因为它已经是 4 个字节长),但 %s 格式和 strcmp 需要“\0” ' 在末尾终止以知道字符串结束。这就是它无法正常工作的原因。
1.: 不要在此字节数组上使用 %s 格式的 printf。
2.:使用memcmp比较字节。
试试这个:
Do not use string functions on not-zero-terminated byte arrays.
The problem is you have two 4 byte arrays which should contain the string "NES\x1a" (no space left for '\0' since it is already 4 bytes long), but the %s format and the strcmp need a '\0' termination at the end to know the strings end. That's why it doesn't work correctly.
1.: Do not use printf with %s format on this byte array.
2.: Use memcmp to compare the bytes.
Try this instead:
也许有点太晚了,但我是这样做的:
正如 Xeno 提议的那样,使用 memcmp 你不关心空终止符。毕竟,您并不是真正使用字符串,而更像是 char 数组,由于 null 终止符,这并不相同。由于除了调试之外,您实际上并不需要打印签名,因此您根本不应该关心使用字符串函数。
A little too late maybe, but here's how I do it:
As Xeno proposed, with memcmp you don't care about null terminators. After all, you are not really using strings, but more like char arrays, which is not the same due to the null terminators. As you don't really need to print the signature other than for debugging, you shouldn't care using string functions at all.
一些评论和建议:
以二进制模式打开文件 - 否则,在非 POSIX 系统上可能会发生有趣的事情(已修复)
如果您想打印或空终止您的缓冲区比较它们或使用像
strncmp()
这样的函数,它接受字符串的长度作为额外参数' \x1a'
是非图形替换字符^Z
Some remarks and suggestions:
open the files in binary mode - otherwise, funny things may happen on non-POSIX systems (fixed)
null-terminate your buffers if you want to print or compare them or use functions like
strncmp()
which accept the string's length as extra argument'\x1a'
is the non-graphic substitute character^Z
好吧,一个问题是您对 strcmp 的使用。此函数需要一个以零结尾的字符串(nes 和 real_nes 都不是代码中以零结尾的字符串)。
另一个问题是恐惧。像这样使用它:
像这样更改您的代码:
然后看看它是否有效。
Well, one problem is your use of strcmp. This function expects a ZERO-TERMINATED string (neither nes nor real_nes are zero-terminated string in your code).
Another problem is fread. Use it like this:
Change your code like this:
And see if it works.