简体   繁体   English

从C ++ StringStream OStringStream获取Char *数组

[英]Getting char* array from c++ stringstream ostringstream

I am trying to copy ostringstream to a char* array and am hoping someone can help me with understanding where my mistake lies. 我正在尝试将ostringstream复制到char *数组,并希望有人可以帮助我理解我的错误所在。 I looked on the forum, found some things that are similar and unfortunately am still am unable to get property copy from ostringstream to char*. 我在论坛上查看了一下,发现有些类似的地方,但是仍然无法将属性副本从ostringstream复制到char *。 In short I am trying to copy into the char* via: 简而言之,我试图通过以下方式复制到char *中:

ostringstream bld
bld<<"test"<<"is"<<"good"
const char * result = bld.str().c_str();

The complete code to reproduce an error is below. 下面是重现错误的完整代码。 In this code I am having two functions that essentially build strings via ostringstream. 在这段代码中,我有两个基本上通过ostringstream构建字符串的函数。 In the makeFilePath( ) function I build a complete file path (ie /path/file.txt ). makeFilePath( )函数中,我建立了完整的文件路径(即/path/file.txt )。 In the add() function, I simply add two more char* arrays to an argument to get prefix /path/file.txt suffix . add()函数中,我仅向参数添加两个char *数组即可获得前缀/path/file.txt后缀

The problem is for some unknown reason to me the fullFilePath also changes to look like prefix /path/file.txt suffix . 问题是由于某种未知原因, fullFilePath也会更改为前缀/path/file.txt后缀 Last three lines of a code will exhibit that. 代码的最后三行将显示该内容。

I spent hours on this, thinking maybe this is a referencing issue or something else. 我花了数小时在此上,认为这可能是参考问题或其他问题。 However, none that I attemped worked. 但是,我没有尝试过。 Any ideas how to get over this problem? 任何想法如何解决这个问题?

Thanks!! 谢谢!!

#include <iostream>
#include <sstream>
#include <string>

using std::cout;
using std::endl;
using std::string;

using std::ostringstream;

const char* add(const char *fileName) {
    ostringstream bld;
    const char *prefix = "prefix";
    const char *suffix = "suffix";
    bld << prefix << " " << fileName << " " << suffix;
    string temp = bld.str();
    cout << "in add(): \n\t" << temp << endl;
    return temp.c_str();
}

const char * makeFilePath(const char *path, const char *name, const char *ext =
        ".txt") {
    ostringstream bld;
    bld << path << name << ext;
    cout << "makeFilePath(), returning: \n\t" << bld.str()<< endl;
    string temp = bld.str();
    return temp.c_str();

}

int main(int argc, char **argv) {
    cout << "=== PROJECT START ===" << endl;

    const char * filePath = "\\Path\\";
    const char *fileName = "FILENAME";
    const char *fullFilePath = makeFilePath(filePath, fileName);

    cout << fullFilePath before calling add():\n\t" << fullFilePath << endl;    
    const char* str = add(fullFilePath);
    cout << fullFilePath after calling add():\n\t" << fullFilePath << endl;

    return 1;
}

stringstream.str() returns a expiring value a temporary string object whose lifetime is restricted to the end of the expression. stringstream.str()返回一个临时字符串对象的到期值,该对象的生命周期仅限于表达式的末尾。 A pointer to a temporary expiring value when deleted would simply dangle and accessing it beyond the expression is an Undefined behaviour possibly a crash or some garbage value. 指向临时过期值的指针在删除后将只是悬垂,并且在表达式之外访问它是未定义的行为,可能是崩溃或某些垃圾值。

One option would be to fetch the string object to a persistent string and then get the constant pointer to the character array buffer. 一种选择是将字符串对象获取为持久字符串,然后获取指向字符数组缓冲区的常量指针。

const std::string bld= stringstream.str();
const char* result= bld.c_str();

Alternatively you may also consider to bind the expiring rvalue to a constant reference (Note some compilers might be lenient to bind to a reference which is possibly incorrect) and then fetch the pointer to the buffer. 或者,您也可以考虑将到期的右值绑定到一个常量引用(请注意,某些编译器可能会宽容地绑定到可能不正确的引用),然后获取指向缓​​冲区的指针。 This will simply extend the lifetime of the temporary object. 这将仅延长临时对象的寿命。

