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

由于这个问题每周都会被问到,这个 常见问题可能会帮助很多用户。

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

  • 如何在 C + + 中将一个字符串转换成一个整数

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

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

166546 次浏览

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

  1. 不要使用 itoaitof函数,因为它们是非标准的,因此不可移植。
  2. 使用字符串流

     #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一样根据需要格式化字符串

    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混淆,后者是不可取的

  3. 使用 增强词法强制转换。如果您不熟悉 ost,那么从一个像 lexical _ cast 这样的小型库开始是一个不错的主意。下载并安装升级及其文档 到这儿来。尽管升级不在 C + + 标准中,但许多升级库最终都得到了标准化,升级被广泛认为是最好的 C + + 库。

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

    #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"
    }
    

How to convert a string to a number in C++03

  1. The most lightweight option, inherited from C, is the functions atoi (for integers (alphabetical to integer)) and atof (for floating-point values (alphabetical to float)). These functions take a C-style string as an argument (const char *) and therefore their usage may be considered a not exactly good C++ practice. cplusplus.com has easy-to-understand documentation on both atoi and atof including how they behave in case of bad input. However the link contains an error in that according to the standard if the input number is too large to fit in the target type, the behavior is undefined.

    #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*
    }
    
  2. Use string streams (this time input string stream, istringstream). Again, istringstream is used just like cin. Again, do not confuse istringstream with istrstream. The latter is deprecated.

    #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
    }
    
  3. Use boost lexical cast.

    #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类型的异常

我从 StackOverflow 的某个地方偷了这个方便的类来将任何可以流化的东西转换成字符串:

// 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_;
};

然后你把它当作

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

很漂亮!

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

// 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;
}

用途:

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

您可能还需要 wstring 的版本。

C + + 11的更新

C++11标准中,字符串到数字的转换和反之亦然都内置在标准库中。以下所有函数都在 <string>中出现(按照第21.5段)。

字符串到数字

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=10z=35)。您可以在这里找到有关 浮点数浮点数浮点数有符号整数无符号整数的确切格式的更多信息。

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

从数字到字符串

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 stringsream 选项并使用流操作器,正如这里的另一个答案所解释的那样。

正如注释中指出的那样,这些函数退回到默认的尾数精度,这可能不是最大精度。如果您的应用程序需要更高的精度,那么最好回到其他字符串格式化过程。

还有一些类似的定义为 to_wstring的函数,这些函数将返回一个 std::wstring

在 C + + 17中,在头 Charconv中引入了新的函数 To _ charsFrom _ chars

To _ chars 与区域设置无关,不分配, 而且不能扔。

使用的格式化策略的一小部分 提供了其他库(例如 std: : sprintf)。

To _ charsFrom _ chars也一样。

保证 std: : from _ chars 可以恢复 格式化的每个浮点值 By to _ chars 只有在以下两种情况下才提供 函数来自同一个实现

 // 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\n", output);
std::exit(ret);
}
void check(const std::errc &ec) noexcept
{
if (ec ==  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);
}

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

#include <iostream>
#include <string.h>
using namespace std;
int main() {
string s="000101";
cout<<s<<"\n";
int a = stoi(s);
cout<<a<<"\n";
s=to_string(a);
s+='1';
cout<<s;
return 0;
}

产出:

  • 000101
  • 101
  • 1011