如何在 C++ 中将数字转换为字符串,反之亦然

How to convert a number to string and vice versa in C++

提问人:Armen Tsirunyan 提问时间:3/13/2011 最后编辑:CommunityArmen Tsirunyan 更新时间:8/10/2023 访问量:172340

问:

由于这个问题每周都会被问到,因此此常见问题解答可能会对很多用户有所帮助。

  • 如何在 C++ 中将整数转换为字符串

  • 如何在 C++ 中将字符串转换为整数

  • 如何在 C++ 中将浮点数转换为字符串

  • 如何在 C++ 中将字符串转换为浮点数

C 字符串 类型转换 数字 C++-FAQ

评论

1赞 Firzok Nadeem 6/25/2020
对于这样的转换,我有一个书签 converttypes.com

答:

89赞 Armen Tsirunyan 3/13/2011 #1

如何在 C++03 中将数字转换为字符串

  1. 不要使用 or 函数,因为它们是非标准的,因此不可移植。itoaitof
  2. 使用字符串流

     #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::endlstd::hexstd::setw()std::setprecision()cout

    不要与 混淆。后者已弃用std::ostringstreamstd::ostrstream

  3. 使用增强词法转换。如果你不熟悉 boost,最好从像这样的小型库lexical_cast开始。要下载和安装 boost 及其文档,请访问此处。虽然 boost 不在 C++ 标准中,但许多 boost 库最终都实现了标准化,boost 被广泛认为是最好的 C++ 库。

    词法转换使用下面的流,所以基本上这个选项与前一个相同,只是不那么冗长。

    #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++03 中将字符串转换为数字

  1. 继承自 C 的最轻量级选项是函数(用于整数(按字母顺序排列到整数))和(对于浮点值(按字母顺序排列到浮点数))。这些函数将 C 样式的字符串作为参数 (),因此它们的使用可能被认为是一种不太好的 C++ 实践。cplusplus.com 有关于 atoiatof 的易于理解的文档,包括它们在输入错误时的行为方式。但是,该链接包含一个错误,即根据标准,如果输入数字太大而无法适应目标类型,则行为是未定义的。atoiatofconst char *

    #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*
    }
    
  2. 使用字符串流(这次输入字符串流,)。同样,istringstream 的使用方式与 .同样,不要与 混淆。后者已弃用。istringstreamcinistringstreamistrstream

    #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  
    }
    
  3. 使用增强词法转换

    #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
    }       
    

    如果输入错误,则抛出 type 的异常lexical_castboost::bad_lexical_cast

评论

4赞 Steve Jessop 3/13/2011
cplusplus的文档不是很好,这是不正确的。它没有提到如果字符串的数值不能用 表示,则行为是未定义的。相反,它说超出范围的值被限制在 /,我在 C++03 或 C89 中都找不到。对于不受信任/未经验证的输入,或者在处理流不支持的基时,您需要 ,它已定义错误行为。以及 / 的类似评论。atoiintINT_MAXINT_MINstrtolatofstrtod
2赞 Johannes Schaub - litb 3/13/2011
cplusplus.com 关于“atoi”是错误的。它说返回值“如果无法执行有效的转换,则返回零值。如果正确的值超出了可表示值的范围,则返回 INT_MAX 或 INT_MIN“,但规范说”如果无法表示结果的值,则行为未定义“,并且”除了错误行为外,它们等效于 。atoi[...] 函数返回转换后的值。众所周知,cplusplus.com 对于初学者来说是一个令人难以置信的不良信息来源。(int)strtol(nptr, (char **)NULL, 10)
0赞 sbi 5/27/2011
istr >> i1 >> f >> i2;严重错过了成功的支票。
4赞 Pubby 5/9/2012
可能想添加std::to_string
1赞 Abhineet 6/29/2012
@ArmenTsirunyan:+10,这是我见过的最好的答案之一。谢谢你的回答。
0赞 Viktor Sehr 3/14/2011 #2

我从 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");

您可能还需要 wstring 的版本。

评论

6赞 Armen Tsirunyan 3/14/2011
这正是 boost::lexical_cast 的作用。而 boost 以一种更通用的方式做到这一点。
0赞 Viktor Sehr 3/14/2011
没错,我浏览了第一个答案,没有看到提升::lexical_casts。
141赞 KillianDS 6/19/2012 #3

C++11 更新

作为标准,字符串到数字的转换(反之亦然)内置于标准库中。(根据第21.5段)中存在以下所有功能。C++11<string>

字符串转数字

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_argumentstd::out_of_range

如果转换成功且未成功,则将包含未用于解码的第一个字符的索引。这可能是最后一个字符后面的索引。idx0idx

最后,整型允许指定一个基数,对于大于 9 的数字,假定字母表为 ( 直到 )。您可以在此处找到有关可以解析浮点数、有符号整数和无符号整数的确切格式的更多信息。a=10z=35

最后,对于每个函数,还有一个重载,它接受 a 作为它的第一个参数。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 stringsream 选项并使用流操纵器,如此处的另一个答案中所述。

如注释中所述,这些函数回退到默认尾数精度,该精度可能不是最大精度。如果您的应用程序需要更高的精度,最好返回到其他字符串格式设置过程。

还定义了类似的函数,这些函数被命名为 ,这些函数将返回一个 .to_wstringstd::wstring

评论

4赞 fun4jimmy 11/27/2014
std::to_string浮点类型的精度会降低很多。例如,返回字符串 23.432390。这使得使用这些函数无法往返浮点值。double f = 23.4323897462387526; std::string f_str = std::to_string(f);
0赞 KillianDS 11/27/2014
@fun4jimmy这是特定标准或实施施加的限制?会将其添加到答案中。并不是说在琴弦上穿梭是一个好主意。
0赞 fun4jimmy 11/27/2014
C++ 标准说“返回:每个函数返回一个字符串对象,该对象包含其参数值的字符表示形式,该参数将通过调用 sprintf(buf, fmt, val) 生成,格式说明符分别为”%d“、”%u“、”%ld“、”%lu“、”%lld“、”%llu“、”%f“、”%f“或%Lf“,其中 buf 指定足够大小的内部字符缓冲区。我看了一下 printfC99 标准,我认为小数位数取决于 float.h 中。#define DECIMAL_DIG
0赞 fun4jimmy 11/27/2014
布鲁斯·道森(Bruce Dawson)在他的博客上发表了一些关于往返浮点数所需的精度的好文章。
2赞 Ident 8/13/2015
所有这些函数都受到全局语言环境的影响,如果使用库,尤其是使用线程,这可能会导致问题。在这里看我的问题:stackoverflow.com/questions/31977457/......
4赞 JiaHao Xu 5/18/2018 #4

在 C++17 中,标头 charconv 中引入了新函数 std::to_charsstd::from_chars

std::to_chars 与语言环境无关,不可分配, 和不投掷。

只有一小部分格式设置策略被 提供了其他库(例如 std::sprintf)。

std::to_chars,std::from_chars 也是如此。

std::from_chars 可以恢复的保证 格式化的每个浮点值 通过to_chars 仅当两者都提供时 函数来自同一实现

 // 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);
}

虽然它没有被编译器完全实现,但它肯定会被实现。

-2赞 Roshan Singh 10/17/2020 #5
#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;
}

输出:

  • 000101
  • 101
  • 1011

评论

1赞 Massimo Costa 10/17/2020
嗨,答案不完整(没有浮点转换)并且不正确(未定义)。请务必提供有用的答案to_string
0赞 aenigma 8/7/2023 #6

如果您仍然将其设计为一个单独的函数,则编写朴素和通用的代码会更容易。

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;
}