C 和 C++字符串详解

From:http://blog.csdn.net/fenxinzi557/article/details/51457829

From:http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html

C++之string类型详解:http://citycowboy.blog.sohu.com/50058804.html


----------------------------------------------------------------------------





CPP 字符串



        之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至是100%)的需要。我们可以用 = 进行赋值操作,== 进行比较,+ 做串联(是不是很简单?)。我们尽可以把它看成是C++的基本数据类型。
        MFC中的CString类使用起来真的非常的方便好用。但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯定的。也许有人会说,即使不用MFC框架,也可以想办法使用MFC中的API,具体的操作方法在本文最后给出操作方法。其实,可能很多人很可能会忽略掉标准C++中string类的使用。标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用。

要想使用标准C++中string类,必须要包含:

#include <string>// 注意是<string>,不是<string.h>,带.h的是C语言中的头文件
using std::string;
using std::wstring;
或
using namespace std;

下面你就可以使用 string/wstring了,它们两分别对应着char和wchar_t。string 和 wstring 的用法是一样的。

以下只用string作介绍:



1. 声明一个C++字符串


声明一个字符串变量很简单:string Str;
这样我们就声明了一个字符串变量,但既然是一个类,就有构造函数和析构函数。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把Str初始化为一个空字符串。



2. String类的构造函数和析构函数


string(const char *s);  // 用c字符串s初始化
string(int n,char c);   // 用n个字符c初始化
                 // string类还支持默认构造函数和拷贝构造函数,如string s1; string s2="hello";

string s;             // 生成一个空字符串s
string s(str)         // 拷贝构造函数 生成str的复制品
string s(str,stridx)  //将字符串str内“始于位置stridx”的部分当作字符串的初值
string s(str,stridx,strlen) // 将字符串str内“始于stridx且长度顶多strlen”的部分作为字符串的初值
string s(cstr)              // 将C字符串作为s的初值
string s(chars,chars_len)   // 将C字符串前chars_len个字符作为字符串s的初值。
string s(num,c)             // 生成一个字符串,包含num个c字符
string s(beg,end)           // 以区间beg;end(不包含end)内的字符作为字符串s的初值
s.~string()                 // 销毁所有字符,释放内存

测试如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1 = "yesterday once more";
    string str2 ("my heart go on");
    string str3 (str1,6); // = day once more
    string str4 (str1,6,3); // = day
    
    char ch_music[] = {"Roly-Poly"};
    
    string str5 = ch_music; // = Roly-Poly 
    string str6 (ch_music); // = Roly-Poly
    string str7 (ch_music,4); // = Roly
    string str8 (10,'i'); // = iiiiiiii
    string str9 (ch_music+5, ch_music+9); // = Poly
    
    str9.~string();
    
    //cout<<str9<<endl; // 测试输出
    
    getchar();
    return 0;
}



3. 字符串操作函数


这里是C++字符串的重点,先把各种操作函数罗列出来。

a) =,assign()                 // 赋以新值
b) swap()                     // 交换两个字符串的内容
c) +=,append(),push_back()    // 在尾部添加字符
d) insert()                   // 插入字符
e) erase()                    // 删除字符
f) clear()                    // 删除全部字符
g) replace()                  // 替换字符
h) +                          // 串联字符串
i) ==,!=,<,<=,>,>=,compare()  // 比较字符串
j) size(),length()            // 返回字符数量
k) max_size()                 // 返回字符的可能最大个数
l) empty()                    // 判断字符串是否为空
m) capacity()                 // 返回重新分配之前的字符容量
n) reserve()                  // 保留一定量内存以容纳一定数量的字符
o) [ ], at()                  // 存取单一字符
p) >>,getline()               // 从stream读取某值
q) <<                         // 将谋值写入stream
r) copy()                     // 将某值赋值为一个C_string
s) c_str()                    // 将内容以C_string返回
t) data()                     // 将内容以字符数组形式返回
u) substr()                   // 返回某个子字符串
v)                  查找系列函数 
w) begin() end()              // 提供类似STL的迭代器支持
x) rbegin() rend()            // 逆向迭代器
y) get_allocator()            // 返回配置器

使用示例代码:

# include <iostream>
# include <string>
using namespace std;
int main()
{
    string str1 = "yesterday once more";
    string str2 ("my heart go on");
    str2.swap(str1);
    cout<<str1<<endl;  // = my heart go on
    cout<<str2<<endl;  // = yesterday once more
	
    string str3,str4;
    str3.assign(str2,3,6);            // = heart
    str4.assign(str2,3,string::npos); // = heart go on (从2开始到结尾赋给str4)
    str4.assign("gaint");             // =gaint
    str4.assign("nico",5);            // = nico,超出长度会发生什么。。。
    str4.assign(5,'x');               // = xxxxx
    cout<<str4<<endl;
    getchar();
    return 0;	
}


string的赋值

string &operator=(const string &s);     // 把字符串s赋给当前字符串
string &assign(const char *s);          // 用c类型字符串s赋值
string &assign(const char *s,int n);    // 用c字符串s开始的n个字符赋值
string &assign(const string &s);        // 把字符串s赋给当前字符串
string &assign(int n,char c);           // 用n个字符c赋值给当前字符串
string &assign(const string &s,int start,int n);          // 把字符串s中从start开始的n个字符赋给当前字符串
string &assign(const_iterator first,const_itertor last);  // 把first和last迭代器之间的部分赋给字符串


string的连接

