从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 ++ 转换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()
需要三个参数。
Answers:
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在n3242)
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);
几年后,与@ 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 ++源代码的中央标头中定义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 ++ 11 std::to_string
),并且不需要任何第三方包含(如果您不能使用Boost lexical_cast<>
);这些其他解决方案都具有更好的性能。
dynamic_cast
但是我正在使用clang进行编译,因此它对此有所抱怨。如果我只是略过,dynamic_cast
那它编译就很好。dynamic_cast
在这种情况下服务的目的是什么?我们已经在创建一个ostringstream
,那么为什么要投射它呢?
ostringstream
,我们对其进行了调用operator<<()
,该方法会返回ostream &
- .str()
尚未定义。我真的很奇怪,如果不使用强制转换,c将如何使这项工作(或为什么它会产生错误)。这个结构已经在很多地方发布,并且我已经在包括MSVC,GCC和XLC在内的许多不同的编译器上使用了十多年,所以我很惊讶于此。
do { } while( 0 )
不会添加任何内容。在2.和3.中,您可能有一个要点-可以使用静态强制转换完成,也许其中的一个模板向导可以提供一个“更细”的界面。但是正如我所说,这绝不是我的发明。环顾四周,这个宏(宏!)无处不在。POLA本身就是这种情况。我可能会对此加一点玩意,以使其更“简化”。
我通常使用以下方法:
#include <sstream>
template <typename T>
std::string NumberToString ( T Number )
{
std::ostringstream ss;
ss << Number;
return ss.str();
}
在此进行详细说明。
ss
,您需ss.clear()
要这样做。没有这种初始化,我已经看到了意想不到的结果。
clear()
新建的ostringstream
对象。clear()
重置错误/错误标志,并且尚未生成任何错误/错误条件。
NumberToString(23213.123)
产生,23213.1
而std::to_string(23213.123)
产生23213.123000
时在那里发生什么?
最常见的简单方法大概就是将您的第二选择包装到名为的模板中lexical_cast
,例如Boost中的模板,因此您的代码如下所示:
int a = 10;
string s = lexical_cast<string>(a);
这样的好处之一是它也支持其他类型的转换(例如,相反方向的效果也一样)。
还要注意,尽管Boost lexical_cast刚开始只是写到一个字符串流,然后从该流中提取回来,但它现在有几个附加项。首先,已经添加了许多类型的专门化,因此对于许多常见类型,它比使用stringstream的速度快得多。其次,它现在检查结果,因此(例如)如果您从字符串转换为int
,则如果该字符串包含无法转换为的内容int
(例如,1234
将成功但123abc
会抛出),则可能引发异常。
从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
),成足够尺寸的缓冲器,则创建std::string
的缓冲区的内容。
如果您安装了Boost(应该这样做):
#include <boost/lexical_cast.hpp>
int num = 4;
std::string str = boost::lexical_cast<std::string>(num);
使用stringstreams会更容易:
#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()
不是标准功能!
您可以std::to_string
按照Matthieu M.的建议在C ++ 11中使用available :
std::to_string(42);
或者,如果性能是至关重要的(例如,如果你做大量的转换),您可以使用fmt::format_int
从{} FMT库整数转换std::string
:
fmt::format_int(42).str();
或C字串:
fmt::format_int f(42);
f.c_str();
后者不做任何动态内存分配,比std::to_string
Boost Karma基准测试快10倍以上。有关更多详细信息,请参见C ++中的快速整数到字符串的转换。
请注意,两者都是线程安全的。
不像std::to_string
,fmt::format_int
不需要C ++ 11,并且可以与任何C ++编译器一起使用。
免责声明:我是{fmt}库的作者。
c_str()
返回指向fmt::FormatInt
类内部声明的缓冲区的指针-因此返回的指针在以下位置无效分号-另请参见stackoverflow.com/questions/4214153/lifetime-of-temporaries
std::string::c_str()
(因此命名)相同。如果要在完整表达式之外使用它,请构造一个对象,FormatInt f(42);
然后可以使用f.c_str()
而不会损坏它。
sprintf()
非常适合格式转换。然后可以像在1中所做的那样将结果C字符串分配给C ++字符串。
NULL
和0大小来调用它,以获取必要的缓冲区大小。
snprintf
(请注意SNP前缀)和sprintf
(请注意SP前缀)。您将大小传递给前者,注意不要溢出,但是后者不知道缓冲区的大小,因此可能会溢出。
snprintf
变体,然后再调用变sprintf
体。由于届时将知道缓冲区的大小,因此调用sprintf
变得完全安全。
使用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)。几乎所有标准工具(从stringstream到sprintf
,还有其他sscanf
)都在使用当前语言环境。直到最近让我难受的时候,我才意识到这一点。当前使用本地生产的东西,不难制造。
对于C ++ 98,有一些选择:
boost/lexical_cast
Boost不是C ++库的一部分,但是包含许多有用的库扩展。
该
lexical_cast
函数模板提供了支持常见的转换和从时,他们都表示为文本任意类型的方便和一致的形式。
- Boost的文档
#include "boost/lexical_cast.hpp"
#include <string>
int main() {
int x = 5;
std::string x_str = boost::lexical_cast<std::string>(x);
return 0;
}
至于运行时,lexical_cast
第一次转换大约要花费80微秒(在我的机器上),然后如果进行冗余处理,则可以大大提高速度。
itoa
此函数未在ANSI-C中定义,也不属于C ++,但某些编译器支持。
- cplusplus.com
这意味着gcc
/ g++
无法使用编译代码itoa
。
#include <stdlib.h>
int main() {
int x = 5;
char * x_str = new char[2];
x_str = itoa(x, x_str, 10); // base 10
return 0;
}
没有要报告的运行时。我没有安装Visual Studio,据报道它可以编译itoa
。
sprintf
sprintf
是可用于C字符串的C标准库函数,并且是完全有效的替代方法。
如果在printf上使用了format,则使用与要打印的文本组成的字符串组成字符串,但是内容将作为C字符串存储在由str指向的缓冲区中,而不是被打印。
- cplusplus.com
#include <stdio.h>
int main() {
int x = 5;
char * x_str = new char[2];
int chars_written = sprintf(x_str, "%d", x);
return 0;
}
该stdio.h
首标可以不是必需的。至于运行时,sprintf
第一次转换大约要花费40微秒(在我的机器上),然后如果进行冗余处理,则可以大大提高速度。
stringstream
这是C ++库将整数转换为字符串,反之亦然的主要方法。有类似的姐妹函数可以stringstream
进一步限制流的预期用途,例如ostringstream
。使用ostringstream
专门告诉你的代码的读者,你只打算使用的<<
运营商,本质上。将整数转换为字符串时,此功能特别重要。请参阅此问题以进行更详细的讨论。
#include <sstream>
#include <string>
int main() {
int x = 5;
std::ostringstream stream;
stream << x;
std::string x_str = stream.str();
return 0;
}
至于运行时,该ostringstream
操作大约需要71微秒(在我的机器上),然后如果进行了冗余处理,则此后可以大大提高速度,但不及以前的功能。
当然,还有其他选择,您甚至可以将其中一个包装到自己的函数中,但这可以分析一些流行的选择。
C ++ 17提供std :: to_chars作为高性能的独立于语言环境的替代方案。
添加一些语法糖相当容易,该语法糖可以使用户以类似流的方式实时编写字符串
#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;
}
已编辑。如果您需要将固定位数的整数快速转换为char * 并用'0'左填充,这是小端架构(所有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;
我认为它应该可以工作。
采用:
#define convertToString(x) #x
int main()
{
convertToString(42); // Returns const char* equivalent of 42
}
std::to_string()
针对数字类型引入的C ++ 11 :
int n = 123; // Input, signed/unsigned short/int/long/long long/float/double
std::string str = std::to_string(n); // Output, std::string
采用:
#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;
while (num)
{
char toInsert = (num % 10) + 48;
numAsStr.insert(0, 1, toInsert);
num /= 10;
}
return numAsStr;
}
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;
}
如果您使用的是MFC,则可以使用CString
:
int a = 10;
CString strA;
strA.Format("%d", a);
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。
掉十的力量
我知道950太小,无法用作示例,但我希望您能理解。