如何在 C 中使用 sprintf 回推另一个字符串

How to use sprintf to pushback another string in C

提问人:yasara malshan 提问时间:1/2/2020 最后编辑:Sid Syasara malshan 更新时间:1/3/2020 访问量:299

问:

我需要将另外几个具有给定尾随模式的字符串推回/附加到 C 中的现有 char 数组中。 为了实现这一点,我愿意使用“sprintf”,如下所示。

#include <stdio.h>
#include<string.h>
int main()
{
    char my_str[1024]; // fixed length checked
    char *s1 = "abcd", *s2 = "pqrs";

    sprintf(my_str, "Hello World"); // begin part added
    sprintf(my_str, "%s , push back '%s' and '%s'.", my_str, s1, s2); // adding more to end of "my_str" (with given trailling format)
    /* here we always use 'my_str' as the first for the string format in sprintf - format starts with it */
    return 0;
}

当我遵循此方法时,我收到“内存重叠”警告。这是一个严重的问题吗?(如内存泄漏、错误输出等)

C 内存管理

评论

0赞 kaylum 1/2/2020
一种选择是改用 strcat
2赞 Barmar 1/2/2020
不能使用相同的字符串作为 中的输入和输出。sprintf()
2赞 kaylum 1/2/2020
另外,请注意,C 和 C++ 是不同的语言,只应使用相关的标签。很多时候,最好的答案是不同的,这取决于它是C还是C++。
3赞 Barmar 1/2/2020
@MawgsaysreinstateMonica String 文字会自动获得尾随 null,则无需显式放置。
3赞 David C. Rankin 1/2/2020
C11 标准 - 7.21.6.6 sprintf 函数"...如果复制发生在重叠的对象之间,则行为是未定义的。

答:

2赞 Barmar 1/2/2020 #1

之所以出现此警告,是因为不允许对输入参数的输出和其中一个输入参数使用相同的字符串。规范说:sprintf()

如果在重叠的对象之间进行复制,则行为是未定义的。

对输出使用新字符串。

#include <stdio.h>
#include<string.h>
int main()
{
    char my_str[1024], my_str2[1024]; // fixed length checked
    char *s1 = "abcd", *s2 = "pqrs";

    sprintf(my_str, "Hello World"); // begin part added
    sprintf(my_str2, "%s , push back '%s' and '%s'.", my_str, s1, s2); // adding more to end of "my_str" (with given trailling format)
    return 0;
}

评论

0赞 yasara malshan 1/2/2020
我的观点是,当格式字符串以“%s”开头时(例如:“%s<anything>”),似乎可以为输入和输出添加相同的字符串。(因为,在我添加“printf(”%s“, my_str);”后,我在“onlinegdb.com/online_c_compiler”中收到正确的输出“Hello World,push back 'abcd' and 'pqrs'.”
1赞 Barmar 1/3/2020
我从规范中添加了不允许的引用。仅仅因为它在您尝试时有效,并不意味着它通常没问题。
7赞 Sid S 1/2/2020 #2

调用时不允许对输入和输出使用相同的字符串sprintf()

因此,请替换以下内容:

sprintf(my_str, "%s , push back '%s' and '%s'.", my_str, s1, s2);

有了这个:

sprintf(my_str + strlen(my_str), " , push back '%s' and '%s'.", s1, s2);

评论

0赞 yasara malshan 1/2/2020
我的观点是,当格式字符串以“%s”开头时(例如:“%s<anything>”),似乎可以为输入和输出添加相同的字符串。(因为,在我添加“printf(”%s“, my_str);”后,我在“onlinegdb.com/online_c_compiler”中收到正确的输出“Hello World,push back 'abcd' and 'pqrs'.”)
1赞 Jonathan Leffler 1/2/2020
@yasaramalshan — 未定义行为的问题在于,它似乎可以按照您的预期工作(即使您的期望是没有根据的),但它随时可以以不同的方式工作,除了修复代码之外,您无能为力,因为您违反了对如何安全使用的限制。不要依赖目前在您的机器上碰巧起作用的未定义行为;它可能再也行不通了。sprintf()
1赞 Bob Shaffer 1/2/2020
此处显示的解决方案消除了重叠,应该没问题。但是,我建议使用 snprintf 并在添加字符串时跟踪字符串长度(snprintf 返回打印的字符数),以便您可以只使用 (buffer_size - total_printed) 之类的东西作为大小参数并避免缓冲区溢出。您还可以使用该值来避免不必要地调用 strlen()。