【问题标题】:snprintf formatting specifiersnprintf 格式说明符
【发布时间】:2013-08-28 16:23:13
【问题描述】:

在我的代码中,我使用如下 snprintf 并且可以看到以下行为

char text[30] = {0};

snprintf(text, sizeof(text), "%s", "hello");
printf("Interm... %s\n", text);
snprintf(text, "%20s", text);
printf("At the end ... %s\n", text);

输出

Interm... hello
At the end ... 

您可以看到 snprintf 的源和目标是否相同,它会清除缓冲区。我希望输出采用 20 年代的格式说明符。我不能在第一步中执行此操作,因为我需要在最后一步附加多个字符串并执行格式说明符。

复制到临时缓冲区并从那里复制到原始缓冲区是唯一可能的解决方案吗?能否请您对此有所了解。

【问题讨论】:

  • text 是如何声明的?
  • 第二个snprintf 不好,但我更好奇第一个如何将“kiruba”变成“hello”
  • 第二个 snprintf() 比这更糟糕...它缺少缓冲区大小参数。
  • @Wumpus : 抱歉输入“kiruba”的类型错误..现在我在问题部分更正了

标签: c string printf


【解决方案1】:

来自snprintfman page

C99 和 POSIX.1-2001 指定结果是未定义的,如果调用 到 sprintf()、snprintf()、vsprintf() 或 vsnprintf() 会导致 复制发生在重叠的对象之间(例如,如果 目标字符串数组和提供的输入参数之一是指 相同的缓冲区)。

这意味着该行

snprintf(text, "%20s", text)

无效。您关于使用额外的临时缓冲区的建议是正确的。

【讨论】:

    【解决方案2】:

    为了实现您的目标:str1 后跟 str2,所有这些在左侧用空格填充,或在右侧截断,长度为 (wid) 个字符,存储在 outbuf 中(必须至少为 wid+ 1 个字符宽)您只能使用一个 sprintf...

    size_t len1=strlen(str1), len2=strlen(str2);
    if (len2 > wid-len1) { len2 = wid-len1; }
    snprinf(outbuf, wid+1, "%*s%.%s", wid-len2, str1, len2, str2);
    

    注意 (wid-len2) 是 str1 在输出上的填充大小, len2 是 str2 在输出上的截断大小。 snprintf() 中的 wid+1 缓冲区大小是对 len1>wid 的病态情况的防范。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-13
      • 2013-08-28
      • 1970-01-01
      • 2017-11-16
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多