由于这个问题每周都会被问到,这个FAQ可能会帮助很多用户。
如何在C++中将整数转换为字符串
如何在C++中将字符串转换为整数
如何在C++中将浮点数转换为字符串
如何在C++中将字符串转换为浮点数
从 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_argument
或 std::out_of_range
)。
如果转换成功且 idx
不为 0
,那么 idx
将包含未用于解码的第一个字符的索引。这可能是最后一个字符后面的索引。
最后,整数类型允许指定基数,对于大于 9 的数字,假定使用字母表(a=10
直到 z=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中的stringstream选项并使用流操作符来进行操作,这在另一个答案中已经解释了。
正如评论中所指出的,这些函数会回退到默认尾数精度,可能不是最大精度。如果您的应用程序需要更高的精度,则最好返回其他字符串格式化过程。
还有类似于to_wstring
命名的函数,它们将返回一个std::wstring
。
std::to_string
对浮点数类型失去了很多精度。例如,double f = 23.4323897462387526; std::string f_str = std::to_string(f);
返回的字符串是23.432390。这使得使用这些函数回合浮点值变得不可能。 - fun4jimmy使用字符串流
#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::endl
、std::hex
和函数std::setw()
、std::setprecision()
等,与字符串流的使用方式完全相同,就像使用cout
一样。
不要混淆std::ostringstream
与std::ostrstream
。后者已被弃用。
使用boost lexical cast进行转换。如果您对boost不熟悉,建议从像这个lexical_cast这样的小库开始。要下载和安装boost及其文档,请点击此处。尽管boost不是C++标准的一部分,但许多boost库最终都会被标准化,并且boost被广泛认为是最好的C++库之一。
Lexical cast基本上是在使用流,因此这个选项与前一个选项基本相同,只是更简洁。
#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 的函数 atoi
(用于整数) 和 atof
(用于浮点数)。这些函数以 C 风格的字符串作为参数(const char *
),因此它们的使用可能被认为是不太好的 C++ 实践 。cplusplus.com 提供了易于理解的文档,包括有关 atoi 和 atof 在输入错误的情况下的行为。但是该链接中存在一个错误,根据标准,如果输入的数字过大而无法适应目标类型,则其行为未定义。
#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
。不要将istringstream
与已弃用的istrstream
混淆。#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
}
#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
的异常。
atoi
的cplusplus文档并不好,它是错误的。它没有提到如果字符串的数值不能在 int
中表示,则行为未定义。相反,它说超出范围的值被夹紧到 INT_MAX
/ INT_MIN
,但我在 C++03 或 C89 中找不到这样的规定。对于不受信任/未经验证的输入或处理流不支持的基数时,您需要使用 strtol
,它具有定义的错误行为。对于 atof
/ strtod
,类似的评论适用。 - Steve Jessop(int)strtol(nptr,(char **)NULL,10)
。atoi[...]函数返回转换后的值。” cplusplus.com被认为是初学者信息来源极差的网站。 - Johannes Schaub - litbstd::to_string
。 - Pubby // 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);
}
虽然编译器目前尚未完全实现,但它肯定会被实现。
我从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");
你可能也需要wstrings的版本。
string IntToStr(int n)
{
string res;
bool s=n<0;
n=abs(n);
do
res=char(n%10+48)+res;
while(n/=10);
return s ? "-"+res : res;
}
#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;
}
to_string
未定义)。请确保提供有用的答案。 - Massimo Costa