如何在C ++中将数字转换为字符串,反之亦然

How to convert a number to string and vice versa in C++

因为这个问题每周都会被问到,所以这个常见问题解答可能会帮助很多用户。

  • 如何在C++中将整数转换为字符串

  • 如何将字符串转换成C++中的整数

  • 如何在C++中将浮点数转换为字符串

  • 如何在C++中将字符串转换为浮点数


C++ 11的更新

C++11标准开始,字符串到数字的转换(反之亦然)都内置在标准库中。以下所有功能均在中(根据第21.5段)。

字符串转换为数字

1
2
3
4
5
6
7
8
float              stof(const string& str, size_t *idx = 0);
double             stod(const string& str, size_t *idx = 0);
long double        stold(const string& str, size_t *idx = 0);
int                stoi(const string& str, size_t *idx = 0, int base = 10);
long               stol(const string& str, size_t *idx = 0, int base = 10);
unsigned long      stoul(const string& str, size_t *idx = 0, int base = 10);
long long          stoll(const string& str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);

其中每一个都以一个字符串作为输入,并尝试将其转换为数字。如果无法构造有效的数字,例如因为没有数字数据或数字超出类型的范围,则会引发异常(std::invalid_argumentstd::out_of_range)。

如果转换成功且idx不是0时,idx将包含未用于解码的第一个字符的索引。这可能是最后一个字符后面的索引。

最后,整数类型允许指定一个基数,对于大于9的数字,假定使用字母表(a=10,直到z=35)。您可以找到有关可以在此处解析的浮点数、有符号整数和无符号整数的确切格式的更多信息。

最后,对于每个函数,还有一个重载,它接受一个std::wstring作为第一个参数。

数字到字符串

1
2
3
4
5
6
7
8
9
string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);

更简单的方法是,传递适当的数字类型,然后返回一个字符串。对于格式化选项,您应该返回到C++ 03 StrugsRAME选项,并使用流操作器,如这里的另一个答案所解释的。

如注释中所述,这些函数返回到默认尾数精度,该精度可能不是最大精度。如果应用程序需要更高的精度,最好返回到其他字符串格式设置过程。

还定义了类似的函数,命名为to_wstring,这些函数将返回std::wstring


