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

758

我想将一个字符串转换为整数,而不是ASCII码。

简单来说,我们会得到一个字符串方程。我们需要将其分解,正确格式化并解决线性方程。但是,我无法将字符串转换为整数。

我知道这个字符串的格式将是(-5)或(25)等,因此它一定是整数。但是如何从一个字符串中提取出它呢?

我考虑的一个方法是通过字符串运行for / while循环,检查数字,提取其后的所有数字,然后查看是否有前导'-',如果有,则将整数乘以-1。

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


12
你尝试过使用atoi()函数吗? - i_am_jorf
3
好的,我会尽力进行翻译。以下是您提供链接中的内容:函数原型:int atoi (const char* str);功能:将参数 str 所指向的字符串转换为一个整数(类型为 int)。返回值:如果转换成功,则返回该整数,否则返回零。注意事项:
  • 该函数会跳过字符串开头的空格字符。
  • 当遇到非数字字符时,停止转换,返回当前已经转换的整数值。
  • 如果转换后的整数超出了 int 类型的范围,则返回 INT_MAXINT_MIN,具体取决于转换结果的符号。
示例用法:/* atoi examples */ #include /* printf */ #include /* atoi */ int main () { int i; char buffer[256]; printf ("Enter a number: "); fgets (buffer, 256, stdin); i = atoi (buffer); printf ("The value entered is %d. Its double is %d.\n",i,i*2); return 0; }
- i_am_jorf
2
http://stackoverflow.com/search?q=convert+string+int++c%2B%2B - Kiril Kirov
9
那么你建议他为一些标准库已经能够完成的事情使用整个库吗?@Chad - Bojangles
8
如果你有一个名为 myStringstd::string,而想要使用 atoi 函数,则需要输入 atoi(myString.c_str()) - Robᵩ
显示剩余7条评论
26个回答

2
C++随着时间的推移发展了起来,其中解析int的方法也随之改变。 我将在这个答案中提供一个总结。
注意:这个答案同样适用于long、float和其他算术类型。
比较
下表比较了所有选项(只包括C++标准选项,没有第三方库),按照最新到最旧的顺序。
方法 错误处理 优点和缺点
std::from_chars
std::from_chars_result
(手动错误处理)
✔️ 快速且零开销
✔️ 支持任意基数作为运行时参数
✔️ 也适用于浮点数,可选择格式
❌ 接口不人性化
❌ 不支持区域设置
std::sto*系列
std::invalid_argument
std::out_of_range
(异常)
✔️ 简单接口
✔️ 支持任意基数作为运行时参数
✔️ 也适用于浮点数
✔️ 在正常情况下没有额外开销
❌ 如果错误频繁发生效率低下
❌ 名称晦涩
❌ 不支持区域设置
std::istringstream
bool 标志,或
stream.exceptions()
✔️ 通用方法(适用于具有>>运算符的类型)
✔️ 考虑区域设置(例如,可以更改基数)
✔️ 可以检测不同的格式(例如,0x...
❌ 慢且流的开销很大
❌ 对不同基数的支持有限
std::strto*系列
std::errno
(全局标志,手动)
✔️ 生成的汇编代码较小
✔️ 在正常/异常情况下开销较小
✔️ 支持任意基数作为运行时参数
✔️ 与C兼容
✔️ 也适用于浮点数
✔️ 支持区域设置
✔️ 如果基数为零,可以检测不同的格式
❌ 名称晦涩
❌ 接口不人性化
std::ato*系列
零表示失败
(手动错误处理)
✔️ 生成的汇编代码较小
✔️ 简单接口
✔️ 在正常/异常情况下开销较小
✔️ 与C兼容
✔️ 也适用于浮点数
❌ 名称晦涩
❌ 对于int,不支持基数、格式等
std::sscanf
int 解析的参数数量
(手动错误处理)
✔️ 生成的汇编代码较小
✔️ 也适用于浮点数
✔️ 可以检测不同的格式(例如,0x...
✔️ 与C兼容
❌ 接口不人性化
❌ 没有类型安全性,容易出错
❌ 对不同基数的支持有限

推荐做法

  • 如果您有一个高性能的应用程序,那么请使用std::from_chars,或者如果不可用,则使用std::strto*std::sto*std::istringstream中的异常开销是不可接受的。
  • 否则,如果您需要与C兼容,请使用std::strto*
  • 否则,如果您的项目禁止使用异常,请使用std::istringstream
  • 否则,请使用std::sto*,或者创建一个std::from_chars的包装器。

大多数特殊情况是不太可能发生的,所以大部分时间,请使用std::stoistd::from_chars的包装器

// could be generalized with a template
bool parse_int(std::string_view str, int& out, int base = 10) {
    auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out, base);
    return err == std::errc{};
}

std::string s = ...;
if (int x; parse_int(s, x)) {
    // x has been parsed :)
}

这种包装器的优点是,在C++17之前,您始终可以回退到其他函数,同时始终具有相同的接口。
// alternative pre-C++17 version
bool parse_int(const std::string& str, int& out, int base = 10) {
    errno = 0;
    char* end = nullptr;
    out = std::strtol(str.data(), str.data() + str.size(), &end, base);
    return str.data() != end && errno == 0;
}

如果你不在乎这个,你也可以让parse_int返回std::optional<int>而不是分配一个引用。

2

好的,有很多答案,很多可能性。我在这里缺少的是一些通用的方法,可以将字符串转换为不同的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上,最大的int是2147483647。 让我们给一个字符串赋值为max int + 1:string str = "2147483648"。 现在,当将字符串转换为int时:

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

x变成了2147483647,这明显是一个错误:字符串“2147483648”不应该被转换为整数2147483647。提供的函数toIntegralType可以检测此类错误并抛出异常。


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

您可以使用std::stringstream,以下是一个示例:

#include <iostream>
#include <sstream>
using namespace std;
string r;
int main() {
    cin >> r;
    stringstream tmp(r);
    int s;
    tmp >> s;
    cout << s;
    return 0;
}

1

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

#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);

0
int stringToInt(std::string value) {
    if (value.length() == 0 || value.find(std::string("NULL")) != std::string::npos || value.find(std::string("null")) != std::string::npos) {
        return 0;
    }

    int i;
    std::stringstream stream1;
    stream1.clear();
    stream1.str(value);
    stream1 >> i;
    return i;
}

0

来自 std::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, A Space Odyssey: 2001 and [, A Space Odyssey]

40c3:  16579

-10010110001: -1201

0x7f: 127

0

我的代码:

#include <iostream>
using namespace std;

int main()
{
    string s="32";  //String
    int n=stoi(s);  //Convert to int
    cout << n + 1 << endl;

    return 0;
}

0

atoi 是一个内置函数,它将字符串转换为整数,假设字符串以整数表示开头。


1
每当你想到 atoi 时,使用 strtol 替代。 - Ben Voigt
atoi和strtol在无法进行转换时都返回0。因此,在使用之前仍然需要进行验证。(Ben在上面指出了这一点) - Azeroth2b

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

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

更多信息请参见{{link1:C++中的字符串转整数}}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接