string &operator+=(const string &s);      // 把字符串s连接到当前字符串的结尾 
string &append(const char *s);            // 把c类型字符串s连接到当前字符串结尾
string &append(const char *s,int n);      // 把c类型字符串s的前n个字符连接到当前字符串结尾
string &append(const string &s);          // 同operator+=()
string &append(const string &s,int pos,int n);  // 把字符串s中从pos开始的n个字符连接到当前字符串的结尾
string &append(int n,char c);                   // 在当前字符串结尾添加n个字符c
string &append(const_iterator first,const_iterator last);  // 把迭代器first和last之间的部分连接到当前字符串的结尾


string的比较

bool operator==(const string &s1,const string &s2)const;  // 比较两个字符串是否相等
                                                          // 运算符">","<",">=","<=","!="均被重载用于字符串的比较;
int compare(const string &s) const;                 // 比较当前字符串和s的大小
int compare(int pos, int n,const string &s)const;   //  比较当前字符串从pos开始的n个字符组成的字符串与s的大小
int compare(int pos, int n,const string &s,int pos2,int n2)const;  // 比较当前字符串从pos开始的n个字符组成的字符串与s中
                                  // pos2开始的n2个字符组成的字符串的大小
int compare(const char *s) const;
int compare(int pos, int n,const char *s) const;
int compare(int pos, int n,const char *s, int pos2) const;
compare函数在>时返回1,<时返回-1,==时返回0  


string的子串

string substr(int pos = 0,int n = npos) const;  // 返回pos开始的n个字符组成的字符串


string的交换

void swap(string &s2); // 交换当前字符串与s2的值


string类的查找函数

特别注意:
find_first_of 函数最容易出错的地方是和find函数搞混。它最大的区别就是如果在一个字符串str1中查找另一个字符串str2,如果str1中含有str2中的任何字符,则就会查找成功,而find则不同;

比如:

string str1("I am change");
string str2("about");
int k=str1.find_first_of(str2); //k返回的值是about这5个字符中任何一个首次在str1中出现的位置;

查找函数列表:

int find(char c, int pos = 0) const;           // 从pos开始查找字符c在当前字符串的位置
int find(const char *s, int pos = 0) const;    // 从pos开始查找字符串s在当前串中的位置
int find(const char *s, int pos, int n) const; // 从pos开始查找字符串s中前n个字符在当前串中的位置
int find(const string &s, int pos = 0) const;  // 从pos开始查找字符串s在当前串中的位置
                                                  // 查找成功时返回所在位置,失败返回string::npos的值 
int rfind(char c, int pos = npos) const;       // 从pos开始从后向前查找字符c在当前串中的位置
int rfind(const char *s, int pos = npos) const;
int rfind(const char *s, int pos, int n = npos) const;
int rfind(const string &s,int pos = npos) const;    //从pos开始从后向前查找字符串s中前n个字符组成的字符串在当前串中的位置,
                                                    //成功返回所在位置,失败时返回string::npos的值 
int find_first_of(char c, int pos = 0) const;           //从pos开始查找字符c第一次出现的位置
int find_first_of(const char *s, int pos = 0) const;
int find_first_of(const char *s, int pos, int n) const;
int find_first_of(const string &s,int pos = 0) const; //从pos开始查找当前串中第一个在s的前n个字符组成的数组里的字符的位置。
                                                      //查找失败返回string::npos 
int find_first_not_of(char c, int pos = 0) const;
int find_first_not_of(const char *s, int pos = 0) const;
int find_first_not_of(const char *s, int pos,int n) const;
int find_first_not_of(const string &s,int pos = 0) const;  //从当前串中查找第一个不在串s中的字符出现的位置,
                                                           //失败返回string::npos 
int find_last_of(char c, int pos = npos) const;
int find_last_of(const char *s, int pos = npos) const;
int find_last_of(const char *s, int pos, int n = npos) const;
int find_last_of(const string &s,int pos = npos) const; 
int find_last_not_of(char c, int pos = npos) const;
int find_last_not_of(const char *s, int pos = npos) const;
int find_last_not_of(const char *s, int pos, int n) const;
int find_last_not_of(const string &s,int pos = npos) const;

//find_last_of和find_last_not_of与find_first_of和find_first_not_of相似,只不过是从后向前查找


查找字符串a是否包含子串b
不是用 strA.find(strB) > 0 而是 strA.find(strB) != string:npos
string::size_type pos = strA.find(strB);
if(pos != string::npos){}
-------------------------------------------
int idx = str.find("abc");
if (idx == string::npos)
...
上述代码中,idx的类型被定义为int,这是错误的,即使定义为 unsigned int 也是错的,它必须定义为 string::size_type。
npos 是这样定义的: static const size_type npos = -1;
因为 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) { ... }
错误:if(str.find("abc") ) 
注:找不到abc会返回-1,不为0为True。0为False 

---------------------------------------------------------------------------------------------------------

使用示例代码:

find 函数 返回类型 size_type
string s("1a2b3c4d5e6f7g8h9i1a2b3c4d5e6f7g8ha9i");
string flag;
string::size_type position;

//find 函数 返回jk 在s 中的下标位置 
position = s.find("jk");
if (position != s.npos)  //如果没找到,返回一个特别的标志c++中用npos表示,我这里npos取值是4294967295,
{
    cout << "position is : " << position << endl;
}
else
{
    cout << "Not found the flag" + flag;
} 

//find 函数 返回flag 中任意字符 在s 中第一次出现的下标位置
flag = "c";
position = s.find_first_of(flag);
cout << "s.find_first_of(flag) is : " << position << endl;

//从字符串s 下标5开始,查找字符串b ,返回b 在s 中的下标
position=s.find("b",5);
cout<<"s.find(b,5) is : "<<position<<endl;

//查找s 中flag 出现的所有位置。
flag="a";
position=0;
int i=1;
while((position=s.find_first_of(flag,position))!=string::npos)
{
    //position=s.find_first_of(flag,position);
    cout<<"position  "<<i<<" : "<<position<<endl;
    position++;
    i++;
}

//查找flag 中与s 第一个不匹配的位置
flag="acb12389efgxyz789";
position=flag.find_first_not_of (s);
cout<<"flag.find_first_not_of (s) :"<<position<<endl;

//反向查找,flag 在s 中最后出现的位置
flag="3";
position=s.rfind (flag);
cout<<"s.rfind (flag) :"<<position<<endl;

说明:

  • 1. 如果string sub = ”abc“;string s = ”cdeabcigld“;s.find(sub) , s.rfind(sub) 这两个函数如果完全匹配才返回匹配的索引,即:当s中含有abc三个连续的字母时才返回当前索引。s.find_first_of(sub), s.find_first_not_of(sub), s.find_last_of(sub), s.find_last_not_of(sub) 这四个函数,查找s中含有sub中任意字母的索引。
  • 2. 如果没有查询到,则返回string::npos,这是一个很大的数,其值不需要知道。


string类的替换函数

string &replace(int p0, int n0,const char *s);       // 删除从p0开始的n0个字符,然后在p0处插入串s
string &replace(int p0, int n0,const char *s, int n);// 删除p0开始的n0个字符,然后在p0处插入字符串s的前n个字符
string &replace(int p0, int n0,const string &s);     // 删除从p0开始的n0个字符,然后在p0处插入串s
string &replace(int p0, int n0,const string &s, int pos, int n);  // 删除p0开始的n0个字符,然后在p0处插入串s中从pos开始的n个字符
string &replace(int p0, int n0,int n, char c);                    // 删除p0开始的n0个字符,然后在p0处插入n个字符c
string &replace(iterator first0, iterator last0,const char *s);   // 把[first0,last0)之间的部分替换为字符串s
string &replace(iterator first0, iterator last0,const char *s, int n);  // 把[first0,last0)之间的部分替换为s的前n个字符
string &replace(iterator first0, iterator last0,const string &s);       // 把[first0,last0)之间的部分替换为串s
string &replace(iterator first0, iterator last0,int n, char c);         // 把[first0,last0)之间的部分替换为n个字符c
string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[first,last)之间的字符串


string类的插入函数

string &insert(int p0, const char *s);
string &insert(int p0, const char *s, int n);
string &insert(int p0,const string &s);
string &insert(int p0,const string &s, int pos, int n);
//前4个函数在p0位置插入字符串s中pos开始的前n个字符
string &insert(int p0, int n, char c);      // 此函数在p0处插入n个字符c
iterator insert(iterator it, char c);       // 在it处插入字符c,返回插入后迭代器的位置
void insert(iterator it, const_iterator first, const_iterator last);  // 在it处插入[first,last)之间的字符
void insert(iterator it, int n, char c);    // 在it处插入n个字符c


string类的删除函数

iterator erase(iterator first, iterator last);  // 删除[first,last)之间的所有字符,返回删除后迭代器的位置
iterator erase(iterator it);                    // 删除it指向的字符,返回删除后迭代器的位置
string &erase(int pos = 0, int n = npos);       // 删除pos开始的n个字符,返回修改后的字符串


string类的迭代器处理

string类提供了向前和向后遍历的迭代器iterator,迭代器提供了访问各个字符的语法,类似于指针操作,迭代器不检查范围。
用string::iterator或string::const_iterator声明迭代器变量,const_iterator不允许改变迭代的内容。
常用迭代器函数有:
const_iterator begin()const;
iterator begin();                // 返回string的起始位置
const_iterator end()const;
iterator end();                  // 返回string的最后一个字符后面的位置
const_iterator rbegin()const;
iterator rbegin();               // 返回string的最后一个字符的位置
const_iterator rend()const;
iterator rend();                 // 返回string第一个字符位置的前面
rbegin和rend用于从后向前的迭代访问,通过设置迭代器string::reverse_iterator,string::const_reverse_iterator实现


string类的字符操作

const char &operator[](int n)const;
const char &at(int n)const;
char &operator[](int n);
char &at(int n);

operator[]和at()均返回当前字符串中第n个字符的位置,
但at函数提供范围检查,当越界时会抛出out_of_range异常,下标运算符[]不提供检查访问。

const char *data()const;     //返回一个非null终止的c字符数组
const char *c_str()const;    //返回一个以null终止的c字符串
int copy(char *s, int n, int pos = 0) const;//把当前串中以pos开始的n个字符拷贝到以s为起始位置的字符数组中,返回实际拷贝的数目


string的特性描述

int capacity()const;     // 返回当前容量(即string中不必增加内存即可存放的元素个数)
int max_size()const;     // 返回string对象中可存放的最大字符串的长度
int size()const;         // 返回当前字符串的大小
int length()const;       // 返回当前字符串的长度
bool empty()const;           // 当前字符串是否为空
void resize(int len,char c); // 把字符串当前大小置为len,并用字符c填充不足的部分


string类的输入输出操作

string类重载运算符operator>>用于输入,同样重载运算符operator<<用于输出操作。
函数getline(istream &in,string &s);用于从输入流in中读取字符串到s中,以换行符'\n'分开。


字符串流处理

通过定义ostringstream和istringstream变量实现,在#include <sstream>头文件中

string input("hello,this is a test");
istringstream is(input);
string s1,s2,s3,s4;
is>>s1>>s2>>s3>>s4; //s1="hello,this",s2="is",s3="a",s4="test"
ostringstream os;
os<<s1<<s2<<s3<<s4;
cout<<os.str();

示例代码:

#include <iostream>  
#include "string"  

using namespace std;  

//字符串初始化  
void strInit()  
{  
    cout << "字符串初始化:"  <<endl;  
    
    string s1 = "abcdefg";  //初始化方式1  
    string s2("abcdefg");   //初始化方式2  
    string s3 = s2;         //通过拷贝构造函数 初始化s3  
    string s4(7,'s');       //初始化7个s的字符串  
    
    cout << "s1 = "<< s1 << endl;  
    cout << "s2 = "<< s2 << endl;  
    cout << "s3 = "<< s3 << endl;  
    cout << "s4 = "<< s4 << endl;  
}  

//字符串遍历  
void strErgo()  
{  
    cout << "字符串遍历:"  <<endl;  
    
    string s1 = "abcdefg";  //初始化字符串  
    
    //通过数组方式遍历  
    cout << "1、通过数组方式遍历:"  <<endl;  
    for (int i = 0; i < s1.length(); i++)  
    {  
        cout << s1[i] << " ";  
    }  
    cout << endl;  
    
    //通过迭代器遍历  
    cout << "2、通过迭代器遍历:"  <<endl;  
    for(string::iterator it = s1.begin(); it!= s1.end(); it++)  
    {  
        cout << *it << " ";  
    }  
    cout << endl;  
    
    //通过at()方式遍历  
    cout << "3、通过at()方式遍历:"  <<endl;  
    for (int i = 0; i < s1.length(); i++)  
    {  
        cout << s1.at(i) << " ";        //此方式可以在越界时抛出异常  
    }  
    cout << endl;  
}  

//字符指针和字符串的转换  
void strConvert()  
{  
    cout << "字符指针和字符串的转换:"  <<endl;  
    string s1 = "abcdefg";  //初始化字符串  
    
    cout << "string转换为char*:"  <<endl;  
    //string转换为char*  
    cout << s1.c_str() <<endl;  //s1.c_str()即为s1的char *形式  
    
    cout << "char*获取string内容:"  <<endl;  
    //char*获取string内容  
    char buf[64] = {0};  
    s1.copy(buf, 7);//复制7个元素  
    cout << buf <<endl;  
}  

//字符串连接  
void strAdd()  
{  
    cout << "字符串连接:"  <<endl;  
    
    cout << "方式1:"  <<endl;  
    string s1 = "123";  
    string s2 = "456";  
    s1 += s2;  
    cout << "s1 = "<< s1 << endl;  
    
    cout << "方式2:"  <<endl;  
    string s3 = "123";  
    string s4 = "456";  
    s3.append(s4);  
    cout << "s3 = "<< s3 << endl;  
}  
int main()  
{  
    //初始化  
    strInit();  
    cout << endl;  
    //遍历  
    strErgo();  
    cout << endl;  
    //字符指针类型和字符串转换  
    strConvert();  
    cout << endl;  
    //字符串连接  
    strAdd();  
    cout << endl;  
    system("pause");  
    return 0;  
}  



4. 下面详细字符串操作函数


C++字符串和C字符串的转换

C ++ 提供的由 C++ 字符串 得到对应的 C_string 的方法是使用 data()、c_str() 和 copy(),其中,data() 以字符数组的形式返回字符串内容,但并不添加’\0’。c_str() 返回一个以‘\0’结尾的字符数组,而 copy() 则把字符串的内容复制或写入既有的c_string或字符数组内。C++字符串并不以’\0’结尾。我的建议是在程序中能使用C++ 字符串就使用,除非万不得已不选用 c_string。


大小和容量函数

一个C++字符串存在三种大小:

a)现有的字符数,函数是size()和length(),他们等效。Empty()用来检查字符串是否为空。

b)max_size() 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。我们一般情况下不用关心他,应该大小足够我们用的。但是不够用的话,会抛出length_error异常c)capacity()重新分配内存之前 string所能包含的最大字符数。这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

还有必要再重复一下C++字符串和C字符串转换的问题,许多人会遇到这样的问题,自己做的程序要调用别人的函数、类什么的(比如数据库连接函数Connect(char*,char*)),但别人的函数参数用的是char*形式的,而我们知道,c_str()、data()返回的字符数组由该字符串拥有,所以是一种const char*,要想作为上面提及的函数的参数,还必须拷贝到一个char*,而我们的原则是能不使用C字符串就不使用。那么,这时候我们的处理方式是:如果此函数对参数(也就是char*)的内容不修改的话,我们可以这样Connect((char*)UserID.c_str(), (char*)PassWD.c_str()),但是这时候是存在危险的,因为这样转换后的字符串其实是可以修改的(有兴趣地可以自己试一试),所以我强调除非函数调用的时候不对参数进行修改,否则必须拷贝到一个char*上去。

当然,更稳妥的办法是无论什么情况都拷贝到一个char*上去。同时我们也祈祷现在仍然使用C字符串进行编程的高手们(说他们是高手一点儿也不为过,也许在我们还穿开裆裤的时候他们就开始编程了,哈哈…)写的函数都比较规范,那样我们就不必进行强制转换了。


元素存取

        我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。但是应该注意的是操作符[]并不检查索引是否有效(有效索引0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用 at()的时候索引无效,会抛出out_of_range异常。

        有一个例外不得不说,const string a;的操作符[]对索引值是a.length()仍然有效,其返回值是’\0’。其他的各种情况,a.length()索引都是无效的。

举例如下:

const string Cstr(“const string”);
string Str(“string”);
Str[3];                  // ok
Str.at(3);               // ok
Str[100];                // 未定义的行为
Str.at(100);             // throw out_of_range
Str[Str.length()]        // 未定义行为
Cstr[Cstr.length()]      // 返回 ‘\0’
Str.at(Str.length());    // throw out_of_range
Cstr.at(Cstr.length())   // throw out_of_range
string str1 = "Iphone 5";
cout<<str1[2]<<endl;      // = h
cout<<str1.at(4)<<endl;   // = n

string stuff;
getline(cin,stuff);       // 输入一行字符赋值给stuff
getline(cin,stuff,'!');   // 输入一行字符以“!”结束
cout<<stuff<<endl;

不赞成类似于下面的引用或指针赋值:
char& r=s[2];
char* p= &s[3];
因为一旦发生重新分配,r,p立即失效。避免的方法就是不使用。


比较函数

        C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<”hello”)。在使用>,>=,<,<=这些操作符的时候是根据“当前字符特性”将字符按字典顺序进行逐一得比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。同时,string (“aaaa”) <string(aaaaa)。
        另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等〉0-大于 <0-小于。

举例如下:

string s(“abcd”);
s.compare(“abcd”);      // 返回0
s.compare(“dcba”);      // 返回一个小于0的值
s.compare(“ab”);        // 返回大于0的值
s.compare(s);             // 相等
s.compare(0,2,s,2,2);     // 用”ab”和”cd”进行比较小于零
s.compare(1,2,”bcx”,2); // 用”bc”和”bc”比较。
也可以使用STL的比较算法。


更改字符串内容

这在字符串的操作中占了很大一部分。
首先讲赋值,第一个赋值方法当然是使用操作符=,新值可以是string(如:s=ns) 、c_string(如:s=”gaint”)甚至单一字符(如:s=’j’)。还可以使用成员函数assign(),这个成员函数可以使你更灵活的对字符串赋值。

举例如下:

s.assign(str);                  // 不说
s.assign(str,1,3);              // 如果str是”iamangel” 就是把”ama”赋给字符串
s.assign(str,2,string::npos);   // 把字符串str从索引值2开始到结尾赋给s
s.assign(“gaint”);            // 不说
s.assign(“nico”,5);           // 把’n’ ‘I’ ‘c’ ‘o’ ‘\0’赋给字符串
s.assign(5,’x’);              // 把五个x赋给字符串
把字符串清空的方法有三个:s=””; s.clear(); s.erase();
string提供了很多函数用于插入(insert)、删除(erase)、替换(replace)、增加字符。
先说增加字符(这里说的增加是在尾巴上),函数有 +=、append()、push_back()。

举例如下:

s+=str;                           // 加个字符串
s+=”my name is jiayp”;          // 加个C字符串
s+=’a’;                         // 加个字符
s.append(str);
s.append(str,1,3);                // 不解释了同前面的函数参数assign的解释
s.append(str,2,string::npos)      // 不解释了
s.append(“my name is jiayp”);
s.append(“nico”,5);
s.append(5,’x’);
s.push_back(‘a’);               // 这个函数只能增加单个字符对STL熟悉的理解起来很简单
也许你需要在string中间的某个位置插入字符串,这时候你可以用insert()函数,这个函数需要你指定一个安插位置的索引,被插入的字符串将放在这个索引的后面。
s.insert(0,”my name”);
s.insert(1,str);
这种形式的insert()函数不支持传入单个字符,这时的单个字符必须写成字符串形式(让人恶心)。既然你觉得恶心,那就不得不继续读下面一段话:为了插入单个字符,insert()函数提供了两个对插入单个字符操作的重载函数:insert(size_type index,size_type num,chart c)和insert(iterator pos,size_type num,chart c)。其中size_type是无符号整数,iterator是char*,所以,你这么调用insert函数是不行的:insert(0,1, ’j’);这时候第一个参数将转换成哪一个呢?所以你必须这么写:insert((string::size_type)0,1,’j’)!第二种形式指出了使用迭代器安插字符的形式,在后面会提及。顺便提一下,string有很多操作是使用STL的迭代器的,他也尽量做得和STL靠近。
删除函数erase()的形式也有好几种(真烦!),替换函数replace()也有好几个。

举例如下:

string s = "il8n";
s.replace(1,2,”nternationalizatio”); // 从索引1开始的2个替换成后面的C_string
s.erase(13);                           // 从索引13开始往后全删除
s.erase(7,5);                          // 从索引7开始往后删5个


提取子串和字符串连接

题取子串的函数是:substr(),形式如下:

s.substr();       // 返回s的全部内容
s.substr(11);     // 从索引11往后的子串
s.substr(5,6);    // 从索引5开始6个字符

把两个字符串结合起来的函数是+。


输入输出操作

  • 1. >> 从输入流读取一个string。
  • 2. << 把一个string写入输出流。

另一个函数就是getline(),他从输入流读取一行内容,直到遇到分行符或到了文件尾。


搜索与查找

查找函数很多,功能也很强大,包括了:

find()
rfind()
find_first_of()
find_last_of()
find_first_not_of()
find_last_not_of()

这些函数返回符合搜索条件的字符区间内的第一个字符的索引,没找到目标就返回npos。


所有的函数的参数说明如下:
第一个参数是被搜寻的对象。第二个参数(可有可无)指出string内的搜寻起点索引,第三个参数(可有可无)指出搜寻的字符个数。比较简单,不多说不理解的可以向我提出,我再仔细的解答。当然,更加强大的STL搜寻在后面会有提及。
最后再说说npos的含义,string::npos的类型是string::size_type,所以,一旦需要把一个索引与npos相比,这个索引值必须是string::size_type类型的,更多的情况下,我们可以直接把函数和npos进行比较(如:if(s.find(“jia”)== string::npos))。

使用示例代码:

# include <iostream>
# include <string>

using namespace std;
int main()
{
    string str = "when i was young, i listen to radio.";
    string::size_type position;

    position  = str.find("listen");

    if (position != str.npos) //npos是个很大的数,如果没找到就会返回npos的值给position
    {
        cout<<"第一次出现的下标是:"<<position<<endl;
    }

    //从字符串下标9开始,查找字符串you,返回you 在str中的下标
    position = str.find("you",9);
    cout<<"str.find("you",9")is:"<<position<<endl;

    //查找子串出现的所有位置
    string substr = "i";
    position = 0;
    int i = 1;
    while((position = str.find_first_of(substr,position)) != string::npos)
    {
        cout<<"position "<<i++<<position<<endl;
        position++;
    }

    //反向查找子串在str中最后出现的位置
    string flag = "to";
    position = str.rfind(flag);
    cout<<"str.rfind(flag):"<<position<<endl;
    getchar();
    return 0;
}


begin() end()    //提供类似STL的迭代器支持

# include <iostream>
# include <string>
# include <algorithm>
using namespace std;
int main()
{
    string str;
    
    str.push_back('Q');
    str.push_back('A');
    
    sort(str.begin(),str.end());
    string::iterator itstr = str.begin();
    
    for ( ; itstr != str.end(); itstr++)
    {
        cout<<*itstr;
    } 
    
    //str.pop_back();
    
    getchar();
    return 0; //输出AQ
}

rbegin() rend()     // 逆向迭代器
get_allocator()     // 返回配置器



string 函数列表


函数名

描述

begin

得到指向字符串开头的Iterator

end

得到指向字符串结尾的Iterator

rbegin

得到指向反向字符串开头的Iterator

rend

得到指向反向字符串结尾的Iterator

size

得到字符串的大小

length

size函数功能相同

max_size

字符串可能的最大大小

capacity

在不重新分配内存的情况下,字符串可能的大小

empty

判断是否为空

operator[]

取第几个元素,相当于数组

c_str

取得C风格的const char*字符串

data

取得字符串内容地址

operator=

赋值操作符

reserve

预留空间

swap

交换函数

insert

插入字符

append

追加字符

push_back

追加字符

operator+=

+= 操作符

erase

删除字符串

clear

清空字符容器中所有内容

resize

重新分配空间

assign

和赋值操作符一样

replace

替代

copy

字符串到空间

find

查找

rfind

反向查找

find_first_of

查找包含子串中的任何字符,返回第一个位置

find_first_not_of

查找不包含子串中的任何字符,返回第一个位置

find_last_of

查找包含子串中的任何字符,返回最后一个位置

find_last_not_of

查找不包含子串中的任何字符,返回最后一个位置

substr

得到字串

compare

比较字符串

operator+

字符串链接

operator==

判断是否相等

operator!=

判断是否不等于

operator<

判断是否小于

operator>>

从输入流中读入字符串

operator<<

字符串写入输出流

getline

从输入流中读入一行






C 字符串



1. 字符串操作

strcpy(p, p1)        // 复制字符串 
strncpy(p, p1, n)    // 复制指定长度字符串 
strcat(p, p1)        // 附加字符串 
strncat(p, p1, n)    // 附加指定长度字符串 
strlen(p)            // 取字符串长度 
strcmp(p, p1)        // 比较字符串 
strcasecmp(const char* s1, const char* s2)            // 忽略大小写比较字符串
strncasecmp(const char* s1, const char* s2, size_t n) // 忽略大小写比较字符串
strncmp(p, p1, n)    // 比较指定长度字符串 
strchr(p, c)         // 在字符串中查找指定字符 
strrchr(p, c)        // 在字符串中反向查找 
strstr(p, p1)    // 查找字符串 
strpbrk(p, p1)   // 以目标字符串的所有字符作为集合,在当前字符串查找该集合的任一元素 
strspn(p, p1)    // 以目标字符串的所有字符作为集合,在当前字符串查找不属于该集合的任一元素的偏移 
strcspn(p, p1)   // 以目标字符串的所有字符作为集合,在当前字符串查找属于该集合的任一元素的偏移 
* 具有指定长度的字符串处理函数在已处理的字符串之后填补零结尾符 


2. 字符串到数值类型的转换 

strtod(p, ppend)          // 从字符串 p 中转换 double 类型数值,并将后续的字符串指针存储到 ppend 指向的 char* 类型存储。
strtol(p, ppend, base)    // 从字符串 p 中转换 long 类型整型数值,base 显式设置转换的整型进制,
         // 设置为 0 以根据特定格式判断所用进制,0x, 0X 前缀以解释为十六进制格式整型,0前缀以解释为八进制格式整型
atoi(p)     // 字符串转换到 int 整型 
atof(p)     // 字符串转换到 double 符点数 
atol(p)     // 字符串转换到 long 整型 


3. 字符检查

isalpha()     // 检查是否为字母字符 
isupper()     // 检查是否为大写字母字符 
islower()     // 检查是否为小写字母字符 
isdigit()     // 检查是否为数字 
isxdigit()    // 检查是否为十六进制数字表示的有效字符 
isspace()     // 检查是否为空格类型字符 
iscntrl()     // 检查是否为控制字符 
ispunct()     // 检查是否为标点符号 
isalnum()     // 检查是否为字母和数字 
isprint()     // 检查是否是可打印字符 
isgraph()     // 检查是否是图形字符,等效于 isalnum() | ispunct() 


4. 函数原型


strcpy 函数

原型:char * strcpy ( char * destination, const char * source )
功能:将字符串source拷贝到字符串destination中 

#include <iostream.h> 
#include <string.h> 
void main(void) 
{ 
    char str1[10] = { "TsinghuaOK"}; 
    char str2[10] = { "Computer"}; 
    cout <<strcpy(str1,str2)<<endl;   // 第二个字符串将覆盖掉第一个字符串的所有内容
}
运行结果:Computer 

注意:在定义数组时,字符数组1的字符串长度必须大于或等于字符串2的字符串长度。不能用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。所有字符串处理函数都包含在头文件string.h中。


strncpy 函数

原型:char * strncpy ( char * destination, const char * source, size_t num );
功能:将字符串source中前num个字符拷贝到字符串destination中 

#include <iostream.h> 
#include <string.h> 
void main(void) 
{ 
    char str1[10] = { "Tsinghua "}; 
    char str2[10] = { "Computer"}; 
    cout <<strncpy(str1,str2,3)<<endl; 
}

运行结果:Comnghua 
注意:字符串source中前numchars个字符将覆盖掉字符串destination中前numchars个字符!

strcat 函数

原型:char * strcat ( char * destination, const char * source );
功能:将字符串source接到字符串destination的后面

#include <iostream.h> 
#include <string.h> 
void main(void) 
{ 
    char str1[] = { "Tsinghua "}; 
    char str2[] = { "Computer"}; 
    cout <<strcpy(str1,str2)<<endl; 
}

运行结果:Tsinghua Computer
注意:在定义字符数组1的长度时应该考虑字符数组2的长度,因为连接后新字符串的长度为两个字符串长度之和。进行字符串连接后,字符串1的结尾符将自动被去掉,在结尾串末尾保留新字符串后面一个结尾符。


strncat 函数

原型:char * strncat ( char * destination, const char * source, size_t num );
功能:将字符串source的前num个字符接到字符串destination的后面

#include <iostream.h> 
#include <string.h> 
void main(void) 
{ 
    char str1[] = { "Tsinghua "}; 
    char str2[] = { "Computer"}; 
    cout <<strncat(str1,str2,3)<<endl; 
}

运行结果:Tsinghua Com

strcmp 函数

原型:int strcmp(const char * firststring, const char * secondstring);
功能:比较两个字符串 firststring 和 secondstring 

#include <iostream.h> 
#include <string.h> 
void main(void) 
{ 
    char buf1[] = "aaa"; 
    char buf2[] = "bbb"; 
    char buf3[] = "ccc"; 
    int ptr;  
    ptr = strcmp(buf2,buf1);  
    if(ptr > 0) 
        cout <<"Buffer 2 is greater than buffer 1"<<endl; 
    else  
        cout <<"Buffer 2 is less than buffer 1"<<endl; 
    ptr = strcmp(buf2,buf3);  
    if(ptr > 0) 
        cout <<"Buffer 2 is greater than buffer 3"<<endl; 
    else  
        cout <<"Buffer 2 is less than buffer 3"<<endl; 
}

运行结果是:Buffer 2 is less than buffer 1  
           Buffer 2 is greater than buffer 3


strlen 函数

原型:size_t strlen ( const char * str );
功能:统计字符串 str 中字符的个数

#include <iostream.h> 
#include <string.h> 
void main(void) 
{ 
    char str[100];  
    cout <<"请输入一个字符串:"; 
    cin >>str; 
    cout <<"The length of the string is :"<<strlen(str)<<"个"<<endl; 
}

运行结果The length of the string is x (x为你输入的字符总数字)
注意:strlen函数的功能是计算字符串的实际长度,不包括'\0'在内。另外,strlen函数也可以直接测试字符串常量的长度,如:strlen("Welcome")。

其他函数

void *memset(void *dest, int c, size_t count);
        将dest前面count个字符置为字符c. 返回dest的值. 
		
void *memmove(void *dest, const void *src, size_t count);
        从src复制count字节的字符到dest. 如果src和dest出现重叠, 函数会自动处理. 返回dest的值. 
		
void *memcpy(void *dest, const void *src, size_t count);
        从src复制count字节的字符到dest. 与memmove功能一样, 只是不能处理src和dest出现重叠. 返回dest的值. 
		
const void * memchr ( const void * buf, int c, size_t count);
      void * memchr (       void * buf, int c, size_t count); 
        在buf前面count字节中查找首次出现字符c的位置. 找到了字符c或者已经搜寻了count个字节, 查找即停止.
        操作成功则返回buf中首次出现c的位置指针, 否则返回NULL.
		
void *_memccpy(void *dest, const void *src, int c, size_t count);
        从src复制0个或多个字节的字符到dest. 当字符c被复制或者count个字符被复制时, 复制停止. 
        如果字符c被复制, 函数返回这个字符后面紧挨一个字符位置的指针. 否则返回NULL. 
		
int memcmp(const void *buf1, const void *buf2, size_t count);
        比较buf1和buf2前面count个字节大小. 
        返回值< 0, 表示buf1小于buf2; 
        返回值为0, 表示buf1等于buf2; 
        返回值> 0, 表示buf1大于buf2. 
		
int memicmp(const void *buf1, const void *buf2, size_t count);
        比较buf1和buf2前面count个字节. 与memcmp不同的是, 它不区分大小写. 返回值同上. 
		
char *strrev(char *string); 
        将字符串string中的字符顺序颠倒过来. NULL结束符位置不变. 返回调整后的字符串的指针. 
		
char *_strupr(char *string); 
        将string中所有小写字母替换成相应的大写字母, 其它字符保持不变. 返回调整后的字符串的指针. 
		
char *_strlwr(char *string); 
        将string中所有大写字母替换成相应的小写字母, 其它字符保持不变. 返回调整后的字符串的指针. 
		
char *strchr(const char *string, int c); 
        查找字 串string中首次出现的位置, NULL结束符也包含在查找中. 
        返回一个指针, 指向字符c在字符串string中首次出现的位置,如果没有找到, 则返回NULL.
		
