LoginSignup
3
3

More than 5 years have passed since last update.

より安全なstoi(文字列を数値に変換する関数)

Last updated at Posted at 2014-11-28

std::stoiでは余分の文字が入ってる場合でも変換できます、例えばstd::stoi("123x1")は123を返します。
ここでより安全なstoiを作ってみました。

ソースコード

template <class T>
inline void stoi_s(const std::string& str, T& result, int base = 10) {
    char* end = nullptr;
    errno = 0;
    long long i = ::strtoll(str.c_str(), &end, base);
    if (end != (str.c_str() + str.size()) || str.size() <= 0 || errno != 0) {
        throw std::invalid_argument("stoi_s");
    }
    if (i < 0 && !std::numeric_limits<T>::is_signed) {
        // if T is unsigned, i will convert to unsigned before compare to result_test
        // make sure i is not negative here
        throw std::out_of_range("stoi_s");
    }
    T result_test = static_cast<T>(i);
    if (result_test != i) {
        throw std::out_of_range("stoi_s");
    }
    result = result_test;
}

テスト

template <class TException, class TFunction>
bool exception_catched(TFunction function) {
    try {
        function();
    } catch(TException&) {
        return true;
    }
    return false;
}

void test() {
    uint8_t a = 0;
    int32_t b = 0;
    uint64_t c = 0;

    stoi_s("100", a);
    assert(a == 100);
    stoi_s("-100", b);
    assert(b == -100);
    stoi_s("-0x80000000", b, 16);
    assert(b == -0x80000000);
    assert(exception_catched<std::invalid_argument>([&] { stoi_s("asd", a); }));
    assert(exception_catched<std::invalid_argument>([&] { stoi_s("1asd", a); })); 
    assert(exception_catched<std::out_of_range>([&] { stoi_s("-1", a); })); 
    assert(exception_catched<std::out_of_range>([&] { stoi_s("300", a); })); 
    assert(exception_catched<std::out_of_range>([&] { stoi_s("-0x80000001", b, 16); }));
    assert(exception_catched<std::out_of_range>([&] { stoi_s("-1", c); }));
    assert(exception_catched<std::invalid_argument>([&] {
        stoi_s("0x8000000000000000", c, 16);
    }));
}

manページ
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/strtoll.3.html

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3