2016-11-28 7 views
0

floatをconst char *に変換するC++関数を記述したい。この関数では、出力値が表すべき小数点以下の桁数を指定する引数が渡されます。私はこの機能を思いついたし、うまく機能する。小数点以下の浮動小数点数を設定する

私はこの機能を書いた方がいいですか?

static const char* getString(float value, int decimalPlaces) 
{ 
    char strValue[sizeof value]; 
    sprintf(strValue, "%.%df", value, decimalPlaces); 
    return strValue; 
} 
+0

'sizeof value'は' float'を表すのに使われるバイト数です。これは 'sprintf'では不十分かもしれません。ローカル配列へのポインタを返します。ローカル配列は、使用前に終了します。 – aschepler

答えて

6

あなたの機能を持つ2つの大きな問題があります使用しないことをお勧めします。

まず、floatのサイズは、ほとんどのプラットフォームの4バイトにあります。これは、配列が4つの要素であることを意味します。浮動小数点値のすべての桁で十分ではありません。範囲外を書き込むと、の定義されていない動作になります。

2番目の問題は、ローカル変数へのポインタを返すことです。配列strValueは、関数が戻ったときに有効範囲外になり、ポインタは現在という迷惑ポインタとなります。これを省略すると、未定義の動作にもつながります。

つまり、あなたの機能はではありません。は「うまく動作します」。それは実際には全く機能しません。

明白な解決策は、std::stringstd::to_stringを使用して浮動小数点値を文字列に変換することです。そして、何らかの理由でCスタイルのヌル終了文字列が必要なときは、文字列c_str()を使用してそのようなポインタを取得します。

小数点以下の桁数が必要な場合は、std::ostringstreamと標準I/O manipulatorsを使用して文字列の書式を設定します。あなたの目標が出力する文字列を取得する場合は、もちろん、この手順をスキップして、出力を書き込むときにマニピュレータを直接使用することができます。

+0

ありがとうございました。ここで私が望むのはconst char *を返すことです。 c_str()を使用すると、それを実現できます。だから、このアプローチを使用する場合は、最初にstd :: stringに変換してからconst char *に変換するなどの不必要なステップがあるとは思わないでください。 –

2

return strValue;を使用すると、ローカル変数へのポインタを返すことになります。つまり、関数が終了するとその変数がなくなり、現在は何もないポインタがあります。そのポインタを使用することは未定義の動作です。

は、次のいずれかのバッファを割り当てる new[]を使用する必要があるとしていると、あなたは delete[]に呼び出しサイト内のポインタを覚えているか std::stringのようなものを使用して文字列自体は、メモリ管理を扱うようにする必要があります。

個人的に私は次のようにstd::stringstd::stringstreamを使用します。あなたはgetMStringを残して、あなたが削除されたデータへのポインタを返したらchar strValue[]が削除されているので、あなたの関数に問題があり

static std::string getMString(float value, int decimalPlaces) 
{ 
    std::stringstream stream; 
    stream << std::fixed << std::setprecision(decimalPlaces) << value; 
    return stream.str(); 
} 
+0

ありがとうございました。ここで私が望むのはconst char *を返すことです。 c_str()を使用すると、それを実現できます。だから、このアプローチを使用する場合は、最初にstd :: stringに変換してからconst char *に変換するなどの不必要なステップがあるとは思わないでください。 –

+1

@TharinduKumaraポインタを返すには、 'new []'と 'delete []'が必要です。個人的には文字列を返し、 'const char *'が必要な場合は、コールサイトで返された文字列の 'c_str()'メソッドを使用できます。 – NathanOliver

2

、これはUBです。

は、私が何かを発明するが、C++ 11 std::to_string(float)

+0

配列は**削除**されていません( 'delete'への呼び出しはありません)。それは単に消える。 –

+0

だからこそ、彼らは地元の目的地の終わりを言います。実装定義、何時にそのメモリ内のデータに何が起こるか – Swift

関連する問題