如何将std :: string转换为int?


483

只是一个简单的问题。我已经看了很多遍互联网,发现了一些解决方案,但是都没有用。看着将字符串转换为int并不意味着ASCII码。

为了快速调试,我们将方程式作为字符串传递。我们将其分解,正确设置格式并求解线性方程。现在,我无法将字符串转换为int。

我知道该字符串将采用(-5)或(25)等格式,因此绝对是整数。但是,我们如何从字符串中提取出来呢?

我想到的一种方法是在字符串中运行for / while循环,检查数字,然后提取所有数字,然后查看是否有前导“-”,如果有,则将int乘以- 1。

对于这么小的问题,似乎有些复杂。有任何想法吗?


9
你试过了atoi()吗?
i_am_jorf 2011年



7
@Chad因此,您建议他使用整个库来完成语言可以与标准库一起使用的工作?
Bojangles

6
@Brandon,如果您有一个std::string myString,并且想要使用atoi,那么您想说atoi(myString.c_str())
罗伯(Robᵩ)2011年

Answers:


725

在C ++ 11中,有一些不错的新转换函数,从转换std::string为数字类型。

所以代替

atoi( str.c_str() )

您可以使用

std::stoi( str )

str您的电话号码在哪里std::string

有版本号的所有口味: long stol(string)float stof(string)double stod(string),...查看http://en.cppreference.com/w/cpp/string/basic_string/stol


5
有关std :: stoi的问题,请参见stackoverflow.com/a/6154614/195527:它将转换"11x"为integer 11
CC。

5
#include <stdlib.h> / * atoi * /
Ulad Kasach '16

4
“ @CC这也是atoi的行为:cplusplus.com/reference/cstdlib/atoi ”该字符串可以在形成整数的字符之后包含其他字符,这些字符将被忽略,并且对该函数的行为没有影响。
锡精灵

4
您介意使用from_charsC ++ 17 更新此答案吗?应该比快几个数量级stoi
NathanOliver '19

stoi应该是首选。请参阅为什么不应该使用atoi()?
phuclv

57
std::istringstream ss(thestring);
ss >> thevalue;

要完全正确,您需要检查错误标志。


2
这不会提取-5(-5)
纳瓦兹

@Nawaz,实际上是在那儿,还是OP展示他的琴弦的方式?
温斯顿·埃韦特

我不知道。我只是指出该方法的局限性。
纳瓦兹

16
@Nawaz,它也不能对输入“ WERWER”进行操作。我不认为括号实际上是他实际字符串的一部分,并且我不认为不解析它们的事实也没有关系。
温斯顿·埃韦特

4
@纳瓦兹,好吧...我不这样说,但我知道你怎么可能。
温斯顿·埃韦特

44

可能的选项如下所述:

1.第一个选项:sscanf()

    #include <cstdio>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        if(sscanf(str.c_str(), "%d", &i) != 1)
            // error management

        // string -> float
        if(sscanf(str.c_str(), "%f", &f) != 1)
            // error management

        // string -> double 
        if(sscanf(str.c_str(), "%lf", &d) != 1)
            // error management

这是一个错误(cppcheck也显示了此错误),因为“在某些版本的libc上,没有字段宽度限制的scanf可能会因大量输入数据而崩溃”(请参见herehere)。

2.第二个选项:std :: sto *()

    #include <iostream>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        try {
            // string -> integer
            int i = std::stoi(str);

            // string -> float
            float f = std::stof(str);

            // string -> double 
            double d = std::stod(str);
        } catch (...) {
            // error management
        }   

该解决方案简短而优雅,但是仅在符合C ++ 11的编译器上可用。

3.第三种选择:sstreams

    #include <string>
    #include <sstream>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        std::istringstream ( str ) >> i;

        // string -> float
        std::istringstream ( str ) >> f;

        // string -> double 
        std::istringstream ( str ) >> d;

        // error management ??

但是,使用此解决方案很难区分输入错误(请参阅此处)。

