Nem*_*emo 1488 c++ string int type-conversion
在C++中转换int为等效的最简单方法是什么?string我知道两种方法.有没有更简单的方法?
(1)
int a = 10;
char *intStr = itoa(a);
string str = string(intStr);
Run Code Online (Sandbox Code Playgroud)
(2)
int a = 10;
stringstream ss;
ss << a;
string str = ss.str();
Run Code Online (Sandbox Code Playgroud)
Mat*_* M. 1975
C++ 11引入std::stoi(以及每种数字类型的变体)和std::to_stringC的对应部分atoi,itoa但以术语表示std::string.
#include <string>
std::string s = std::to_string(42);
Run Code Online (Sandbox Code Playgroud)
因此,这是我能想到的最短路.您甚至可以使用auto关键字省略命名类型:
auto s = std::to_string(42);
Run Code Online (Sandbox Code Playgroud)
注:参见[string.conversions] (21.5在n3242)
Dev*_*lar 179
几年后,与@ 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();
}
Run Code Online (Sandbox Code Playgroud)
用法:
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 ) );
Run Code Online (Sandbox Code Playgroud)
原始答案:
由于"将...转换为字符串"是一个反复出现的问题,我总是在我的C++源代码的中心标题中定义SSTR()宏:
#include <sstream>
#define SSTR( x ) static_cast< std::ostringstream & >( \
( std::ostringstream() << std::dec << x ) ).str()
Run Code Online (Sandbox Code Playgroud)
用法很简单:
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 ) );
Run Code Online (Sandbox Code Playgroud)
以上是C++ 98兼容(如果你不能使用C++ 11 std::to_string),并且不需要任何第三方包含(如果你不能使用Boost lexical_cast<>); 这些其他解决方案都有更好的性能.
Ras*_*oul 104
我通常使用以下方法:
#include <sstream>
template <typename T>
std::string NumberToString ( T Number )
{
std::ostringstream ss;
ss << Number;
return ss.str();
}
Run Code Online (Sandbox Code Playgroud)
这里详细描述.
Jer*_*fin 85
可能最常见的简单方法基本上将您的第二个选择包装到名为的模板中lexical_cast,例如Boost中的模板,因此您的代码如下所示:
int a = 10;
string s = lexical_cast<string>(a);
Run Code Online (Sandbox Code Playgroud)
这样做的一个好处是它也支持其他演员表(例如,在相反的方向上工作也一样).
另请注意,虽然Boost lexical_cast最初只是写入字符串流,然后从流中提取出来,但它现在有一些补充.首先,添加了很多类型的特化,因此对于许多常见类型,它比使用字符串流要快得多.其次,它现在检查结果,所以(例如)如果从字符串转换为a int,如果字符串包含无法转换为a的内容int(例如,1234会成功,但123abc会抛出),它可以抛出异常.
从C++ 11开始,有一个std::to_string函数为整数类型重载,所以你可以使用如下代码:
int a = 20;
std::string s = to_string(a);
Run Code Online (Sandbox Code Playgroud)
标准将这些定义为等同于使用sprintf(使用与提供的对象类型匹配的转换说明符,例如%dfor int)进行转换,将其转换为足够大小的缓冲区,然后创建std::string该缓冲区的内容.
小智 41
如果你安装了Boost(你应该):
#include <boost/lexical_cast.hpp>
int num = 4;
std::string str = boost::lexical_cast<std::string>(num);
Run Code Online (Sandbox Code Playgroud)
小智 27
使用stringstream会不会更容易?
#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
Run Code Online (Sandbox Code Playgroud)
或者做一个功能:
#include <sstream>
string IntToString(int a)
{
ostringstream temp;
temp << a;
return temp.str();
}
Run Code Online (Sandbox Code Playgroud)
Meh*_*dad 19
在纯C++中,我不知道.但对你提到的内容进行一点修改
string s = string(itoa(a));
Run Code Online (Sandbox Code Playgroud)
应该工作,而且很短.
Thr*_*986 16
sprintf()非常适合格式转换.然后,您可以像在1中一样将结果C字符串分配给C++字符串.
vit*_*aut 16
您可以std::to_string按照Matthieu M.的建议在C++ 11中使用:
std::to_string(42);
Run Code Online (Sandbox Code Playgroud)
或者,如果性能是至关重要的(例如,如果你做大量的转换),您可以使用fmt::format_int从C++格式库整数转换std::string:
fmt::format_int(42).str();
Run Code Online (Sandbox Code Playgroud)
或C字符串:
fmt::format_int f(42);
f.c_str();
Run Code Online (Sandbox Code Playgroud)
后者不进行任何动态内存分配,比std::to_stringBoost Karma基准测试快10倍以上.有关详细信息,请参阅C++中的快速整数到字符串转换.
不同std::to_string,fmt::format_int不需要C++ 11并且可以与任何C++编译器一起使用.
免责声明:我是C++格式库的作者.
Jan*_*tke 12
C++ 随着时间的推移而不断发展,并将 an 转换int为字符串的方法也随之发展。\n我将在此答案中提供摘要。\n请注意,某些方法不会std::string直接为您提供char*. 您可以轻松地转换char*为前者,并且在某些情况下避免std::string.
下表按最新到最新的顺序比较了所有选项(仅 C++ 标准选项,无第三方库)。
\n| 方法 | 结果 | 优点缺点 |
|---|---|---|
| std::格式 c++20 | std::string | \xe2\x9c\x94\xef\xb8\x8f 通用方法(对于可格式化类型) \xe2\x9c\x94\xef\xb8\x8f 支持通用基数,并且语言环境 \xe2\x9d\x8c 编译速度慢 \xe2\x9d \x8c 慢速(转发到 std::vformat) |
| std::to_chars c++17 | 写给char[] | \xe2\x9c\x94\xef\xb8\x8f 快速且零开销(无动态分配) \xe2\x9c\x94\xef\xb8\x8f 支持任何基数作为运行时参数 \xe2\x9d\x8c 仅适用于基本类型 \xe2\x9d\x8c 接口不符合人体工程学 |
| std::to_string c++11 | std::string | \xe2\x9c\x94\xef\xb8\x8f 简洁且不言自明 \xe2\x9c\x94\xef\xb8\x8f 零开销(如果需要) std::string\ xe2\x9d\x8c 仅适用于基本类型 \xe2 \x9d\x8c 仅以 10 为基数 |
| std::ostringstream c++98 | std::string | \xe2\x9c\x94\xef\xb8\x8f 通用方法(对于带有<<运算符的类型)\xe2\x9c\x94\xef\xb8\x8f 考虑语言环境(例如可以更改基数) \xe2\x9d\x8c 慢,高流的开销 |
| std::sprintf c++98 | 写给char[] | \xe2\x9c\x94\xef\xb8\x8f 最小汇编输出 \xe2\x9c\x94\xef\xb8\x8f 支持某些基数 \xe2\x9c\x94\xef\xb8\x8f 与 C 兼容,与所有其他方法不同 \xe2\x9d\x8c 仅适用于基本类型 \xe2\x9d\x8c 接口不符合人体工程学 \xe2\x9d\x8c 无类型安全 |
std::to_string如果您只需将 an 转换int为十进制字符串,请使用。它简单、优雅、正确。
如果您无法使用std::to_string,请根据您需要的功能选择其他选项。更喜欢更现代的解决方案(例如 )std::to_chars而不是较旧的解决方案(例如std::sprintf.
std::formatstd::string d = std::format("{}", 100); // d = "100"\nstd::string h = std::format("{:#x}", 15); // h = "0xf"\nRun Code Online (Sandbox Code Playgroud)\nstd::to_charsstd::array<char, 5> a;\nauto [ptr, ec] = std::to_chars(a.data(), a.data() + a.size(), 1234);\n// a = {\'1\', \'2\', \'3\', \'4\', indeterminate} (no null terminator!)\n// ptr points to 4, and ec == std::errc{}\n// notice that there is no null terminator\nstd::string_view view(a.data(), ptr); // string_view doesn\'t require null terminators\nstd::string s(a.data(), ptr); // wrapping in a std:string kinda defeats the point\nRun Code Online (Sandbox Code Playgroud)\nstd::to_stringstd::string d = std::to_string(100); // d = "100"\nRun Code Online (Sandbox Code Playgroud)\nstd::ostringstreamstd::string d = (std::ostringstream() << 100).str(); // d = "100"\nstd::string h = (std::ostringstream() << std::hex << 15).str(); // h = "0xf"\nRun Code Online (Sandbox Code Playgroud)\n注意:这些单行代码依赖于LWG 1203 (C++20),但最近的编译器也允许在 C++11 模式下使用它。更新您的编译器,或者创建一个单独的std::ostringstream stream变量(如果它不起作用)。
sprintf/snprintfchar a[20];\nsprintf(a, "%d", 15); // a = {\'1\', \'5\', \'\\0\', ?, ?, ?, ...}\nsnprintf(a, sizeof(a), "%#x", 15); // a = {\'0\', \'x\', \'f\', \'\\0\', ?, ?, ...}\nstd::string s = a;\nRun Code Online (Sandbox Code Playgroud)\n
小智 11
首先包括:
#include <string>
#include <sstream>
Run Code Online (Sandbox Code Playgroud)
第二个添加方法:
template <typename T>
string NumberToString(T pNumber)
{
ostringstream oOStrStream;
oOStrStream << pNumber;
return oOStrStream.str();
}
Run Code Online (Sandbox Code Playgroud)
使用这样的方法:
NumberToString(69);
Run Code Online (Sandbox Code Playgroud)
要么
int x = 69;
string vStr = NumberToString(x) + " Hello word!."
Run Code Online (Sandbox Code Playgroud)
小智 10
在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;
}
Run Code Online (Sandbox Code Playgroud)
使用stringstream进行数字转换很危险!
请参阅http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/,其中说明operator<<插入格式化输出.
根据您当前的区域设置,大于3位的整数,可以转换为4位数的字符串,添加额外的千位分隔符.
例如,int = 1000可以转换为字符串1.001.这可能使比较操作根本不起作用.
所以我强烈建议使用这种std::to_string方式.它更容易,做你期望的.
对于C++ 98,有几个选项:
boost/lexical_castBoost不是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;
}
Run Code Online (Sandbox Code Playgroud)
至于运行时,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;
}
Run Code Online (Sandbox Code Playgroud)
没有运行时报告.我没有安装Visual Studio,据说可以编译itoa.
sprintfsprintf 是一个C标准库函数,适用于C字符串,是一个完全有效的选择.
如果在printf上使用了格式,则使用与打印时相同的文本组成一个字符串,但不是打印,而是将内容作为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;
}
Run Code Online (Sandbox Code Playgroud)
该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;
}
Run Code Online (Sandbox Code Playgroud)
至于运行时,ostringstream操作大约需要71微秒(在我的机器上),然后如果冗余完成则会大大加快,但不会像以前的功能那样多.
当然还有其他选择,您甚至可以将其中一个包装到您自己的功能中,但这可以分析一些流行的功能.
如果您需要将固定位数的整数快速转换为左填充 '0'的char* ,这是小端架构(所有 x86、x86_64 等)的示例:
如果您要转换两位数:
int32_t s = 0x3030 | (n/10) | (n%10) << 8;
Run Code Online (Sandbox Code Playgroud)
如果您要转换三位数:
int32_t s = 0x303030 | (n/100) | (n/10%10) << 8 | (n%10) << 16;
Run Code Online (Sandbox Code Playgroud)
如果您要转换四位数:
int64_t s = 0x30303030 | (n/1000) | (n/100%10)<<8 | (n/10%10)<<16 | (n%10)<<24;
Run Code Online (Sandbox Code Playgroud)
依此类推,直至七位数字。在这个例子中n是一个给定的整数。转换后,可以通过以下方式访问它的字符串表示形式(char*)&s:
std::cout << (char*)&s << std::endl;
Run Code Online (Sandbox Code Playgroud)
注意:如果您需要大端字节顺序,虽然我没有测试它,但这里有一个示例:对于三位数,它适用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;我认为它应该可以工作。
| 归档时间: |
|
| 查看次数: |
2727891 次 |
| 最近记录: |