ACM程序设计(第2版)
上QQ阅读APP看书,第一时间看更新

2.3 string基本字符系列容器

C语言只提供了一个char类型用来处理字符,而对于字符串,只能通过字符串数组来处理,显得十分不便。C++STL提供了string基本字符系列容器来处理字符串,可以把string理解为字符串类,它提供了添加、删除、替换、查找和比较等丰富的方法。

虽然使用vector<char>这样的向量也可以处理字符串,但功能比不上string。向量的元素类型可以是string,如vector<string>这样的向量,实际上就类似于C语言中的字符串数组。

使用string容器,需要头文件包含声明“#include <string>”。string文件在C:\Program Files\Microsoft Visual Studio\VC98\Include文件夹中可以找到。

2.3.1 创建string对象

下面这条语句创建了字符串对象s, s是一个空字符串,其长度为0:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          cout<<s.length()<<endl;
          return 0;
        }

运行结果:

        0

2.3.2 给string对象赋值

给string对象赋值一般有两种方式。

(1)直接给字符串对象赋值,如:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {

            string s;
            s="hello, C++STL.";
            cout<<s<<endl;
            return 0;
          }

运行结果:

        hello, C++STL.

(2)更常用的方法是,把字符指针赋给一个字符串对象:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          char ss[5000];
          //scanf的输入速度比cin快得多
          //scanf是C语言的函数,不支持string对象
          scanf("%s", &ss);
          //把整个字符数组赋值给string对象
          s=ss;
          //输出字符对象
          cout<<s<<endl;
          return 0;
        }

运行结果(先从键盘上输入“hello, string.”):

        hello, string.
        hello, string.

2.3.3 从string对象尾部添加字符

在string对象的尾部添加一个字符(char),采用“+”操作符即可,具体应用如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s=s+'a';
          s=s+'b';
          s=s+'c';
          cout<<s<<endl;
          return 0;
        }

运行结果:

        abc

2.3.4 从string对象尾部追加字符串

从尾部追加的方式有两种。

(1)直接采用“+”操作符,代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s=s+"abc";
          s=s+"123";
          cout<<s<<endl;
          return 0;
        }

运行结果:

        abc123

(2)采用append()方法,代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s.append("abc");
          s.append("123");
          cout<<s<<endl;
          return 0;
        }

运行结果:

        abc123

2.3.5 给string对象插入字符

可以使用insert()方法把一个字符插入到迭代器位置之前,代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

        int main(int argc, char * argv[])
        {
          string s;
          s="123456";
          //定义迭代器
          string::iterator it;
          //迭代器位置为字符串首
          it=s.begin();
          //把字符’p’插入到第1个字符前(注意,字符位置是从0开始计数)
          s.insert(it+1, 'p');
          cout<<s<<endl;
          return 0;
        }

运行结果:

        1p23456

2.3.6 访问string对象的元素

一般使用下标方式随机访问string对象的元素,下标是从0开始计数的。另外,string对象的元素是一个字符(char),这点一定要清楚。代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s="abc123456";
          //输出string对象的首元素
          cout<<s[0]<<endl;
          //两个相同的字符相减值为0
          cout<<s[0]-'a'<<endl;
          return 0;
        }

运行结果:

        a
        0

2.3.7 删除string对象的元素

(1)清空一个字符串,则直接给它赋空字符串即可。

(2)使用erase()方法删除迭代器所指的那个元素或一个区间中的所有元素。代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

        int main(int argc, char * argv[])
        {
          string s;
          s="abc123456";
          //定义迭代器变量,指向字符串对象首元素
          string::iterator it=s.begin();
          //删除第3个元素,元素位置从0开始计数
          s.erase(it+3);
          cout<<s<<endl;
          //删除0~4区间的所有元素
          s.erase(it, it+4);
          cout<<s<<endl;
          //清空字符串
          s="";
          //输出字符串的长度
          cout<<s.length()<<endl;
          return 0;
        }

