簡體   English   中英

從C ++ StringStream OStringStream獲取Char *數組

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

我正在嘗試將ostringstream復制到char *數組,並希望有人可以幫助我理解我的錯誤所在。 我在論壇上查看了一下,發現有些類似的地方,但是仍然無法將屬性副本從ostringstream復制到char *。 簡而言之,我試圖通過以下方式復制到char *中:

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

下面是重現錯誤的完整代碼。 在這段代碼中,我有兩個基本上通過ostringstream構建字符串的函數。 makeFilePath( )函數中,我建立了完整的文件路徑(即/path/file.txt )。 add()函數中,我僅向參數添加兩個char *數組即可獲得前綴/path/file.txt后綴

問題是由於某種未知原因, fullFilePath也會更改為前綴/path/file.txt后綴 代碼的最后三行將顯示該內容。

我花了數小時在此上,認為這可能是參考問題或其他問題。 但是,我沒有嘗試過。 任何想法如何解決這個問題?

謝謝!!

#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()返回一個臨時字符串對象的到期值,該對象的生命周期僅限於表達式的末尾。 指向臨時過期值的指針在刪除后將只是懸垂,並且在表達式之外訪問它是未定義的行為,可能是崩潰或某些垃圾值。

一種選擇是將字符串對象獲取為持久字符串,然后獲取指向字符數組緩沖區的常量指針。

const std::string bld= stringstream.str();
const char* result= bld.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();

}

您正在返回一個指向本地對象的指針,該對象的范圍未超出功能范圍。 更好的建議是從函數中返回一個字符串對象,然后在調用者作用域上將字符串對象轉換為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();

}

另外,您可能希望使用strdup復制字符串,但是調用者應注意釋放分配的緩沖區的資源。

簡短的答案是,您需要使用諸如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());
}

這是一個真正次優的解決方案,因為除非您正確free此函數的結果,否則現在您會發生內存泄漏,而且如果不進行測試,它有時可能會返回NULL ,這可能會導致混亂。 返回std::string會更好。

如果您使用的是C ++,請使用C ++。

只是不要使用char * 如果您正在編寫C ++,則應使用C ++字符串,而不是C字符串。

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

這里有更廣泛的一課,在現代C ++中,您可以刪除幾乎所有使用指針的方式(而不僅僅是char指針)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM