您的位置:首页 > 编程语言 > C语言/C++

用C++的string::size()和string::length()返回值做比较

2016-03-16 14:17 453 查看
楼主今天在自己实现kmp算法的c++代码时,发现了一个问题。我先把代码贴上来。

//kmp search
#include <iostream>
#include <vector>
using namespace std;

vector<int> GetNext(string pattern)
{
vector<int> next(pattern.size(), -1);
int i = 0;
int j = -1;
while(i < pattern.size())
{
if(j == -1 || pattern[i] == pattern[j])
{
i++;
j++;
if(pattern[i] != pattern[j])
next[i] = j;
else
next[i] = next[j];
}
else
{
j = next[j];
}
}
return next;
}

int KmpSearch(string text, string pattern)
{
if(text.size() <= 0 || pattern.size() <= 0)
return -1;
vector<int> next = GetNext(pattern);
int i = 0;
int j = 0;
int slen = text.size();
int plen = pattern.size();
while(i < slen && j < plen)//while(i < text.size() && j < pattern.size())
{
if(j == -1 || text[i] == pattern[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if(j == pattern.size())
return i-j;
return -1;
}

int main(int argc, char const *argv[])
{
string txt = "BBCAAAAB ABCDAB ABCDABCDABDE";
string pat = "ABCDABD";
cout << "index = " << KmpSearch(txt, pat) << endl;
return 0;
}


请注意第39行,我原来写的循环条件是如注释一样的。后来发现无论如何循环都只跑一遍,然后就退出了,不能得到正确的结果,思前想后都不知道到底是哪里出了问题。然后才将
text.size()
替换成了一个
signed int
型的数字,这才解决了问题。

这个时候我就猜可能是
string::size()
的返回值的问题,跑去cpp reference string::size()查看,赫然发现这样一句话:

The number of bytes in the string.

size_t is an unsigned integral type (the same as member type string::size_type).

瞬间明白了:
string::size()
返回的是一个无符号的整数。

并由此推导出:当它的返回值和一个有符号数比较时,有符号数会被隐式转换成无符号数。(不是取绝对值,而是对将最高为(MSB)当成数字处理,不再表示符号)

KMP算法里,游标j可能为-1,因此当判断条件
j < text.size()
中的j为-1时,它的二进制补码为0xFFFFFFFF,而作为无符号数它被转化为了4294967295,因此没有按我本来的意思执行。

我做的实验如下:

//test for string::size() and string::length()
#include <iostream>

int main(int argc, char const *argv[])
{
string test("abcd");
int slen = test.size();
int llen = test.length();

signed int i = -1;
unsigned int K = 4294967295;
int minus_one = 0xFFFFFFFF;
cout << minus_one << endl;
cout << 0xFFFFFFFF << endl;

if(K >= i)
cout << "K > i true" << endl;
else
cout << "K > i false" << endl;

if(test.size() > i)
cout << "test.size() > i true" << endl;
else
cout << "test.size() > i false" << endl;

if(slen > 0)
cout << "slen > 0 true" << endl;
else
cout << "slen > 0 false" << endl;
if(llen > 0)
cout << "llen > 0 true" << endl;
else
cout << "llen > 0 false" << endl;
if(slen > -1)
cout << "slen > -1 true" << endl;
else
cout << "slen > -1 false" << endl;
if(llen > -1)
cout << "llen > -1 true" << endl;
else
cout << "llen > -1 false" << endl;

if(test.size() > 0)
cout << "test.size() > 0 true" << endl;
else
cout << "test.size() > 0 false" << endl;
if(test.length() > 0)
cout << "test.length() > 0 true" << endl;
else
cout << "test.length() > 0 false" << endl;

//pay attention to the following lines
if(test.size() > -1)
cout << "test.size() > -1 true" << endl;
else
cout << "test.size() > -1 false" << endl;
if(test.length() > -1)
cout << "test.length() > -1 true" << endl;
else
cout << "test.length() > -1 false" << endl;
return 0;
}


打印的内容也充分地说明了这一点,同时还说明了
string::length()
的行为与
string::size()
是完全相同的。

-1

4294967295

K > i true

test.size() > i false

slen > 0 true

llen > 0 true

slen > -1 true

llen > -1 true

test.size() > 0 true

test.length() > 0 true

test.size() > -1 false

test.length() > -1 false

提醒自己:不要将string类型的size()和length()方法的返回值直接用来比较,可能会产生预计之外的情况
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: