题 在C ++中将int转换为字符串的最简单方法


什么是最简单的转换方式 int 相当于 string 在C ++中。我知道两种方法。有没有更简单的方法?

(1)

int a = 10;
char *intStr = itoa(a);
string str = string(intStr);

(2)

int a = 10;
stringstream ss;
ss << a;
string str = ss.str();

1212
2018-04-08 04:19


起源


我认为你提供的两种方法都是很好的解决方案这取决于你需要做的上下文。如果您已经在使用流,例如读取或写入文件,那么您的第二种方法是最好的。如果你需要将int作为字符串传递给函数参数,那么itoa可能是一种简单的方法。但大多数情况下,在处理文件时会发生int到字符串转换,因此流是合适的。 - Charles Brunet
选项1如何为您工作?这是我的理解 itoa() 有三个参数。 - b1nary.atr0phy
itoa将比同等流更快。还有一些方法可以使用itoa方法重用字符串缓冲区(如果您经常生成字符串,则可以避免堆分配。例如,对于某些快速更新的数字输出)。或者,您可以生成自定义streambuf以减少一些分配开销等。首先构建流也不是一个低成本的冒险。 - Pete
@Pete:一旦你开始担心哪个更快,你会想看看 stackoverflow.com/questions/4351371/... - Ben Voigt
请注意,itoa()不是标准的一部分,因此使用它会使您的代码不可移植,因为并非所有编译器都支持它。对于Linux,除非你使用的不是GCC,否则你肯定会出局,因为GCC不支持这个功能。如果您有C ++ 0x,请使用@Matthieu在答案中建议的内容。如果不是这种情况,请使用stringstream,因为它是一个受到良好支持的功能,并且您的代码应该与每个C ++编译器兼容。作为替代方案,您可以随时使用sprintf()。 - rbaleksandar


答案:


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


1597
2018-04-08 06:13



to_string 不是。的成员 std 固定: stackoverflow.com/questions/12975341/... - Ben
或者根据您的编译器,只需设置正确的语言标准: g++ -std=c++11 someFile.cc - Thomas M. DuBuisson
@Steve:它应该是。它是...的成员 std 在我知道的每个编译器中除了一个。 - Mooing Duck
@Matthiew M.我使用的是您建议的相同但我收到此错误: Error : No instance of overloaded function "std::to_string" matches the argument list  我正在使用VS2010 c ++
@Flying:在VS2010下你必须显式地将转换整数转换为以下类型之一[_Longlong,_ULonglong,long double];即: string s = to_string((_ULonglong)i); - Zac


几年后,与@ v.oddou进行了讨论,C ++ 17终于提供了一种方法来完成最初基于宏的类型无关的解决方案(保留在下面)  经历宏观丑陋。

template < typename... Args >
std::string sstr( Args &&... args )
{
    std::ostringstream sstr;
    ( 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 ) );

原始答案:

由于“将...转换为字符串”是一个反复出现的问题,我总是定义 SSTR() 我的C ++源代码的中心标题中的宏:

#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<>);这些其他解决方案都有更好的性能。


165
2018-04-08 04:23



我不是很熟悉 dynamic_cast 但我正在使用clang进行编译,所以它抱怨它。如果我只是省略了 dynamic_cast 然后编译好;这个目的是什么? dynamic_cast 在这种情况下服务?我们已经创造了一个 ostringstream那么为什么要施展呢? - Mathew
@Mathew:我的答案中的链接导致对构造的每个部分的详细描述。虽然我们 创建 一个 ostringstream,我们打电话 operator<<() 在它上面,它返回 ostream &  - 为此 .str() 没有定义。我真的很想知道clang如何在没有演员的情况下完成这项工作(或者为什么它会产生错误)。这个结构发表在很多地方,我已经在许多不同的编译器上使用它超过十年了,包括MSVC,GCC和XLC,所以我很惊讶它的铿锵声。 - DevSolar
刚刚来到派对的好奇心,并且投了赞成票。原因:对于一个不优雅且可能很慢的解决方案投票太多。宏观用法我没有系统地对任何宏观都不屑一顾,但是这个宏太短了,终端客户总是害怕重复这个论点,除了对未受保护的多线宏的恐惧之外。 (不受do {}和(0)保护)2。dynamic_cast。看来你在这里只需要一个static_cast,除非你想断言你的库确实是按照你的希望实现的。在这种情况下,您应该使用boost :: polymorphic_downcast。 - v.oddou
@ v.oddou:当然,你可以自由批评。但是1.无效 - 宏是一个单一的陈述, do { } while( 0 ) 不会添加任何东西。使用2.和3.你可能有一点 - 这可以通过静态强制转换完成,也许你们中的一个模板向导可以提出一个“更好”的界面。但正如我所说,这绝不是我自己的发明。环顾四周,这个宏(宏!)是无处不在的。这是POLA本身的一个案例。我可能会玩这个以使它更“流线型”。 - DevSolar
@ v.oddou:看看我在C ++ 17给我们带来的东西中发现了什么。 :-)我希望你喜欢更新的答案。 - DevSolar


