【问题标题】:Append formatted string to string in C without pointer arithmetic将格式化的字符串附加到 C 中的字符串而不使用指针算术
【发布时间】:2011-01-02 16:42:18
【问题描述】:

我写了一个非常简单的 C 函数来说明我想简化的内容:

void main(int argc, char *argv[])
{
    char *me = "Foo";
    char *you = "Bar";
    char us[100];
    memset(us, 100, 0x00);

    sprintf(us, "You: %s\n", you);
    sprintf(us + strlen(us), "Me: %s\n", me);
    sprintf(us + strlen(us), "We are %s and %s!\n", me, you);
    printf(us);
}

是否有标准库函数来处理我对sprintf 所做的事情并推进指针?

【问题讨论】:

  • “似乎应该有一个标准库函数”,c stdlib 没有像 Java 这样的其他语言那么广泛,所以我怀疑有
  • @hhafez,当场;转变回用 C 语言思考(与 Python 和 Java 相比)正是我所处的位置。

标签: c string append string-formatting


【解决方案1】:

您可能正在寻找strcat(或者更好的strncat)。

【讨论】:

  • 先格式化,再拼接。
  • @AJ,不,你可以使用相同的缓冲区,只是一直到它的末尾(虽然这有点低效,因为每次你调用strcat/strncat它需要重新扫描整个字符串)。
【解决方案2】:

sprintf 返回写入的非 NUL 字符数。

int len = 0;
len += sprintf(us+len, ...);
len += sprintf(us+len, ...);
...

【讨论】:

  • 哈,我想这有点简短,但仍然以同样的方式完成。
  • 没有。您的示例为每次迭代调用 strlen() ,这使得 sprintf() 调用次数为 O(N^2) 。这利用了 printf 系列函数返回打印的字符数以免费获得 strlen 结果的事实。事实上,这是这类事情的标准习语。和往常一样:确保你正在测试你的缓冲区长度并使用 snprintf 如果这是处理不受信任数据的任何东西!
【解决方案3】:
char *me="Foo";
char *you="Bar";
char us[100];

char* out = us;
out += sprintf(out,"You: %s\n",you);
out += sprintf(out,"Me: %s\n",me);
out += sprintf(out,"We are %s and %s!\n",me,you);
printf("%s", us);

【讨论】:

  • 请不要printf(us)printf("%s", us)fputs(us, stdout)更安全。
  • 与问题无关, sprintf() 也是邪恶的。已更新,谢谢。
  • sprintf 只要您对缓冲区的大小有信心就可以了。另一方面,printf(us) 花费额外的工作来扫描%,即使它是安全的并且不应该存在。
【解决方案4】:

你可以使用这样的东西:

sprintf(us, "You: %s\nMe: %s\nWe are %s and %s!\n", you, me, me, you);

【讨论】:

  • 或者对于 SUS 兼容的系统:sprintf(us, "You: %1$s\nMe: %2$s\nWe are %2$s and %1$s!\n", you, me);
【解决方案5】:

永远不要使用非常量字符串作为printf 的第一个参数(或fprintf 的第二个参数。这是不好的做法。尝试将me 变量更改为"Muahaha %n%d%n%d%n%d%n%d%n" 并与您的堆栈说再见,然后向 SEGFAULT 打个招呼。printf 将尝试格式化字符串,但您没有提供任何参数供它处理,即使字符串中有格式说明符 printf 也不知道您没有t 给它任何论据。

如果要输出“预格式化”字符串,请使用fputs(str,stdout)。将printf 与非常量格式字符串一起使用的情况很少。

【讨论】:

  • @hhafez,不,dreamlax 是说使用文字以外的字符串是危险的,因为它可能包含您尚未传递参数的格式说明符,从而调用未定义的行为。在处理用户输入时这是一个更大的问题,因为它会使您受到攻击(永远不要在用户输入上调用 printf(str)),而且如果您的程序生成错误的格式字符串也是一个问题。
  • @hhafez: printf 用于打印格式化字符串基于格式描述字符串和提供的参数。当您提供预格式化的字符串且没有参数时,您没有正确使用printf。如果要逐字输出字符串,请使用专用于该目的的函数,例如fputs。如果您使用printf 输出非常量的预格式化字符串,则您冒着告诉printf 再次格式化部分字符串的风险。恶意用户可以提供格式说明符作为输入(例如%n%d),您的应用程序肯定会崩溃。
猜你喜欢
  • 2013-03-24
  • 2015-04-04
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多