Sprintf输出一个额外的字符串

sprintf outputs an extra string

本文关键字:字符串 一个 输出 Sprintf      更新时间:2023-10-16

使用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;
}

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

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

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

最后,你的函数正在泄漏内存,因为你没有调用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();
}

我真的很惊讶这段代码没有崩溃…您的sprint目标字符串没有足够的空间来放置数据。我还输入了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).

所以你的第二个sprint在c99中没有定义。

还有一点很奇怪,你使用c++的new操作符和sprintf来附加字符串和插入数字到string中,而在c++中你有std::string和string流可以安全地完成这些操作。

我认为你需要读一些书,了解c和c++是怎么回事

首先,永远不要使用sprintf。几乎是不可能的正确使用。在本例中,您将它的值输出到不存在的内存,所以你有未定义的行为。(你认为new char[0]会占用多少内存分配?。在第二个sprintf中,您也从不存在的内存—更多未定义行为,以及你从同一个记忆中输出和输入(假设)有任何记忆),这也是未定义行为。

忘掉sprintf和array new:

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'

相关文章: