我正在尝试从字符串中提取两个值。第一个是8位十六进制值,第二个是无符号1-4位数值。这些值之前还应该有一个命令,该命令告诉程序如何处理这些值,在本例中为“read”。格式的一些例子:
"read 0x1234ABCD 2000"
"read 0x00000001 10"
我想要提取两个值并确认格式,并且具有以下代码行:
uint addr;
uint len;
int n = sscanf(str, "read 0x%x[0-9a-fA-F]{8} %u[0-9]{1,4}", &addr, &len);
if (n != 2){
// Wrong format...
}
正确读取十六进制值,但第二个值不正确,n总是1.我做错了什么?
答案 0 :(得分:3)
我做错了什么?
Input: "read 0x1234ABCD 2000"
Format: "read 0x%x[0-9a-fA-F]{8} %u[0-9]{1,4}"
输入"read 0x"
与格式"read 0x"
匹配。好到目前为止。
输入"1234ABCD"
与格式"%x"
匹配。目前很好。 +返回值。
输入" "
与格式"["
不匹配。扫描停止。 sscanf()
返回1.
替代方案,将第二个值读作十进制值。
const char *f1 = "read 0x%x %u";
const char *f2 = "read 0x%x%u"; // Space not need, yet looks good
const char *f3 = "read %x%u"; // Always read addr as hex, even with/without 0x
const char *f4 = "read %x %u";
const char *f5 = "read%x%u";
unsigned addr;
unsigned len;
int n = sscanf(str, fn, &addr, &len); // select format from above
以上代码不会失败
"read 0x0x123 +1234"
"read 0x123 456 xyz"
"read 0x123 12345"
"read 0x+123 -123"
OP是否需要更多错误检查。 8将addr
的文本输入限制为8个非空白字符。 sentinel
检测到拖尾的非白色空间垃圾。
unsigned addr;
unsigned len;
char sentinel;
int n = sscanf(str, "read 0x%8x %4u %c", &addr, &len, &sentinel);
if (n != 2){
// Wrong format...
}
以上确实失败
"read 0x123 456 xyz"
最接近OP原始代码的内容需要更多工作。使用"%[...]"
测试允许的扫描集。
#define F_RD "read"
#define F_SP "%*[ ]"
#define F_ADDR "0x%8[0-9a-fA-F]"
#define F_LEN "%4[0-9]"
#define F_SEN " %c"
char addr_s[8+1];
char len_s[4+1];
char sentinel;
int n = sscanf(str, F_RD F_SP F_ADDR F_SP F_LEN F_SEN, addr_s, len_s, &sentinel);
if (n == 2){
// Success
unsigned long addr = strtoul(addr_s, (char **)NULL, 16);
unsigned len = strtoul(len_s, (char **)NULL, 10);
...
}
除了我允许x
或X
之外,我没有看到此代码没有失败/传递的输入行,除非我允许<input type="checkbox" name="day_of_week[]" value="1">Monday
<input type="checkbox" name="day_of_week[]" value="2">Tuesday
<input type="checkbox" name="day_of_week[]" value="3">Wednessday
<input type="checkbox" name="day_of_week[]" value="4">Thursday
<input type="checkbox" name="day_of_week[]" value="5">Friday
<input type="checkbox" name="day_of_week[]" value="6">Saturday
<input type="checkbox" name="day_of_week[]" value="7">Sunday
或string mysqli_real_escape_string ( mysqli $link , string $escapestr )
。
答案 1 :(得分:2)
要解析十六进制和十进制编码的数字,请使用%i
转换说明符。
使用您在格式字符串中使用的正则表达式语法无法指定位数,这解释了第二次转换失败的原因。
这是一个更简单的版本:
int n = sscanf(str, "read %i %i", &addr, &len);