char *strrchr(const char *string, int c);
        查找字符c在字符串string中最后一次出现的位置, 也就是对string进行反序搜索, 包含NULL结束符. 
        返回一个指针, 指向字符c在字符串string中最后一次出现的位置, 如果没有找到, 则返回NULL. 
		
char *strstr(const char *string, const char *strSearch);
        在字符串string中查找strSearch子串. 返回子串strSearch在string中首次出现位置的指针. 
        没有找到子串strSearch, 则返回NULL. 如果子串strSearch为空串, 函数返回string值.
		
char *strdup(const char *strSource); 
        函数运行中会自己调用malloc函数为复制strSource字符串分配存储空间, 然后再将strSource复制到分配到的空间中. 
        注意要及时释放这个分配的空间。返回一个指针, 指向为复制字符串分配的空间; 如果分配空间失败, 则返回NULL值. 
		
char *strcat(char *strDestination, const char *strSource);
        将源串strSource添加到目标串strDestination后面, 并在得到的新串后面加上NULL结束符.
        源串strSource的字符会覆盖目标串strDestination后面的结束符NULL. 在字符串的复制或添加过程中没有溢出检查, 
        所以要保证目标串空间足够大. 不能处理源串与目标串重叠的情况. 函数返回strDestination值.

char *strncat(char *strDestination, const char *strSource, size_t count);
        将源串strSource开始的count个字符添加到目标串strDest后. 源串strSource的字符会覆盖目标串strDestination后面的结束符NULL. 
        如果count大于源串长度, 则会用源串的长度值替换count值. 得到的新串后面会自动加上NULL结束符. 与strcat函数一样, 
        本函数不能处理源串与目标串重叠的情况. 函数返回strDestination值.
		
char *strcpy(char *strDestination, const char *strSource);
        复制源串strSource到目标串strDestination所指定的位置, 包含NULL结束符. 不能处理源串与目标串重叠的情况.函数返回strDestination值.
		
char *strncpy(char *strDestination, const char *strSource, size_t count);
        将源串strSource开始的count个字符复制到目标串strDestination所指定的位置. 
        如果count值小于或等于strSource串的长度, 不会自动添加NULL结束符目标串中, 
        而count大于strSource串的长度时, 则将strSource用NULL结束符填充补齐count个字符, 复制到目标串中. 
        不能处理源串与目标串重叠的情况.函数返回strDestination值.
		
char *strset(char *string, int c); 
        将string串的所有字符设置为字符c, 遇到NULL结束符停止. 函数返回内容调整后的string指针. 

char *strnset(char *string, int c, size_t count);
        将string串开始count个字符设置为字符c, 如果count值大于string串的长度, 将用string的长度替换count值. 函数返回内容调整后的string指针.
		
size_t strspn(const char *string, const char *strCharSet);
        查找任何一个不包含在strCharSet串中的字符 (字符串结束符NULL除外) 在string串中首次出现的位置序号. 
        返回一个整数值, 指定在string中全部由characters中的字符组成的子串的长度. 
        如果string以一个不包含在strCharSet中的字符开头, 函数将返回0值.

size_t strcspn(const char *string, const char *strCharSet);
        查找strCharSet串中任何一个字符在string串中首次出现的位置序号, 包含字符串结束符NULL. 
        返回一个整数值, 指定在string中全部由非characters中的字符组成的子串的长度. 
        如果string以一个包含在strCharSet中的字符开头, 函数将返回0值.
		
char *strspnp(const char *string, const char *strCharSet);
        查找任何一个不包含在strCharSet串中的字符 (字符串结束符NULL除外) 在string串中首次出现的位置指针. 
        返回一个指针, 指向非strCharSet中的字符在string中首次出现的位置.
		
char *strpbrk(const char *string, const char *strCharSet);
        查找strCharSet串中任何一个字符在string串中首次出现的位置, 不包含字符串结束符NULL. 
        返回一个指针, 指向strCharSet中任一字符在string中首次出现的位置. 
        如果两个字符串参数不含相同字符, 则返回NULL值. 
		
int strcmp(const char *string1, const char *string2);
        比较字符串string1和string2大小. 
        返回值< 0, 表示string1小于string2; 
        返回值为0, 表示string1等于string2; 
        返回值> 0, 表示string1大于string2. 
		
int stricmp(const char *string1, const char *string2);
        比较字符串string1和string2大小,和strcmp不同, 比较的是它们的小写字母版本.返回值与strcmp相同. 
		
int strcmpi(const char *string1, const char *string2);
        等价于stricmp函数, 只是提供一个向后兼容的版本. 
		
int strncmp(const char *string1, const char *string2, size_t count);
        比较字符串string1和string2大小,只比较前面count个字符. 
        比较过程中, 任何一个字符串的长度小于count, 则count将被较短的字符串的长度取代. 此时如果两串前面的字符都相等, 则较短的串要小.
        返回值< 0, 表示string1的子串小于string2的子串; 
        返回值为0, 表示string1的子串等于string2的子串; 
        返回值> 0, 表示string1的子串大于string2的子串. 
		
int strnicmp(const char *string1, const char *string2, size_t count);
        比较字符串string1和string2大小,只比较前面count个字符. 与strncmp不同的是, 比较的是它们的小写字母版本. 返回值与strncmp相同.
		
char *strtok(char *strToken, const char *strDelimit);
        在strToken 串中查找下一个标记, strDelimit字符集则指定了在当前查找调用中可能遇到的分界符. 
        返回一个指针, 指向在strToken中找到的下一个标记. 如果找不到标记, 就返回NULL值. 
        每次调用都会修改strToken内容, 用NULL字符替换遇到的每个分界符.






----------------------------------------------------------------------------


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值