运行结果:

        abc23456
        3456
        0

2.3.8 返回string对象的长度

采用length()方法可返回字符串的长度;采用empty()方法,可返回字符串是否为空,如果字符串为空,则返回逻辑真,即1,否则,返回逻辑假,即0。代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s="abc123456";
          //输出字符串的长度
          cout<<s.length()<<endl;
          //清空字符串
          s="";
          //判断字符串是否为空
          cout<<s.empty()<<endl;
          return 0;
        }

运行结果:

        9
        1

2.3.9 替换string对象的字符

使用replace()方法可以很方便地替换string对象中的字符,replace()方法的重载函数相当多,常用的只有一两个,具体代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s="abc123456";
          //从第3个开始,将连续的3个字符替换为“good”
          //即将“abc”替换为“good”
          s.replace(3,3, "good");
          cout<<s<<endl;
          return 0;
        }

运行结果:

        abcgood456

2.3.10 搜索string对象的元素或子串

采用find()方法可查找字符串中的第一个字符元素(char,用单引号界定)或者子串(用双引号界定),如果查到,则返回下标值(从0开始计数),如果查不到,则返回4294967295。

find()方法有很多重载函数,下面的代码,仅举出了一种用法。

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s="cat dog cat";
          //查找第一个字符‘c',返回下标值
          cout<<s.find('c')<<endl;
          //查找第一个子串“c”,返回下标值
          cout<<s.find("c")<<endl;
          //查找第一个子串“cat”,返回下标值
          cout<<s.find("cat")<<endl;
          //查找第一个子串“dog”,返回下标值
          cout<<s.find("dog")<<endl;
          //查找第一个子串“dogc”,查不到则返回4294967295
          cout<<s.find("dogc")<<endl;
          return 0;
        }

运行结果:

        0
        0
        0
        4
        4294967295

2.3.11 string对象的比较

string对象可与使用compare()方法与其他字符串相比较。如果它比对方大,则返回1;如果它比对方小,则返回-1;如果它与对方相同(相等),则返回0。代码如下:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s="cat dog cat";
          //s比“cat”字符串大,返回1
          cout<<s.compare("cat")<<endl;
          //s与“cat dog cat”相等,返回0
          cout<<s.compare("cat dog cat")<<endl;
          //s比“dog”小,返回-1
          cout<<s.compare("dog")<<endl;
          return 0;
        }

运行结果:

        1
        0
        -1

2.3.12 用reverse反向排序string对象

采用reverse()方法可将string对象迭代器所指向的一段区间中的元素(字符)反向排序。reverse()方法需要声明头文件“#include <algorithm>”。代码如下:

        #include <string>
        #include <iostream>
        #include <algorithm>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          s="123456789";
          reverse(s.begin(), s.end());

            cout<<s<<endl;
            return 0;
          }

运行结果:

        987654321

2.3.13 string对象作为vector元素

string对象可以作为vector向量的元素,这种用法,类似于字符串数组。代码如下:

        #include <vector>
        #include <string>
        #include <iostream>
        #include <algorithm>
        using namespace std;

       int main(int argc, char * argv[])
        {
          vector<string> v;
          v.push_back("Jack");
          v.push_back("Mike");
          v.push_back("Tom");
          cout<<v[0]<<endl;
          cout<<v[1]<<endl;
          cout<<v[2]<<endl;
          cout<<v[0][0]<<endl;
          cout<<v[1][0]<<endl;
          cout<<v[2].length()<<endl;
          return 0;
        }

运行结果:

        Jack
        Mike
        Tom
        J
        M
        3

2.3.14 string类型的数字化处理

在ACM竞赛中,常常需要将读入的数字的每位分离出来,如果采用取余的方法,花费的时间就会太长,这时候,我们可以将读入的数据当成字符串来处理,这样就方便、省时多了。下面这个程序演示了求一个整数各位的和:

        #include <string>
        #include <iostream>
        using namespace std;

        int main(int argc, char * argv[])
        {
          string s;
          s="1234059";
          int i;
          int sum=0;
          for(i=0; i<s.length(); i++)
          {
              if(s[i]=='0')sum+=0;
              else if(s[i]=='1')sum+=1;
              else if(s[i]=='2')sum+=2;
              else if(s[i]=='3')sum+=3;
              else if(s[i]=='4')sum+=4;
              else if(s[i]=='5')sum+=5;
              else if(s[i]=='6')sum+=6;
              else if(s[i]=='7')sum+=7;
              else if(s[i]=='8')sum+=8;
              else if(s[i]=='9')sum+=9;
          }
          cout<<sum<<endl;
          return 0;
        }

运行结果:

        24

2.3.15 string对象与字符数组互操作

下面这个程序演示了字符数组与string对象的输入与输出:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s;
          char ss[100];
          //输入字符串到字符数组中
          scanf("%s", &ss);
          //字符数组赋值线字符串对象
          s=ss;
          //用printf输出字符串对象,要采用c_str()方法
          printf(s.c_str());
          //换行
          cout<<endl;
          //用printf输出字符数组
          printf("%s", ss);
          //换行

            cout<<endl;
            //用cout输出字符串对象
            cout<<s<<endl;
            //用cout输出字符数组
            cout<<ss<<endl;
             return 0;
          }

输出结果(从键盘输入“abc123”字符串后按回车键):

        abc123
        abc123
        abc123
        abc123
        abc123

2.3.16 string对象与sscanf函数

在C语言中,sscanf函数很管用,它可以把一个字符串按你需要的方式分离出子串,甚至是数字。下面这个程序演示了sscanf函数的具体用法:

        #include <string>
        #include <iostream>
        using namespace std;

       int main(int argc, char * argv[])
        {
          string s1, s2, s3;
          char sa[100], sb[100], sc[100];
          //将字符串分离成子串,分隔符为空格
          sscanf("abc 123 pc", "%s %s %s", sa, sb, sc);
          s1=sa;
          s2=sb;
          s3=sc;
          cout<<s1<<" "<<s2<<" "<<s3<<endl;
          //将字符串分离成数字,分隔符为空格
          //当用到数字的时候,跟scanf一样,它要传指针地址
          int a, b, c;
          sscanf("1 2 3", "%d %d %d", &a, &b, &c);
          cout<<a<<" "<<b<<" "<<c<<endl;
          //将字符串分离成数字,分隔符为“,”和“$”
          //当用到数字的时候,跟scanf一样,它要传指针地址
          int x, y, z;
          sscanf("4,5$6", "%d, %d$%d", &x, &y, &z);
          cout<<x<<" "<<y<<" "<<z<<endl;
          return 0;
        }

运行结果:

        abc 123 pc

        1 2 3
        4 5 6

2.3.17 string对象与数值相互转换

有时候,string对象与数值之间需要相互转换,下面这个例子详细说明了如何完成这项工作:

        #include <iostream>
        #include <string>
        #include <sstream>
        using namespace std;

       //C++方法:将数值转换为string
        string convertToString(double x)
         {
          ostringstream o;
          if (o << x)
              return o.str();
          return "conversion error"; //if error
         }

       //C++方法:将string转换为数值
        double convertFromString(const string &s)
         {
          istringstream i(s);
          double x;
          if (i >> x)
            return x;
          return 0.0; //if error
         }

       int main(int argc, char * argv[])
        {
          //将数值转换为string的第一种方法:C方法
          char b[10];
          string a;
          sprintf(b, "%d",1975);
          a=b;
          cout<<a<<endl;

         //将数值转换为string的第二种方法:C++方法
          string cc=convertToString(1976);
          cout<<cc<<endl;

         //将string转换为数值的方法:C++方法
          string dd="2006";
          int p=convertFromString(dd)+2;
          cout<<p<<endl;

         return 0;
        }