3
using namespace std;
int main(int argc, char *argv[]) {
    char c[] = {'0','.','5'};
    //char c[] = "0.5";
    float f = atof(c);
    cout << f*10;
    if(c[3] != '\0')
    {
        cout << "YES";
    }
}

出力:5YES

atof は null で終了しない文字配列でも機能しますか? もしそうなら、どこで停止するかをどうやって知るのですか?

4

8 に答える 8

5

atof は null で終了しない文字配列でも機能しますか?

いいえ、そうではありませんstd::atof入力に ​​null で終わる文字列が必要です。この前提条件を満たさないことはUndefined Behaviorです。

未定義の動作とは、プログラムが正常に動作しているように見えることを含め、何かが起こる可能性があることを意味します。ここで起こっているのは、配列の最後の要素の直後にメモリ内にバイトがあり、浮動小数点数の表現の一部として解釈できないため、実装がstd::atof停止することです。しかし、それは頼りにできないものです。

次のようにプログラムを修正する必要があります。

char c[] = {'0', '.', '5', '\0'};
//                         ^^^^
于 2013-03-22T12:21:12.670 に答える
2

いいえ、atofnull 以外で終了する配列では機能しません。渡した配列の末尾の後にゼロが検出されると停止します。終端なしで配列を渡すと、関数が配列の末尾を超えて読み取るようになるため、未定義の動作になります。配列。あなたの例では、関数は割り当てられたバイトにアクセスした可能性があります(ただし、メモリ内で追跡する必要がないfため、確実ではありません)。fc[]

char c[] = {'0','.','5'};
char d[] = {'6','7','8'};
float f = atof(c); // << Undefined behavior!!!
float g = atof(d); // << Undefined behavior!!!
cout << f*10;

上記の出力 5.678は、配列の末尾を超えて読み取りが行われたという事実を指摘しています。

于 2013-03-22T12:21:38.240 に答える
1

いいえ... atof() にはヌルで終了する文字列が必要です。

null で終了していない変換する必要がある文字列がある場合は、有効な数字である各文字の値に基づいて、それをターゲット バッファーにコピーしてみてください。効果のあるもの...

char buff[64] = { 0 };

for( int i = 0; i < sizeof( buff )-1; i++ )
{
    char input = input_string[i];

    if( isdigit( input ) || input == '-' || input == '.' )
        buff[i] = input;
    else
        break;
}

double result = atof( buff );
于 2013-03-22T12:26:21.067 に答える
0

std::string はすでに NULL で文字列を終了しています!

では、なぜでしょうか

std::string number = "7.6";
double temp = ::atof(number.c_str());

stringstream または boost::lexical_cast でも実行できます

http://www.boost.org/doc/libs/1_53_0/doc/html/boost_lexical_cast.html http://www.cplusplus.com/reference/sstream/stringstream/

于 2013-03-22T12:47:18.627 に答える
0

atof()MSDNの関数の説明から(おそらく他のコンパイラに適用されます):

関数は、数値の一部として認識できない最初の文字で入力文字列の読み取りを停止します。この文字は、文字列を終了するヌル文字 ('\0' または L'\0') の場合があります。

于 2013-03-22T12:21:35.253 に答える
0

0 で終了するか、テキストに番号に属さない文字が含まれている必要があります。

于 2013-03-22T12:22:36.133 に答える
0

C++11 以降、std::stof. に置き換えることatofstd::stof扱いやすくなります。

既知のサイズの char 配列を常に渡す場合に便利なラッパーを作成しました。

ライブデモ

#include <fmt/core.h>
#include <type_traits>
#include <iostream>

// SFINAE fallback  
template<typename T, typename =
    std::enable_if< std::is_pointer<T>::value >
>
float charArrayToFloat(const T arr){  // Fall back for user friendly compiler errors
    static_assert(false == std::is_pointer<T>::value, "`charArrayToFloat()` dosen't allow conversion from pointer!");
    return -1;
}

// Valid for both null or non-null-terminated char array
template<size_t sz>
float charArrayToFloat(const char(&arr)[sz]){
    // It doesn't matter whether it's null terminated or not
    std::string str(arr, sz);
    return std::stof(str);
}


int main() {
    char number[4] = {'0','.','4','2'};
    float ret = charArrayToFloat(number);
    fmt::print("The answer is {}. ", ret);
    return 0;
}

出力:The answer is 0.42.

于 2022-03-01T09:57:42.080 に答える