But that would not resolve all you pain. 但这并不能解决您的所有痛苦。 As I have missed your function implementation 因为我错过了您的功能实现

const char * makeFilePath(const char *path, const char *name, const char *ext =
        ".txt") {
    ostringstream bld;
    bld << path << name << ext;
    cout << "makeFilePath(), returning: \n\t" << bld.str()<< endl;
    string temp = bld.str();
    return temp.c_str();

}

You are returning a pointer to a local object the scope of which is not extended beyond the function scope. 您正在返回一个指向本地对象的指针,该对象的范围未超出功能范围。 A better suggestion would be to return a string object from your function and then on the caller scope convert the string object to a const C null terminated string. 更好的建议是从函数中返回一个字符串对象,然后在调用者作用域上将字符串对象转换为const C null终止的字符串。

std::string makeFilePath(const char *path, const char *name, const char *ext =
        ".txt") {
    ostringstream bld;
    bld << path << name << ext;
    cout << "makeFilePath(), returning: \n\t" << bld.str()<< endl;
    return bld.str();

}

Alternatively you may want to duplicate the string using strdup, but the caller should be aware to release the resource for the allocated buffer. 另外,您可能希望使用strdup复制字符串,但是调用者应注意释放分配的缓冲区的资源。

The short answer is you need to use something like strdup to fix this: 简短的答案是,您需要使用诸如strdup东西来解决此问题:

const char* makeFilePath(const char *path, const char *name, const char *ext = ".txt")
{
  ostringstream bld;
  bld << path << name << ext;
  cout << "makeFilePath(), returning: \n\t" << bld.str()<< endl;

  return strdup(bld.str().c_str());
}

This is a really sub-optimal solution as now you have a memory leak unless you properly free the result of this function, plus it might return NULL on occasion which could cause chaos if you don't test for it. 这是一个真正次优的解决方案,因为除非您正确free此函数的结果,否则现在您会发生内存泄漏,而且如果不进行测试,它有时可能会返回NULL ,这可能会导致混乱。 It'd be much better to return std::string . 返回std::string会更好。

If you're using C++, use C++. 如果您使用的是C ++,请使用C ++。

Just don't use char * . 只是不要使用char * If you're writing C++, you should use C++ strings, not C strings. 如果您正在编写C ++,则应使用C ++字符串,而不是C字符串。

C doesn't have anything to copy strings for you, (except maybe sprintf with the NULL-target GNU extension?), so you are often going to be left with invalid pointers. C没有任何东西可以为您复制字符串(可能是带有NULL目标的GNU扩展名的sprintf除外),因此您经常会留下无效的指针。

using std::ostringstream;
using std::string;

string add(const string fileName) {
    ostringstream bld;
    string prefix = "prefix";
    string suffix = "suffix";
    bld << prefix << " " << fileName << " " << suffix;
    string temp = bld.str();
    cout << "in add(): \n\t" << temp << endl;
    return temp;
}

string makeFilePath(string path, string name, string ext =
        ".txt") {
    ostringstream bld;
    bld << path << name << ext;
    cout << "makeFilePath(), returning: \n\t" << bld << endl;
    string temp = bld.str();
    return temp;

}

int main(int argc, char **argv) { // unfortunately, argv much be char**
    cout << "=== PROJECT START ===" << endl;

    string filePath = "\\Path\\";
    string fileName = "FILENAME";
    string fullFilePath = makeFilePath(filePath, fileName);

    cout << fullFilePath before calling add():\n\t" << fullFilePath << endl;    
    string str = add(fullFilePath);
    cout << fullFilePath after calling add():\n\t" << fullFilePath << endl;

    return 1;
}

There's a broader lesson here, in modern C++ you can delete almost all use of pointers (not just char pointers) 这里有更广泛的一课,在现代C ++中,您可以删除几乎所有使用指针的方式(而不仅仅是char指针)

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

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