如何在C++ 03中将数字转换为字符串

  • 不要使用itoaitof功能,因为它们是非标准的,因此不可移植。
  • 使用字符串流

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     #include <sstream>  //include this to use string streams
     #include <string>

    int main()
    {    
        int number = 1234;

        std::ostringstream ostr; //output string stream
        ostr << number; //use the string stream just like cout,
        //except the stream prints not to stdout but to a string.

        std::string theNumberString = ostr.str(); //the str() function of the stream
        //returns the string.

        //now  theNumberString is"1234"  
    }

    注意,也可以使用字符串流将浮点数字转换为字符串,还可以根据需要格式化字符串,就像使用cout一样。

    1
    2
    3
    4
    5
    6
    std::ostringstream ostr;
    float f = 1.2;
    int i = 3;
    ostr << f <<" +" i <<" =" << f + i;  
    std::string s = ostr.str();
    //now s is"1.2 + 3 = 4.2"

    可以使用流操纵器,如std::endlstd::hex和函数std::setw()std::setprecision()等,使用字符串流的方式与cout完全相同。

    不要混淆std::ostringstreamstd::ostrstream。后者已被弃用

  • 使用增强词法。如果你不熟悉Boost,最好从这个词汇库开始。要下载并安装Boost及其文档,请访问此处。虽然Boost不是C++标准,但许多Boost库最终得到了标准化,Boost被广泛认为是最好的C++库。

    词法转换在下面使用流,所以基本上这个选项与前一个选项相同,只是不那么冗长。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <boost/lexical_cast.hpp>
    #include <string>

    int main()
    {
       float f = 1.2;
       int i = 42;
       std::string sf = boost::lexical_cast<std::string>(f); //sf is"1.2"
       std::string si = boost::lexical_cast<std::string>(i); //sf is"42"
    }
  • 如何将字符串转换成C++ 03中的数字

  • 继承自C的最轻量选项是函数atoi(对于整数(字母到整数))和atof(对于浮点值(字母到浮点))。这些函数以C样式字符串作为参数(EDCOX1,12),因此它们的用法可以被认为不是一个很好的C++实践。cplusplus.com很容易理解关于atoi和atof的文档,包括在输入错误的情况下它们的行为。但是,根据标准,链接中包含一个错误,如果输入的数字太大,不适合目标类型,则行为未定义。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <cstdlib> //the standard C library header
    #include <string>
    int main()
    {
        std::string si ="12";
        std::string sf ="1.2";
        int i = atoi(si.c_str()); //the c_str() function"converts"
        double f = atof(sf.c_str()); //std::string to const char*
    }
  • 使用字符串流(这次输入字符串流,istringstream)。同样,IStringstream的使用方式与cin相同。同样,不要把istringstreamistrstream混淆。后者已被弃用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <sstream>
    #include <string>
    int main()
    {
       std::string inputString ="1234 12.3 44";
       std::istringstream istr(inputString);
       int i1, i2;
       float f;
       istr >> i1 >> f >> i2;
       //i1 is 1234, f is 12.3, i2 is 44  
    }
  • 使用增强词法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <boost/lexical_cast.hpp>
    #include <string>

    int main()
    {
       std::string sf ="42.2";
       std::string si ="42";
       float f = boost::lexical_cast<float>(sf); //f is 42.2
       int i = boost::lexical_cast<int>(si);  //i is 42
    }

    如果输入错误,lexical_cast将抛出boost::bad_lexical_cast类型的异常。


  • STD:C++17中,新函数STD::To-CARS和STD::FROX-CHARS被引入到头查尔考夫中。

    std::to_chars is locale-independent, non-allocating,
    and non-throwing.

    Only a small subset of formatting policies used by
    other libraries (such as std::sprintf) is provided.

    从STD::to-CARS,与STD::Fux-CARS。

    The guarantee that std::from_chars can recover
    every floating-point value formatted
    by to_chars exactly is only provided if both
    functions are from the same implementation

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     // See en.cppreference.com for more information, including format control.
    #include <cstdio>
    #include <cstddef>
    #include <cstdlib>
    #include <cassert>
    #include <charconv>

    using Type =  /* Any fundamental type */ ;
    std::size_t buffer_size = /* ... */ ;

    [[noreturn]] void report_and_exit(int ret, const char *output) noexcept
    {
        std::printf("%s
    "
    , output);
        std::exit(ret);
    }
    void check(const std::errc &ec) noexcept
    {
        if (ec == &nbsp;std::errc::value_too_large)
            report_and_exit(1,"Failed");
    }
    int main() {
        char buffer[buffer_size];        
        Type val_to_be_converted, result_of_converted_back;

        auto result1 = std::to_chars(buffer, buffer + buffer_size,  val_to_be_converted);
        check(result1.ec);
        *result1.ptr = '\0';

        auto result2 = std::from_chars(buffer, result1.ptr, result_of_converted_back);
        check(result2.ec);

        assert(val_to_be_converted == result_of_converted_back);
        report_and_exit(0, buffer);
    }

    虽然编译器没有完全实现它,但它肯定会被实现。


    我从StackOverflow的某个地方偷了这个便利类,将任何可流式转换为字符串:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // make_string
    class make_string {
    public:
      template <typename T>
      make_string& operator<<( T const & val ) {
        buffer_ << val;
        return *this;
      }
      operator std::string() const {
        return buffer_.str();
      }
    private:
      std::ostringstream buffer_;
    };

    然后你用它作为;

    1
    string str = make_string() << 6 << 8 <<"hello";

    相当漂亮!

    另外,我使用这个函数将字符串转换成任何可流式的,尽管如果您试图解析一个不包含数字的字符串是不太安全的;(它也不像最后一个那么聪明)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // parse_string
    template <typename RETURN_TYPE, typename STRING_TYPE>
    RETURN_TYPE parse_string(const STRING_TYPE& str) {
      std::stringstream buf;
      buf << str;
      RETURN_TYPE val;
      buf >> val;
      return val;
    }

    用作:

    1
    int x = parse_string<int>("78");

    您可能还需要wstring的版本。