我发现了一些奇怪的东西。下面是代码示例:
...
char *start = strchr(value, '(');
if(start)
{
char buf[LEN];
memset(buf, 0, LEN);
int num = sscanf(start, "(%s)", buf);
if(num)
{
buf[strlen(buf) - 1] = '\0';
sprintf(value, "%s", buf);
}
...
例如,如果值为"(xxx)",则此操作之后的值将为"xxx“。
但如果值为“(34xx{4,7}\ 1234567890)”,则值将为"34xx{4,7}“。
有人能解释一下吗?
这是手臂平台。
发布于 2014-02-21 13:39:12
int num = sscanf(start, "(%s)", buf);
在这里,当sscanf
遇到start
指向的缓冲区中的空白时,它会返回。输入字符串中有一个空格:
"([34]xx{4,7}| 1234567890)"
^ space here
scanf
返回成功匹配和分配的输入项数。在这里,它将返回1
,而num
的值是1
。接下来,用buf
块中的这个语句覆盖if
中的最后一个字符。
buf[strlen(buf) - 1] = '\0';
这解释了你的程序的输出。现在,关于您的代码的一些事情:
你不需要做memset(buf, 0, LEN);
。只需执行char buf[LEN] = {0};
,就可以用空字节填充数组。
sscanf
不检查正在写入sscanf
从start
读取的字符串的缓冲区buf
的数组绑定。如果buf
的大小不够,sscanf
将尝试写入缓冲区buf
以外的内存。这将导致未定义的行为,甚至程序崩溃,因为非法的内存访问。您应该在sscanf
的格式字符串中给出字段宽度,以防止缓冲区溢出。
#define STRINGIFY(s) #s // preprocessor command # stringifies the token s
#define XSTRINGIFY(s) STRINGIFY(s)
#define LEN 10 // max buffer length without the null byte
// inside a function
char buf[LEN + 1]; // +1 for the null byte
const char *format = "(" XSTRINGIFY(LEN) "%s)"; // "(%10s)"
int num = sscanf(start, format, buf);
格式字符串10
"(%10s)"
意味着最多将10
字符存储在buf
指向的缓冲区中,最后自动添加空字节\0
。因此,在if
块中不需要以下内容:
buf[strlen(buf) - 1] = '\0'; // overwrites the last char before null byte in buf.
实际上,这样做会覆盖buf
中的最后一个字符,因为strlen
不计算空字节。
发布于 2014-02-21 12:53:14
sscanf与%s一起使用,当它遇到空白时,它将终止。这就是为什么要将输出作为“34 as {4,7}”而不是预期的行为的原因。
发布于 2014-02-21 12:57:39
格式字符串由一系列指令组成,这些指令描述如何处理输入字符的序列。如果指令处理失败,则不会读取进一步的输入,scanf()将返回。" failure“可以是以下两种之一:输入失败,意味着输入字符不可用,或者匹配失败,这意味着输入不合适(见下文)。
在您的示例中,sscanf
匹配启动的(
,然后解析下一个令牌,%s
,它消耗数据直到第一个空白字符。然后,sscanf
无法匹配)
,这意味着解析将停止。成功读取并分配了一个令牌,因此返回值为1
。
注意,当使用scanf
时,您无法检测在分配的最后一个令牌之后发生的匹配失败。
https://stackoverflow.com/questions/21934858
复制相似问题