4.第四个选项:Boost的lexical_cast

    #include <boost/lexical_cast.hpp>
    #include <string>

        std::string str;

        try {
            int i = boost::lexical_cast<int>( str.c_str());
            float f = boost::lexical_cast<int>( str.c_str());
            double d = boost::lexical_cast<int>( str.c_str());
            } catch( boost::bad_lexical_cast const& ) {
                // Error management
        }

但是,这只是的包装sstream,文档建议使用sstream进行更好的错误管理(请参阅此处))。

5.第五个选项:strto *()

由于存在错误管理,此解决方案非常长,在此进行描述。由于没有函数返回纯整数,因此在整数的情况下需要进行转换(有关如何实现此转换的信息,请参见此处)。

6.第六选择:Qt

    #include <QString>
    #include <string>

        bool ok;
        std::string;

        int i = QString::fromStdString(str).toInt(&ok);
        if (!ok)
            // Error management

        float f = QString::fromStdString(str).toFloat(&ok);
        if (!ok)
            // Error management 

        double d = QString::fromStdString(str).toDouble(&ok);
        if (!ok)
    // Error management     

结论

总结起来,最好的解决方案是C ++ 11,std::stoi()或者作为第二个选择,使用Qt库。不建议使用其他解决方案或进行故障检查。


固定。感谢您的举报。
克劳迪奥

美丽的总结,非常感谢。我是否可以建议添加初步意见,以提出最终解决方案,以便只有对细节感兴趣的人才能继续阅读?
luca

1
这应该是被接受的答案,您也会忘记(或者应该添加原因,因为它是一个旧答案)from_chars
xception


9

那么Boost.Lexical_cast呢?

这是他们的例子:

以下示例将命令行参数视为数字数据序列:

int main(int argc, char * argv[])
{
    using boost::lexical_cast;
    using boost::bad_lexical_cast;

    std::vector<short> args;

    while(*++argv)
    {
        try
        {
            args.push_back(lexical_cast<short>(*argv));
        }
        catch(bad_lexical_cast &)
        {
            args.push_back(0);
        }
    }
    ...
}

链接断开。你能修好吗?
Yuchen Zhong'3

5

诚然,我的解决方案不适用于负整数,但是它将从包含整数的输入文本中提取所有正整数。它使用numeric_only语言环境:

int main() {
        int num;
        std::cin.imbue(std::locale(std::locale(), new numeric_only()));
        while ( std::cin >> num)
             std::cout << num << std::endl;
        return 0;
}

输入文本:

 the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878

输出整数:

 5
25
7987
78
9878

该类numeric_only定义为:

struct numeric_only: std::ctype<char> 
{
    numeric_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
        return &rc[0];
    }
};

完整的在线演示:http : //ideone.com/dRWSj


4

这可能有点矫kill过正,但 boost::lexical_cast<int>( theString )应该可以很好地完成工作。


错字了。它应该简单boost::lexical_cast<int>( theString )(在theString其中包含要转换为字符串的变量的名称int)。
James Kanze 2011年


1

在Windows中,您可以使用:

const std::wstring hex = L"0x13";
const std::wstring dec = L"19";

int ret;
if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}
if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}

strtolstringstream如果需要解释十六进制,则需要指定基数。


1

好吧,很多答案,很多可能性。我在这里缺少的是一些通用方法,该方法将字符串转换为不同的C ++整数类型(short,int,long,bool等)。我想出了以下解决方案:

#include<sstream>
#include<exception>
#include<string>
#include<type_traits>

using namespace std;

template<typename T>
T toIntegralType(const string &str) {
    static_assert(is_integral<T>::value, "Integral type required.");
    T ret;
    stringstream ss(str);
    ss >> ret;
    if ( to_string(ret) != str)
        throw invalid_argument("Can't convert " + str);
    return ret;
}

以下是用法示例:

string str = "123";
int x = toIntegralType<int>(str); // x = 123

