首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >斯堪夫的奇怪行为

斯堪夫的奇怪行为
EN

Stack Overflow用户
提问于 2014-02-21 12:45:17
回答 3查看 531关注 0票数 0

我发现了一些奇怪的东西。下面是代码示例:

代码语言:javascript
运行
复制
...
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}“。

有人能解释一下吗?

这是手臂平台。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-21 13:39:12

代码语言:javascript
运行
复制
int num = sscanf(start, "(%s)", buf);

在这里,当sscanf遇到start指向的缓冲区中的空白时,它会返回。输入字符串中有一个空格:

代码语言:javascript
运行
复制
"([34]xx{4,7}| 1234567890)"
              ^ space here

scanf返回成功匹配和分配的输入项数。在这里,它将返回1,而num的值是1。接下来,用buf块中的这个语句覆盖if中的最后一个字符。

代码语言:javascript
运行
复制
buf[strlen(buf) - 1] = '\0';

这解释了你的程序的输出。现在,关于您的代码的一些事情:

你不需要做memset(buf, 0, LEN);。只需执行char buf[LEN] = {0};,就可以用空字节填充数组。

sscanf不检查正在写入sscanfstart读取的字符串的缓冲区buf的数组绑定。如果buf的大小不够,sscanf将尝试写入缓冲区buf以外的内存。这将导致未定义的行为,甚至程序崩溃,因为非法的内存访问。您应该在sscanf的格式字符串中给出字段宽度,以防止缓冲区溢出。

代码语言:javascript
运行
复制
#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块中不需要以下内容:

代码语言:javascript
运行
复制
buf[strlen(buf) - 1] = '\0'; // overwrites the last char before null byte in buf.

实际上,这样做会覆盖buf中的最后一个字符,因为strlen不计算空字节。

票数 2
EN

Stack Overflow用户

发布于 2014-02-21 12:53:14

sscanf与%s一起使用,当它遇到空白时,它将终止。这就是为什么要将输出作为“34 as {4,7}”而不是预期的行为的原因。

票数 1
EN

Stack Overflow用户

发布于 2014-02-21 12:57:39

格式字符串由一系列指令组成,这些指令描述如何处理输入字符的序列。如果指令处理失败,则不会读取进一步的输入,scanf()将返回。" failure“可以是以下两种之一:输入失败,意味着输入字符不可用,或者匹配失败,这意味着输入不合适(见下文)。

在您的示例中,sscanf匹配启动的(,然后解析下一个令牌,%s,它消耗数据直到第一个空白字符。然后,sscanf无法匹配),这意味着解析将停止。成功读取并分配了一个令牌,因此返回值为1

注意,当使用scanf时,您无法检测在分配的最后一个令牌之后发生的匹配失败。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21934858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档