我想将一个字符串转换为int,我不是指ASCII码。

为了快速回顾,我们将一个方程作为字符串传递。我们要把它分解,正确地格式化并解出线性方程。说到这里,我不能把一个字符串转换成int型。

我知道字符串的格式是(-5)或(25)等,所以它肯定是int型。但是我们如何从字符串中提取它呢?

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

对于这样一个小问题来说,这似乎有点过于复杂了。什么好主意吗?


当前回答

从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和[,太空漫游]

40 c3: 16579

-10010110001: -1201

0x7f:127

其他回答

可能的选择如下:

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会因大量输入数据而崩溃”(参见这里和这里)。

2. std::我()*

    #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. 提高的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 () *

由于错误管理,这个解决方案很长,这里将对其进行描述。由于没有函数返回纯int,因此需要对整数进行转换(参见这里了解如何实现这种转换)。

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库。所有其他的解决方案都是不鼓励的或有缺陷的。

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

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

有很多答案,很多可能性。我在这里缺少的是一些通用方法,可以将字符串转换为不同的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输出操作符将字符串转换为整型? 以下是答案: 假设字符串包含的值超出了预期整型的限制。例如,在windows 64上,max int是2147483647。 让我们给一个字符串赋值max int + 1: string str = "2147483648"。 现在,当将字符串转换为int类型时:

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

X变成2147483647,这肯定是一个错误:字符串“2147483648”不应该被转换为int 2147483647。为integraltype提供的函数会发现这样的错误并抛出异常。

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

如果需要解释十六进制,Strtol和stringstream需要指定基数。

我知道这个问题很老了,但我认为有更好的解决方法

#include <string>
#include <sstream>

bool string_to_int(std::string value, int * result) {
  std::stringstream stream1, stream2;
  std::string stringednumber;
  int tempnumber;
  stream1 << value;
  stream1 >> tempnumber;
  stream2 << tempnumber;
  stream2 >> stringednumber;
  if (!value.compare(stringednumber)) {
    *result = tempnumber;
    return true;
  }
  else return false;
}

如果我写的代码是正确的,这将返回一个布尔值,告诉你如果字符串是一个有效的数字,如果为假,它不是一个数字,如果为真,它是一个数字,这个数字现在是结果,你会这样调用它:

std::string input;
std::cin >> input;
bool worked = string_to_int(input, &result);