我通常使用以下方法:

#include <sstream>

template <typename T>
  std::string NumberToString ( T Number )
  {
     std::ostringstream ss;
     ss << Number;
     return ss.str();
  }

详细描述 这里


96
2017-11-29 22:46



使用前 ss, 你需要 ss.clear() 它。没有这个初始化,我看到了意想不到的结果。 - lifebalance
@lifebalance:我从未见过这样的行为。 - Rasoul
@lifebalance:你不需要 clear() 一个新创建的 ostringstream 目的。 clear() 重置错误/ eof标志,并且还没有生成任何错误/ eof条件。 - Remy Lebeau
你曾经 试试这个 char? - Wolf
@Rasoul NumberToString(23213.123) 产生 23213.1 而 std::to_string(23213.123) 产生 23213.123000 那里发生了什么? - Killzone Kid


可能最常见的简单方法基本上将您的第二选择包装到名为的模板中 lexical_cast,比如 促进,所以你的代码看起来像这样:

int a = 10;
string s = lexical_cast<string>(a);

这样做的一个好处是它也支持其他演员表(例如,在相反的方向上也可以工作)。

另请注意,尽管Boost lexical_cast最初只是写入字符串流,然后从流中提取出来,但它现在还有一些补充。首先,添加了很多类型的特化,因此对于许多常见类型,它比使用字符串流要快得多。其次,它现在检查结果,所以(例如)如果从字符串转换为 int,如果字符串包含无法转换为的字符串,它可以抛出异常 int (例如。, 1234 会成功,但是 123abc 会抛出)。

从C ++ 11开始,有一个 std::to_string 函数重载为整数类型,因此您可以使用如下代码:

int a = 20;
std::string s = to_string(a);

标准将这些定义为等同于进行转换 sprintf (使用与提供的对象类型匹配的转换说明符,例如 %d 对于 int),进入足够大小的缓冲区,然后创建一个 std::string 该缓冲区的内容。


84
2018-04-08 04:23



很好,我更喜欢Kevin的答案,尽管他展示了include和命名空间。只是一个小抱怨。 :)虽然干得好! - Jason R. Mick
如果你没有C ++ 11的支持,我会说这是要走的路。 - Alex
提升链接破裂了。 - Kris Hollenbeck


如果你安装了Boost(你应该):

#include <boost/lexical_cast.hpp>

int num = 4;
std::string str = boost::lexical_cast<std::string>(num);

40
2018-04-08 04:26



同意加速安装。我认为通常会有人格式化字符串。为此,我更喜欢boost :: format例如format(“%02d”,number).str() - Werner Erasmus


使用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();
}

27
2018-04-16 19:37





在纯C ++中,我不知道。但对你提到的内容进行一点修改

string s = string(itoa(a));

应该工作,而且很短。


19
2018-04-08 04:22



itoa() 不是标准功能! - cartoonist
@cartoonist:那是什么? - Mehrdad
ANSI-C和C ++中未定义此函数。所以g ++等编译器不支持它。 - cartoonist


sprintf() 非常适合格式转换。然后,您可以像在1中一样将生成的C字符串分配给C ++字符串。


16
2018-04-08 04:23



并希望你使用的缓冲区足够大...... - Matthieu M.
嘿,是的。但是,在处理C字符串时,我通常依赖snprintf()和朋友来处理任何后果。 - Throwback1986
@MatthieuM。你的评论进一步证明,你不是。如果输出因此限制而被截断,则返回值是字符数(不包括终止空字节),如果有足够的空间,则该字符数将被写入最终字符串。因此,大小或更大的返回值意味着输出被截断。所以你用它来称呼它 NULL 和零大小以获得必要的缓冲区大小。 - user1095108
@ user1095108:我觉得你错了 snprintf (注意 SNP 前缀)和 sprintf (注意 SP 字首)。您将大小传递给前者,并且注意不要溢出,但后者不知道缓冲区的大小,因此可能溢出。 - Matthieu M.
这个想法是打电话给 snprintf 变体首先和a sprintf 之后的变种。由于缓冲区大小已知,所以调用 sprintf 变得完全安全。 - user1095108