使用sscanf从格式化字符串读取多个值
我试图从一个字符串中提取两个值。第一个是8位十六进制值,第二个是无符号1-4位值。这些值之前还应该有一个命令,告诉程序如何处理这些值,在本例中为“读取”。格式的一些示例:使用sscanf从格式化字符串读取多个值,c,regex,scanf,C,Regex,Scanf,我试图从一个字符串中提取两个值。第一个是8位十六进制值,第二个是无符号1-4位值。这些值之前还应该有一个命令,告诉程序如何处理这些值,在本例中为“读取”。格式的一些示例: "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, &
"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。我做错了什么?要解析十六进制和十进制编码的数字,请使用
%I
转换说明符
无法使用格式字符串中使用的正则表达式语法指定位数,这解释了第二次转换失败的原因
以下是一个更简单的版本:
int n = sscanf(str, "read %i %i", &addr, &len);
我做错了什么
输入“read 0x”
与格式“read 0x”
匹配。到目前为止还不错
输入“1234ABCD”
与格式“%x”
匹配。到目前为止还不错+返回值为1
输入“
与格式”[“
不匹配。扫描停止。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所希望的那样失败/通过,除了我允许
x
或x
scanf
不做正则表达式。要读取多达八个十六进制数字,只需使用%8x
。例如,@Someprogrammerdude.Hmm,我想知道这个答案()。这不是正则表达式吗?假设你的意思是“%[0-9]”,那么它不是正则表达式,但它是一个使用简单字符类的变体。好的,我在sscanf“read 0x%8x%u”中尝试了以下方法,效果很好。谢谢!@AndrewHenle Agreescanf()
可能是一个挑战,但更大的挑战,IMO,是语法要求从一开始就不完整:只提供一些可接受的表单和一些不可接受的表单。当允许原始目标不精确时,任何解决方案都容易出现维护问题。第一个%i真的能确保将值解析为十六进制?我知道数字是否有A-F字符,但如果数字是“00000010”怎么办?这将被解读为16还是10?@Martin--您的问题的答案在文档中。%i
希望输入的格式为。00000010
将被解读为八进制数字,十进制数字为8。如果您希望输入被解读为十六进制,请使用0x00000010
或0x00000010
。请注意错误检查版本输入“读取0x75088FF08”
@DavidBowling时不会失败请参见编辑
"read 0x123 456 xyz"
#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);
...
}