【问题标题】:Why does sscanf changing the value of original char array?为什么 sscanf 会改变原始 char 数组的值?
【发布时间】:2021-11-18 03:29:19
【问题描述】:

我不明白 sscanf 的工作原理。

#include <stdio.h>
#include <string.h>

int main(void)
{

    char s[100] = "testtes te asdf newlinetest";

    char parm1[10];
    char parm2[4];
    char parm3[256];
    char parm4[10];

    printf("BEFORE: %s\n", s);
    sscanf(s, "%s %s %s %s", parm1, parm2, parm3, parm4);
    printf("AFTER: %s\n", s);

    return (0);
}

输出:

BEFORE: testtes te asdf newlinetest
AFTER: t

似乎是在打印最后一个字符,但是当 parm1 的大小为 90 时,它会打印正确的输出。

输出:

BEFORE: testtes te asdf newlinetest
AFTER: testtes te asdf newlinetest

【问题讨论】:

  • parm4 没有足够的空间容纳第 4 个单词。

标签: c scanf c-strings


【解决方案1】:

parm4 中的空间不足,无法容纳 "newlinetest"parm4 可以容纳 10 个字符,但 "newlinetest" 是 11 个字符长,加上空字符需要一个额外的字符,所以需要 12 个字符来容纳它。在将前 10 个字符写入parm4 之后,它继续运行,将t\0 写入parm4 之后的内存,在这种情况下显然是s。所以s 最终持有"t"

请注意,这是未定义的行为,您不能指望它会以这种方式行事。

【讨论】:

    【解决方案2】:

    param4 不够大,无法容纳字符串“newlinetest”。结果,当sscanf 写入它时,它会写入数组的末尾。这会触发undefined behavior

    在这个特殊案例中,s 恰好出现在内存中的param4 之后,所以s 的前几个字节被覆盖了。然而,这只是程序可能表现的一种方式。它本来可以正常工作的。

    通过使param4 更大,可以防止写入超出数组末尾。

    【讨论】:

      【解决方案3】:

      存在内存覆盖,因为以下数组仅使用 10 之类的字符声明

      char parm4[10];
      

      并且您正尝试向其写入包含 12 字符的字符串 "newlinetest",其中包括终止零字符 '\0'

      至少用12 个字符声明数组

      char parm4[12];
      

      你会得到预期的结果。

      【讨论】:

        【解决方案4】:

        除了答案中已经说过的,当你使用sscanf()解析字符串时,最好使用宽度修饰符:

        #include <stdio.h>
        #include <string.h>
        
        int main(void)
        {
            char s[100] = "testtes te asdf newlinetest";
        
            char parm1[10];
            char parm2[4];
            char parm3[256];
            char parm4[12]; // 12 since your last word contains 11 characters (+1 for \0)
        
            printf("BEFORE: %s\n", s);
            sscanf(s, "%9s %3s %255s %11s", parm1, parm2, parm3, parm4);
            printf("AFTER: %s\n", s);
        }
        

        您的输出应如下所示:

        BEFORE: testtes te asdf newlinetest
        AFTER: testtes te asdf newlinetest
        

        【讨论】:

          猜你喜欢
          • 2019-07-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-17
          • 1970-01-01
          • 2019-10-14
          • 2016-06-24
          • 2015-06-06
          相关资源
          最近更新 更多