-4

使用 sprintf 会输出一个额外的字符串,例如 "%x ...."

int main()
{   
    char *word_tmp = new char[0];
    char *word_all = new char[0];

    for(int i=0;i<5;i++)
    {
        sprintf(word_tmp, "\nNumber:%d, Good Good!", i);
        sprintf(word_all, "%s%s", word_all, word_tmp);   
    }

    std::cout<<word_all;
}

该程序工作正常,但输出一个我没有输出的字符串。

4

3 回答 3

3

您的数组长度为零,因此缓冲区word_tmp不足以容纳第一次调用的结果sprintf(),这会导致缓冲区溢出。因此,在这种情况下,您第一次调用的行为sprintf()是未定义的。

除此之外,如果由于调用sprintf()or而在重叠的对象之间发生复制snprintf(),则结果是 undefined

最后,您的函数正在泄漏内存,因为您没有调用delete[]分配给new[].

您应该使用std::ostringstream类型安全的方式来完成您想要实现的目标(感谢 James Kanze发现我之前尝试为您的程序生成最小修复的问题):

#include <iostream>
#include <sstream>

int main()
{
    std::ostringstream ss;
    for (int i = 0; i < 5; i++)
    {
        ss << "Number: " << i << ", Good Good!" << std::endl;
    }

    std::cout << ss.str();
}

这是一个活生生的例子

于 2013-03-31T11:00:34.900 回答
0

实际上,我对这段代码没有崩溃感到非常惊讶……您的 sprintf 目标字符串没有足够的空间来放置数据。而且我刚刚输入了 man sprintf 并阅读了以下内容:

C99  and  POSIX.1-2001 specify that the results are undefined if a call to sprintf(),
snprintf(), vsprintf(), or vsnprintf() would cause copying to take place between objects 
that overlap (e.g., if the target string array and one of the
supplied input arguments refer to the same buffer).

所以你的第二个 sprintf 在 c99 中是未定义的。

同样,您使用 C++ new 运算符并使用 sprintf 附加字符串并将数字插入字符串也很奇怪,而在 C++ 中,您有 std::string 和 stings 流以安全的方式执行此操作。

我认为您需要阅读一些书籍并了解 c 和 c++ 中发生了什么。

于 2013-03-31T11:08:20.443 回答
0

首先,你永远不想使用sprintf. 正确使用几乎是不可能的。在这种情况下,您将其值输出到不存在的内存中,因此您有未定义的行为。new char[0](您认为要分配多少内存?。在第二个sprintf中,您还从不存在的内存输入 - 更多未定义的行为,并且您从同一内存输出和输入(假设有是任何记忆),这也是未定义的行为。

忘记sprintf和数组新的:

std::string results;
for ( int i = 0; i != 5; ++ i ) {
    std::ostringstream s;
    s << "Number: " << i << " Good Good!\n";
    results += s.str();
}
std::cout << results;

(我认为这就是你想要做的。)

最后一点:虽然它几乎从来都不是真正的问题,但标准确实要求输出到文本流(如std::cout)的最后一个字符是'\n'.

于 2013-03-31T11:15:34.570 回答