简体   繁体   English

C ++:为什么我不能用sprintf打印const char *?

[英]C++ : Why I can't print a const char* with sprintf?

What am I missing here ? 我在这里错过了什么? It's driving me nuts ! 这让我疯了!

I have a function that returns a const char* 我有一个返回const char *函数

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}

Now in another part of the code I am doing this : 现在在代码的另一部分我这样做:

.....
.....
char str[50];       
sprintf(str, "%s", Notation());
.....
.....

but str remains unchanged. 但是str保持不变。

If instead I do this : 如果相反,我这样做:

.....
.....
char str[50];
str[0]=0;
strcat(str, Notation());
.....
.....

str is correctly set. str正确设置。

I am wondering why sprintf doesn't work as expected... 我想知道为什么sprintf不能按预期工作......

You're trying to return an array allocated on stack and its behaviour is undefined. 您正在尝试返回在堆栈上分配的数组,并且其行为未定义。

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}

here s isn't going to be around after you've returned from the function Notation() . 这里s不会左右你从函数返回后Notation() If you aren't concerned with thread safety you could make s static. 如果你不与线程安全而言,你可以让s静态的。

const char* Notation() const
{
    static char s[10];
    ....

In both cases, it invokes undefined behavior, as Notation() returns a local array which gets destroyed on returning. 在这两种情况下,它都会调用未定义的行为,因为Notation()返回一个在返回时被销毁的本地数组。 You're unlucky that it works in one case, making you feel that it is correct. 不幸的是它在一个案例中起作用,让你觉得它是正确的。

The solution is to use std::string as: 解决方案是使用std::string作为:

std::string Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s; //it is okay now, s gets converted into std::string
}

Or using C++ stream as: 或者使用C ++流作为:

std::string Notation() const
{
    int x=5;
    std::ostringstream oss;
    oss << x;
    return oss.str(); 
}

and then: 然后:

char str[50];       
sprintf(str, "%s", Notation().c_str());

The benefit (and beauty) of std::ostringstream (and std::string ) is that you don't have to know the size of output in advance, which means you don't have to use magic number such as 10 in array declaration char s[10] . std::ostringstream (和std::string )的好处( std::ostringstream )是你不必事先知道输出的大小,这意味着你不必在数组中使用10等幻数声明char s[10] These classes are safe in that sense. 从这个意义上说,这些类是安全的。

char s[10] in Notation is placed on stack so it gets destroyed after exit from Notation function. Notation char s[10]放在堆栈上,因此在退出Notation函数后会被销毁。 Such variables are called automatic . 这些变量称为自动变量。 You need to save your string in heap using new : 您需要使用new将字符串保存在堆中:

char *s = new char[10];

But you have to free this memory manually: 但你必须手动释放这个记忆:

char str[50];
const char *nt = Notation();
sprintf(str, "%s", nt);
printf("%s", str);
delete[] nt;

If you really use C++ then use built-in string class like Nawaz suggested. 如果你真的使用C ++,那么使用像Nawaz建议的内置string类。 If you somehow restricted to raw pointers then allocate buffer outside Notation and pass it as destanation parameter like in sprintf or strcat . 如果以某种方式限制为原始指针,则在Notation外部分配缓冲区,并将其作为destanation参数传递,如sprintfstrcat

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM