在std::string上使用strtol的用法

4
我最近从C语言转移到C++,但是有一些关于字符串的疑惑。现在的字符串不再是以前那样的字符数组并以'\0'结尾了。 我还没有找到真正的答案,所以你能把std::string类当作C-Strings使用到什么程度呢?
例如:如果我知道一个字符串中有一个数字,比如字符串ireallylike314,在C语言中,我可以使用strtol(string + 10, NULL, 10)来获取这个数字。而且,如果这种方法行不通,是否有一种方法可以像使用C-Strings一样使用std::string呢?

2
在C语言中,string[10]做的是同样的事情... - chris
在这种情况下,string[10]的作用类似于string+10,它会在该偏移量处返回相应的字符串。或者我错了吗? - BigBadWolf
3
string[10]代表的是*(string + 10),而不是(string + 10) - timrau
哦,该死,你说得对。我把自己搞混了,很抱歉。我会把它改成字符串+10。 - BigBadWolf
6
对于 std::string 对象,请使用 stol 函数。 - Some programmer dude
显示剩余3条评论
6个回答

4
使用 c_str() 方法。
strtol(string.c_str() + 10, NULL, 10);

@Mgetz,你看到这个问题了吗?“在C语言中,我可以使用strtol(string + 10, NULL, 10)”。 - Jonathan Wakely

2

虽然 stol 本身不支持你想要的功能,但我认为可以与 substr 结合使用来获得所需结果:

std::string in = "ireallylike314";

// extract number and print it out multiplied by 2 to show we got a number
std::cout << 2 * stol(in.substr(11));

结果:

628

这种方法有利有弊。不足之处在于,它创建了一个全新的字符串对象来保存输入字符串中的数字。而优点是,它可以更好地控制要转换的数字位数,因此,如果您只想从字符串中转换前两个数字(即使在本例中后面还有更多数字),也可以很容易地实现:

std::cout << 2 * stol(in.substr(11, 2));

结果:

62

在很多情况下,这对你来说是否切实可行很大程度上取决于你的实现是否包括短字符串优化。如果包括,创建一个(小)字符串通常足够便宜,使得这个过程完全合理。如果不包括,则从substr返回临时字符串对象需要堆分配,这可能是你不想承担的更高代价。


如果你查看代码,boost::string_ref 有一个 stol 的实现,它是通过调用 strtol 来保持安全性的。 - Mgetz

2
如果您想从std::string获取C风格的字符串,则可以使用上述提到的c_str()方法。但是,解决此特定问题的另一种解决方案只需要使用stol而不是strtol即可。

stol无法工作,因为它不能直接处理字符串的中间部分。 - R. Martinho Fernandes
1
@R.MartinhoFernandes 我忘了,但是你可以使用 substr 方法获取字符串的中间部分。 - user4180612

1

类C语言的方式:

long n = std::strtol( string.c_str() + offset, nullptr, 10 );
// sets ERRNO on error and returns value by saturating arithmetic.

Java式的方法:

long n = std::stol( string.substr( offset, std::string::npos ) );
// exception (no return value) and perhaps ERRNO is set on error.

流式编程方式:

long n = 0;
std::istringstream( string ).ignore( offset ) >> n;
// n is unmodified on error

本地化的方式:

long n = 0;
std::ios_base fmt; // Use default formatting: base-10 only.
std::ios::iostate err = {};
std::num_get< char, std::string::iterator >()
            .get( string.begin() + offset, string.end(), fmt, err, n );
// err is set to std::ios::failbit on error

0
字符串已经不再是以前的样子了,也就是说,不再只是带着终止符'\0 '的字符数组。
你错了。在C++中,字符串的定义方式是相同的。在这两种语言中,字符串的定义方式都是:
一个字符串是由一系列相邻字符组成的,包括第一个空字符(\0)。
你将字符串与类std::string(或std::basic_string)混淆了,它们并不相同。
例如:如果我知道某个字符串中有一个数字,在这个字符串ireallylike314中,我可以使用C中的strtol(string[10], NULL, 10)来获取那个数字
你错了。这个有效的函数调用看起来将是:
strtol( &string[11], NULL, 10)

或者

strtol( string + 11, NULL, 10)

你可以使用成员函数c_str()或(从C ++ 2011开始)data()调用相同的函数,以处理std::string类的对象。

例如:

std::string s( "ireallylike314" );

auto x = std::strtol( s.c_str() + 11, NULL, 10 );

或者

auto x = std::strtol( s.data() + 11, NULL, 10 );

2
他并没有“错”。显然,std::stringchar[N]之间存在很大的区别,尽管后者与前者的部分实现相似。 - Lightness Races in Orbit
@Lightness Races in Orbit Class std::string(或std::basic_string)和字符串的概念是不同的东西。 - Vlad from Moscow

0

这可能超出了问题的范围,但由于您正在迁移到C++并且似乎对std::string感到困惑,您可能会发现以下内容有用。

拥有std::string的重点不是像使用C-Strings一样(当然你可以这样做,就像之前的答案所示)。您可以利用std::string的许多优势。例如,它是一个C++容器,有函数可用于获取子字符串、比较字符串等等...

与C-Strings相比,使用std::string进行字符串操作通常更加容易。

例如,查看http://www.cplusplus.com/reference/string/string/以了解其功能。


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