在 C++ 中从 int
转换为等效 string
的最简单方法是什么。我知道两种方法。有没有更简单的方法?
(1)
int a = 10;
char *intStr = itoa(a);
string str = string(intStr);
(2)
int a = 10;
stringstream ss;
ss << a;
string str = ss.str();
itoa()
采用三个参数。
C++11 引入了 std::stoi
(以及每种数字类型的变体)和 std::to_string
,它们是 C atoi
和 itoa
的对应物,但用 std::string
表示。
#include <string>
std::string s = std::to_string(42);
因此是我能想到的最短的方法。您甚至可以省略类型的命名,使用 auto
关键字:
auto s = std::to_string(42);
注意:参见 [string.conversions](21.5 in n3242)
C++20 更新: std::format 现在是惯用的方式。
C++17 更新:
几年后与@v.oddou 进行了讨论,C++17 终于提供了一种方法来执行最初基于宏的类型不可知解决方案(保留在下面),而无需经历宏的丑陋。
// variadic template
template < typename... Args >
std::string sstr( Args &&... args )
{
std::ostringstream sstr;
// fold expression
( sstr << std::dec << ... << args );
return sstr.str();
}
用法:
int i = 42;
std::string s = sstr( "i is: ", i );
puts( sstr( i ).c_str() );
Foo x( 42 );
throw std::runtime_error( sstr( "Foo is '", x, "', i is ", i ) );
原始(C++ 98)答案:
由于“将 ... 转换为字符串”是一个反复出现的问题,因此我总是在 C++ 源代码的中心标头中定义 SSTR() 宏:
#include <sstream>
#define SSTR( x ) static_cast< std::ostringstream & >( \
( std::ostringstream() << std::dec << x ) ).str()
使用尽可能简单:
int i = 42;
std::string s = SSTR( "i is: " << i );
puts( SSTR( i ).c_str() );
Foo x( 42 );
throw std::runtime_error( SSTR( "Foo is '" << x << "', i is " << i ) );
以上是C++98兼容的(如果你不能使用C++11std::to_string
),并且不需要任何第三方包含(如果你不能使用Boostlexical_cast<>
);不过,这两种其他解决方案都有更好的性能。
dynamic_cast
不是很熟悉,但我正在使用 clang 进行编译,所以它会抱怨它。如果我只是省略 dynamic_cast
那么它编译得很好;在这种情况下,dynamic_cast
的用途是什么?我们已经创建了一个 ostringstream
,那么为什么要转换它呢?
ostringstream
时,我们在其上调用了 operator<<()
,它返回 ostream &
——没有定义 .str()
。我真的很想知道在没有演员阵容的情况下 clang 将如何使这项工作(或者为什么它会产生错误)。这个结构在很多地方都发布过,而且我已经在许多不同的编译器上使用它十多年了,包括 MSVC、GCC 和 XLC,所以我很惊讶 clang 对它犹豫不决。
do { } while( 0 )
不会添加任何内容。有了 2. 和 3. 你可能明白了——这可以通过静态转换来完成,也许你们中的一个模板向导可以提出一个“更好”的界面。但正如我所说,这绝不是我自己的发明。环顾四周,这个宏(宏!)是相当普遍的。这就是 POLA 本身的一个例子。我可能会玩弄它以使其更加“流线型”。
当前的 C++
从 C++11 开始,有一个为整数类型重载的 std::to_string
函数,因此您可以使用如下代码:
int a = 20;
std::string s = std::to_string(a);
// or: auto s = std::to_string(a);
标准将这些定义为等效于使用 sprintf
进行转换(使用与提供的对象类型匹配的转换说明符,例如 %d
用于 int
)到足够大小的缓冲区,然后创建一个 { 4} 该缓冲区的内容。
旧 C++
对于较旧的(C++11 之前的)编译器,可能最常见的简单方法基本上是将您的第二选择包装到通常名为 lexical_cast
的模板中,例如 Boost 中的那个,因此您的代码如下所示:
int a = 10;
string s = lexical_cast<string>(a);
其中一个优点是它也支持其他类型的转换(例如,在相反的方向上也同样有效)。
另请注意,尽管 Boost lexical_cast
开始时只是写入 stringstream
,然后从流中提取回来,但它现在有一些添加。首先,添加了许多类型的特化,因此对于许多常见类型,它比使用 stringstream
快得多。其次,它现在检查结果,因此(例如)如果您从字符串转换为 int
,如果字符串包含无法转换为 int
的内容(例如,{ 6} 会成功,但 123abc
会抛出)。
我通常使用以下方法:
#include <sstream>
template <typename T>
std::string NumberToString ( T Number )
{
std::ostringstream ss;
ss << Number;
return ss.str();
}
详见here。
clear()
新创建的 ostringstream
对象。 clear()
重置错误/eof 标志,并且尚未生成任何错误/eof 条件。
NumberToString(23213.123)
产生 23213.1
而 std::to_string(23213.123)
产生 23213.123000
那里发生了什么?
.flags(...)
阅读 &清除格式标志,.str("")
清除现有字符串。
您可以将 C++11 中的 std::to_string
用作 suggested by Matthieu M.:
std::to_string(42);
或者,如果性能至关重要(例如,如果您进行大量转换),您可以使用 {fmt} 库中的 fmt::format_int
将整数转换为 std::string
:
fmt::format_int(42).str();
或 C 字符串:
fmt::format_int f(42);
f.c_str();
后者不进行任何动态内存分配,并且在 Boost Karma 基准测试中比 std::to_string
的 libstdc++ 实现快 70% 以上。有关详细信息,请参阅 Converting a hundred million integers to strings per second。
免责声明:我是 {fmt} 库的作者。
c_str()
返回一个指向在 fmt::FormatInt
类中声明的缓冲区的指针——所以返回的指针在分号处无效 -- 另请参阅 stackoverflow.com/questions/4214153/lifetime-of-temporaries
std::string::c_str()
的行为相同(因此命名)。如果你想在完整的表达式之外使用它构造一个对象 FormatInt f(42);
那么你可以使用 f.c_str()
而没有它被破坏的危险。
如果您安装了 Boost(您应该安装):
#include <boost/lexical_cast.hpp>
int num = 4;
std::string str = boost::lexical_cast<std::string>(num);
使用字符串流会更容易:
#include <sstream>
int x = 42; // The integer
string str; // The string
ostringstream temp; // 'temp' as in temporary
temp << x;
str = temp.str(); // str is 'temp' as string
或者做一个函数:
#include <sstream>
string IntToString(int a)
{
ostringstream temp;
temp << a;
return temp.str();
}
不是我所知道的,在纯 C++ 中。但是对你提到的内容稍作修改
string s = string(itoa(a));
应该可以工作,而且很短。
itoa()
不是标准函数!
sprintf()
非常适合格式转换。然后,您可以将生成的 C 字符串分配给 C++ 字符串,就像在 1 中所做的那样。
NULL
和零大小调用它以获得必要的缓冲区大小。
snprintf
(注意 SNP 前缀)和 sprintf
(注意 SP 前缀)。您将大小传递给前者,它注意不要溢出,但是后者不知道缓冲区的大小,因此可能会溢出。
snprintf
变体,然后再调用 sprintf
变体。由于此时缓冲区大小已知,调用 sprintf
变得完全安全。
首先包括:
#include <string>
#include <sstream>
其次添加方法:
template <typename T>
string NumberToString(T pNumber)
{
ostringstream oOStrStream;
oOStrStream << pNumber;
return oOStrStream.str();
}
使用这样的方法:
NumberToString(69);
或者
int x = 69;
string vStr = NumberToString(x) + " Hello word!."
使用 stringstream 进行数字转换是危险的!
请参阅 http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/,它告诉 operator<<
插入格式化输出。
根据您当前的语言环境,大于 3 位的整数可以转换为 4 位字符串,添加额外的千位分隔符。
例如,int = 1000
可以转换为字符串 1.001
。这可能会使比较操作根本不起作用。
所以我强烈推荐使用 std::to_string
方式。它更容易,并且可以满足您的期望。
更新(见下面的评论):
C++17 提供 std::to_chars 作为更高性能的独立于语言环境的替代方案
std::to_string
也使用当前语言环境(请参阅 en.cppreference.com/w/cpp/string/basic_string/to_string 的“注释”部分)。几乎所有标准工具(从 stringstreams 到 sprintf
,还有 sscanf
等)都使用当前语言环境。我直到最近才意识到这一点,当时它给我带来了沉重的打击。目前用的是国产的,不难做。
在 C++11 中,我们可以使用“to_string()”函数将 int 转换为字符串
#include <iostream>
#include <string>
using namespace std;
int main()
{
int x=1612;
string s=to_string(x);
cout<<s<<endl;
return 0;
}
已编辑。如果您需要将具有固定位数的整数快速转换为 char* 左填充 '0',这是 little-endian 体系结构(所有 x86、x86_64 和其他)的示例:
如果要转换两位数:
int32_t s = 0x3030 | (n/10) | (n%10) << 8;
如果要转换三位数字:
int32_t s = 0x303030 | (n/100) | (n/10%10) << 8 | (n%10) << 16;
如果要转换四位数:
int64_t s = 0x30303030 | (n/1000) | (n/100%10)<<8 | (n/10%10)<<16 | (n%10)<<24;
依此类推,最多七位数。在此示例中,n
是给定的整数。转换后,它的字符串表示可以作为 (char*)&s
访问:
std::cout << (char*)&s << std::endl;
注意:如果您需要大端字节序,虽然我没有测试它,但这里有一个例子:对于三位数,它是 int32_t s = 0x00303030 | (n/100)<< 24 | (n/10%10)<<16 | (n%10)<<8;
对于四位数(64 位拱形):int64_t s = 0x0000000030303030 | (n/1000)<<56 | (n/100%10)<<48 | (n/10%10)<<40 | (n%10)<<32;
我认为它应该工作。
添加一些语法糖是相当容易的,它允许人们以类似流的方式即时组合字符串
#include <string>
#include <sstream>
struct strmake {
std::stringstream s;
template <typename T> strmake& operator << (const T& x) {
s << x; return *this;
}
operator std::string() {return s.str();}
};
现在您可以将任何您想要的内容(假设为它定义了运算符 << (std::ostream& ..)
)附加到 strmake()
并使用它来代替 std::string
。
例子:
#include <iostream>
int main() {
std::string x =
strmake() << "Current time is " << 5+5 << ":" << 5*5 << " GST";
std::cout << x << std::endl;
}
利用:
#define convertToString(x) #x
int main()
{
convertToString(42); // Returns const char* equivalent of 42
}
我用:
int myint = 0;
long double myLD = 0.0;
string myint_str = static_cast<ostringstream*>(&(ostringstream() << myint))->str();
string myLD_str = static_cast<ostringstream*>(&(ostringstream() << myLD))->str();
它适用于我的 Windows 和 Linux g++ 编译器。
这是另一种简单的方法
char str[100];
sprintf(str, "%d", 101);
string s = str;
sprintf
是一种众所周知的将任何数据插入所需格式的字符串的方法。
您可以将 char *
数组转换为字符串,如第三行所示。
如果您使用 MFC,则可以使用 CString
:
int a = 10;
CString strA;
strA.Format("%d", a);
C++11 为数字类型引入了 std::to_string()
:
int n = 123; // Input, signed/unsigned short/int/long/long long/float/double
std::string str = std::to_string(n); // Output, std::string
string number_to_string(int x) {
if (!x)
return "0";
string s, s2;
while(x) {
s.push_back(x%10 + '0');
x /= 10;
}
reverse(s.begin(), s.end());
return s;
}
这对我有用 -
我的代码:
#include <iostream>
using namespace std;
int main()
{
int n = 32;
string s = to_string(n);
cout << "string: " + s << endl;
return 0;
}
stringstream
?
std::to_string()
using namespace std;
:)
int i = 255; std::string s = std::to_string(i);
在 c++ 中,to_string() 将通过将值表示为字符序列来创建整数值的字符串对象。
使用普通的标准 stdio 标头,您可以将 sprintf 上的整数转换为缓冲区,如下所示:
#include <stdio.h>
int main()
{
int x=23;
char y[2]; //the output buffer
sprintf(y,"%d",x);
printf("%s",y)
}
请记住根据您的需要照顾您的缓冲区大小[字符串输出大小]
利用:
#include<iostream>
#include<string>
std::string intToString(int num);
int main()
{
int integer = 4782151;
std::string integerAsStr = intToString(integer);
std::cout << "integer = " << integer << std::endl;
std::cout << "integerAsStr = " << integerAsStr << std::endl;
return 0;
}
std::string intToString(int num)
{
std::string numAsStr;
bool isNegative = num < 0;
if(isNegative) num*=-1;
do
{
char toInsert = (num % 10) + 48;
numAsStr.insert(0, 1, toInsert);
num /= 10;
}while (num);
return isNegative? numAsStr.insert(0, 1, '-') : numAsStr;
}
char * bufSecs = new char[32];
char * bufMs = new char[32];
sprintf(bufSecs, "%d", timeStart.elapsed()/1000);
sprintf(bufMs, "%d", timeStart.elapsed()%1000);
namespace std
{
inline string to_string(int _Val)
{ // Convert long long to string
char _Buf[2 * _MAX_INT_DIG];
snprintf(_Buf, "%d", _Val);
return (string(_Buf));
}
}
您现在可以使用 to_string(5)
。
std
命名空间也不是您应该做的事情。此外,_MAX_INT_DIG
似乎不是标准宏,因此如果定义错误,此代码很有可能引发未定义的行为。 -1
您使用计数器类型的算法来转换为字符串。我从对 Commodore 64 计算机编程中获得了这项技术。它也适用于游戏编程。
您取整数并取以 10 的幂加权的每个数字。因此假设整数为 950。如果整数等于或大于 100,000,则减去 100,000 并在 ["000000"]; 处增加字符串中的计数器;继续这样做,直到位置 100,000 中没有更多数字为止。再降一个十的幂。如果整数等于或大于 10,000,则减去 10,000 并增加字符串中 ["000000"] + 1 位置处的计数器;继续这样做,直到位置 10,000 没有更多数字为止。
如果整数等于或大于 100,000,则减去 100,000 并在 ["000000"] 处增加字符串中的计数器;继续这样做,直到位置 100,000 中没有更多数字为止。再降一个十的幂。
如果整数等于或大于 10,000,则减去 10,000 并增加字符串中 ["000000"] + 1 位置处的计数器;继续这样做,直到位置 10,000 没有更多数字为止。
放下另一个十的幂
重复模式
我知道 950 太小,无法用作示例,但我希望您能理解。
我认为使用 stringstream
非常简单:
string toString(int n)
{
stringstream ss(n);
ss << n;
return ss.str();
}
int main()
{
int n;
cin >> n;
cout << toString(n) << endl;
return 0;
}
不定期副业成功案例分享
to_string
不是std
修复的成员:stackoverflow.com/questions/12975341/…g++ -std=c++11 someFile.cc
std
的成员,除了一个。Error : No instance of overloaded function "std::to_string" matches the argument list
我正在使用 VS2010 c++string s = to_string((_ULonglong)i);