欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++程序员应了解的那些事(31)关于string::npos的用法

程序员文章站 2022-07-12 22:48:37
...

【一】关于npos的定义

//basic_string.h
static const size_type	npos = static_cast<size_type>(-1);
//basic_string.tcc
template<typename _CharT, typename _Traits, typename _Alloc>
    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
    basic_string<_CharT, _Traits, _Alloc>::npos;

The constant is the largest representable value of type size_type. It is assuredly larger than max_size(); hence it serves as  either a very large value or as a special code.

       以上的意思是npos是一个常数,表示size_t的最大值(Maximum value for size_t)。许多容器都提供这个东西,用来表示不存在的位置,类型一般是std::container_type::size_type。

#include <iostream>    
#include <limits>    
#include <string>    
using namespace std;    
    
int main()    
{    
    size_t npos = -1;    
    cout << "npos: " << npos << endl;    
    cout << "size_t max: " << numeric_limits<size_t>::max() << endl;  
}
输出:
npos:   4294967295
size_t max:  4294967295
//可见他们是相等的,也就是说npos表示size_t的最大值

【二】npos的用法

(1)npos可以表示string的结束位置,是string::size_type 类型的,也就是find()返回的类型。find函数在找不到指定值得情况下会返回string::npos。

<示例>
#include <string>  
#include <iostream>  
using namespace std; 
int main()  
{  
    string name("Annaqijiashe");  
    int pos=name.find("Anna");  
    //要修改为string::size_type pos=name.find("Anna");  
    if(pos==string::npos)       
    cout<<"Anna not found!\n";  
    else  cout<<"Anna found at pos:"<<pos<<endl;  
}
输出:
Anna found at pos:0

(2)string::npos作为string的成员函数的一个长度参数时,表示“直到字符串结束(until the end of the string)”

<说明>
tmpname.replace(idx+1, string::npos, suffix);  
这里的string::npos就是一个长度参数,表示直到字符串的结束,配合idx+1表示,string的剩余部分。
<示例>
#include <iostream>    
#include <limits>    
#include <string>    
using namespace std;    
int main()    
{    
    string filename = "test.cpp";    
    cout << "filename : " << filename << endl;    
    
    size_t idx = filename.find('.');   
   // 修改为 string::size_type idx = filename.find('.');   
    if(idx == string::npos)        
    {    
        cout << "filename does not contain any period!" << endl;    
    }    
    else    
    {    
        string tmpname = filename;    
        tmpname.replace(idx + 1, string::npos, "xxx"); //string::npos作为长度参数,表示直到字符串结束    
        cout << "repalce: " << tmpname << endl;    
    }    
}
输出:
filename:test.cpp
replace: test.xxx

【三】Tips:需要注意npos的类型

int idx = str.find("abc");  
if (idx == string::npos)  

        上述代码中,idx的类型被定义为int,这是错误的,即使定义为 unsigned int 也是错的,它必须定义string::size_type(所以上面的两个示例代码是有问题的)。因为 string::size_type (由字符串配置器 allocator 定义) 描述的是 size,故需为无符号整数型别。因为缺省配置器以型别 size_t 作为 size_type,于是 -1 被转换为无符号整数型别,npos 也就成了该型别的最大无符号值。不过实际数值还是取决于型别 size_type 的实际定义。不幸的是这些最大值都不相同。事实上(unsigned long)-1 和 (unsigned short)-1 不同(前提是两者型别大小不同)。因此,比较式 idx == string::npos 中,如果 idx 的值为-1,由于 idx 和字符串string::npos 型别不同,比较结果可能得到 false。

要想判断 find() 的结果是否为npos,最好的办法是直接比较:
if (str.find("abc") == string::npos)
{ ... }

       ※string类提供了 6 种查找函数,每种函数以不同形式的 find 命名。这些操作全都返回 string::size_type 类型的值,以下标形式标记查找匹配所发生的位置;或者返回一个名为 string::npos 的特殊值,说明查找没有匹配。string 类将 npos 定义为保证大于任何有效下标的值。

相关标签: 程序员应知应会