2017-02-10 7 views
-1

関数からC文字列を返そうとしています。この関数は3つの整数をコンマで連結し、結果をchar配列として返しますが、ガベージ値が得られます。私はmallocを正しく呼び出さないと仮定しています。誰かが何が問題なのかアドバイスできますか?mallocを使用して関数からC文字列を返す方法

using namespace std; 

const char * createCommand(int p1, int p2, int p3){ 
    stringstream sstm; 
    std::string comma = ","; 
    sstm << p1 << comma << p2 << comma << p3; 
    std::string str = sstm.str(); 
    const char *cstr = (const char *)malloc((str.length()+1) * sizeof (char)); 

    cstr = str.c_str(); 
    return cstr;  
} 

int main() { 
    const char *cstr2 = createCommand(1,0,250); //I want to return "1,0,250" 
    printf("char = %s\n",cstr2); 
} 
+0

あなたはここでかなり漏れています。 –

+0

C文字列を返す特別な理由はありますか?非常に良い理由がない限り、C++でこのようなコードを書くことは間違いありません。 – Xirema

+0

C++では、メモリを動的に割り当てるために 'malloc'ではなく' new'を使うべきです。 – Barmar

答えて

2

リテラルの問題に対処するための回答にはすでに他の2つの回答がありますので、私はあなたの問題を引き起こしているかなり重大な設計上の欠陥、すなわちc-ストリングを返すことについてアドバイスします。

提供しているコード例では、c-stringの使用はまったく意味がありません。次のコードは、あなたが支障なくもしくは問題のあるコードをどうするつもり何を達成します:

std::string createCommand(int p1, int p2, int p3){ 
    std::stringstream sstm; 
    std::string comma = ","; 
    sstm << p1 << comma << p2 << comma << p3; 
    return sstm.str(); 
} 

int main() { 
    std::string command = createCommand(1,0,250); //I want to return "1,0,250" 
    std::cout << "char = " << command << "\n"; 
} 

あなたは、この設計はまだ良いです、代わりにC++のiostreamライブラリのprintfを使用に限定している場合でも:

std::string createCommand(int p1, int p2, int p3){ 
    std::stringstream sstm; 
    std::string comma = ","; 
    sstm << p1 << comma << p2 << comma << p3; 
    return sstm.str(); 
} 

int main() { 
    std::string command = createCommand(1,0,250); //I want to return "1,0,250" 
    printf("char = %s\n", command.c_str()); 
} 

古いCベースのライブラリに渡されるC文字列が必要な場合でも、この設計で十分です。つまり、mallocを使用する理由や、文字列自体を除いて基本となるC文字列表現とのインタフェースを使用する理由はありません。

+0

mallocを 'command.c_str()'のために扱う必要がない理由は、mainメソッドにあるからです。 – bakalolo

+0

いいえ、 'c_str()'は単に 'std :: string'が所有するメモリへのポインタを返すからです。 'std :: string'はそのメモリを解放します。 –

+1

@bakalolo mallocを扱う必要がない理由は、 'std :: string'オブジェクトが独自の動的メモリを管理するからです。あなた自身でそれをする理由はありません。 – Xirema

0

ポインタを返す前に、文字列をstrcpyの形式でコピーする必要があります。 std::string及びその他の目的のために正常に動作します

const char * createCommand(int p1, int p2, int p3){ 
    stringstream sstm; 
    std::string comma = ","; 
    sstm << p1 << comma << p2 << comma << p3; 
    std::string str = sstm.str(); 
    const char *cstr = (const char *)malloc((str.length()+1) * sizeof (char)); 

    strcpy(cstr, str.c_str()); 
    return cstr;  
} 
1

代入演算子は、ポインタの上書きを持つことはできません。したがって、割り当ては

cstr = str.c_str(); 

は、割り当てたメモリをリークし、文字列のデータでポインタを置き換えます。さらに、関数が現在返すポインタは、関数を終了すると無効にされるメモリを指し、リークに加えて未定義の動作を生成します。

この問題を解決するには、std::strcpy(cstr, str.c_str());に電話してください。呼び出し結果にstd::freeを呼び出すことを忘れないでください。 編集:createCommand関数(WhozCraig、コメントありがとう)の戻り値の型からconstを削除する必要があります。

注:私は、これはあなたがnew[]を使用することが好適であることを知っていること、そしてあなたが関数からstd::stringを返すことができる場合は、上記のいずれかを行う必要がないであろうと、mallocを使用しての唯一の運動であると仮定。

+0

私は前提をしません。 C + +プログラマは、C++が「クラスを持つC」に過ぎないと考えているか、同じデザイン原則が両方の言語に当てはまると考えるプログラマです。 – Xirema

+0

@ Xirema OPのプロフィールによれば、彼は以前のCの経験をたくさん持っているようには見えないので、私の最高の推測は、これは学習の練習であるということです。 – dasblinkenlight

+0

もう1つ注意してください:OPのコードは 'createCommand'を' const char * 'を返すものとして示していますが、' malloc'の結果を返すときは意味がありません。ポインタ。この答えの変更は、OPが必要とするものとまったく同じですが、呼び出しは 'char *'を返さなければなりません。呼び出し元が 'free()'を覚えておくことを推奨します。 – WhozCraig

関連する問題