str = "123a";
x = toIntegralType<int>(str); // throws exception, because "123a" is not int

str = "1";
bool y = toIntegralType<bool>(str); // y is true
str = "0";
y = toIntegralType<bool>(str); // y is false
str = "00";
y = toIntegralType<bool>(str); // throws exception

为什么不只使用stringstream输出运算符将字符串转换为整数类型?答案是这样的:假设一个字符串包含的值超出了预期整数类型的限制。例如,在Wndows上,64 int的最大值是2147483647。让我们为字符串赋值max int + 1:字符串str =“ 2147483648”。现在,将字符串转换为int时:

stringstream ss(str);
int x;
ss >> x;

x变成2147483647,这绝对是一个错误:不应将字符串“ 2147483648”转换为int2147483647。toIntegralType提供的函数会发现此类错误并引发异常。


0

来自http://www.cplusplus.com/reference/string/stoi/

// stoi example
#include <iostream>   // std::cout
#include <string>     // std::string, std::stoi

int main ()
{
  std::string str_dec = "2001, A Space Odyssey";
  std::string str_hex = "40c3";
  std::string str_bin = "-10010110001";
  std::string str_auto = "0x7f";

  std::string::size_type sz;   // alias of size_t

  int i_dec = std::stoi (str_dec,&sz);
  int i_hex = std::stoi (str_hex,nullptr,16);
  int i_bin = std::stoi (str_bin,nullptr,2);
  int i_auto = std::stoi (str_auto,nullptr,0);

  std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
  std::cout << str_hex << ": " << i_hex << '\n';
  std::cout << str_bin << ": " << i_bin << '\n';
  std::cout << str_auto << ": " << i_auto << '\n';

  return 0;
}

输出:

2001,太空漫游:2001年和[,太空漫游]

40c3:16579

-10010110001:-1201

0x7f:127



0
ll toll(string a){
    ll ret=0;
    bool minus=false;
    for(auto i:a){
        if(i=='-'){ minus=true; continue; }
        ret*=10;
        ret+=(i-'0');
    } if(minus) ret*=-1;
    return ret;
    # ll is defined as, #define ll long long int
    # usage: ll a = toll(string("-1234"));
}

0

要将字符串表示形式转换为整数值,可以使用std :: stringstream。

如果转换的值超出整数数据类型的范围,则返回INT_MIN或INT_MAX。

同样,如果字符串值不能表示为有效的int数据类型,则返回0。

#include 
#include 
#include 

int main() {

    std::string x = "50";
    int y;
    std::istringstream(x) >> y;
    std::cout << y << '\n';
    return 0;
}

输出:50

根据上面的输出,我们可以看到它已从字符串数字转换为整数。

从int C ++的字符串获取源代码和更多内容


-2

一线版本: long n = strtol(s.c_str(), NULL, base);

s是字符串,并且baseint诸如2、8、10、16之类的。)

您可以参考此链接以获取有关的更多详细信息strtol


核心思想是使用strtol函数,该函数包含在中cstdlib

由于strtol仅使用char数组处理,因此我们需要转换stringchar数组。您可以参考此链接

一个例子:

#include <iostream>
#include <string>   // string type
#include <bitset>   // bitset type used in the output

int main(){
    s = "1111000001011010";
    long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string

    cout << s << endl;
    cout << t << endl;
    cout << hex << t << endl;
    cout << bitset<16> (t) << endl;

    return 0;
}

将输出:

1111000001011010
61530
f05a
1111000001011010

-3

还有另一种简单的方法:假设您有一个像 c='4'这样因此可以执行以下步骤之一:

1st:整数q

q=(int) c ; (q is now 52 in ascii table ) . q=q-48; remember that adding 48 to digits is their ascii code .

第二种方式:

q=c-'0'; the same , character '0' means 48


1
问题是关于从转换stringint而不是从转换charstring
Yuchen Zhong

越野车和不匹配的问题
caoanan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.