C++复习 03 标准库类型

本文详细介绍了C++标准库中的string和vector类型,包括它们的构造、操作、迭代器使用等,并对比了与传统字符串和数组的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >




声明,所有的朋友,如果要转我的帖子,务必注明"作者:黑啤 来源:优快云博客"和具体的网络地址http://blog.youkuaiyun.com/nx500/archive/2007/10/21/1836173.aspx,并且我的所有博客内容,禁止任何形式的 商业用途,请大家尊重我的劳动.谢谢!

目 录

三.标准库类型.
  001 两种重要的标准库类型是string和vector.说他们重要,是因为它们在C++定义的基本类型基础上作了一些改进.
      string类型支持长度可变的字符串,vector可用于保存一组指定类型的对象.
  002 命名空间.
      std::cin 通过域操作符,说明cin是命名空间std中定义的.
      使用using声明可以在不需要加前缀namespace_name::的情况下访问命名空间的名字.
        using namespace::name;
         //  03002.cpp
        #include  < iostream >
        #include 
< string >

        
//  一个using声明一次只能作用于一个命名空间成员.必须要为每个用到的名字都提供using声明.
         using  std::cout;
        
using  std::endl;
        
using  std:: string ;

        
int  main() {
          
string s("hello heipi");
          cout 
<< s << endl;

          
return 0;
        }

      在头文件中必须总是使用完全限定的标准库名字(std::cin).因为头文件的内容会被预处理器复制到程序中.
      如果在头文件中放置using声明,就相当于在包含该头文件的每个程序中都放置这些using声明,而有些文件很可能不能有这样的声明.
  003 标准库string类型.构造函数(初始化方法).
        #include <string>
        using std::string;
        string s1;
        string s2(s1);
        string s3("value");
        string s4(n, 'c');
      字符串字面值与string类型不是同一种类型,注意区分.
      string对像的读写
        string s;
        cin >> s;
        读取并忽略开头所有的空白字符,读取字符直到再次遇到空白字符,读取终止. 输入" Hello  heipi ", s=="Hello"
        返回左操作数作为运算结果,所以可以连续读入. cin >> s1 >> s2;
      和内置类型的输入操作符一样,string的输入操作符也会返回所读的数据流,因此,可以把输入操作作为判断条件.
         //  03003.cpp
        #include  < iostream >
        #include 
< string >

        
using  std::cin;
        
using  std::cout;
        
using  std::endl;
        
using  std:: string ;

        
int  main() {
          
string s;
          
while(cin >> s)  // linux下,循环直到读入^d,遇到回车并不会使cin产生错误状态
            cout << s << endl;
          
return 0;
        }

        // 下面是编译和运行的结果
        Nan@linux-g4n6:~/Documents> g++ 03003.cpp
        Nan@linux-g4n6:~/Documents> ./a.out
        abc -123 234 95.5 s2 0xff34
        abc
        -123
        234
        95.5
        s2
        0xff34
        ^d
        Nan@linux-g4n6:~/Documents>
  004 getline读取整行文本.从输入流的下一行读取,并保存内容到s中,但不包含换行符.
      和输入操作(cin>>)不一样的是,getline并不忽略行开头的换行符.
      如果换行符是输入的第一个字符,getline也将停止读入并返回,此时s被置为空string.getline是string头文件中定义的函数.
         //  03004.cpp
        #include  < iostream >
        #include 
< string >

        
using  std::cin;
        
using  std::cout;
        
using  std::endl;
        
using  std:: string ;

        
int  main() {
          
string s;
          
while(getline(cin, s))
            cout 
<< s << endl; // getline不读入换行符,所以人为的加上一个换行符.
          return 0;
        }

        // 编译及运行结果
        Nan@linux-g4n6:~/Documents> g++ 03004.cpp
        Nan@linux-g4n6:~/Documents> ./a.out
        abc -123 234 95.5 s2 0xff34
        abc -123 234 95.5 s2 0xff34
        ^d
        Nan@linux-g4n6:~/Documents>
  005 string对像的操作.
        s.empty() 返回bool类型值,如果s为空,则返回true,否则返回false.
        s.size()  返回string::size_type类型,返回s中字符的个数,注意:不要把返回值赋给int型变量.
        s[n]      返回s中位置为n的字符,起始位置为0.下标必须是一个string::size_type类型.
        s1 + s2   把s1和s2链接成一个新的字符串,返回新生成的字符串.
        s1 = s2   把s2的内容赋值给s1.
        s1 == s2  比较s1和s2的内容,相同则返回true,否则返回false.
        !=, <, >, <=, >= 保持这些操作惯有的含义 (还记得么? A的ASCII码是65,a是98,0是48).
      当进行string对象和字符串字面值混合链接操作时,"+"操作的左右操作数必须至少有一个是string类型.
        string s1 = "hello";
        string s2 = s1 + " hei" + " pi";  // ok
        string s3 = " hei" + " pi " + s1; // error: 不行对两个字符串字面值进行+操作
      用下标方法索引string类型中的字符要注意范围,超出将引起溢出错误.任何可产生整型值的表达式都可以用做下标操作符的索引.
      string对像的下标操作返回值也是左值,所以可以对其赋值.
        s[someotherval * someval] = someval;
  006 string对象中字符的处理. (这些函数都包含在cctype头文件定义中)
        isalnum(c)  如果是字母或数字,返回true
        isalpha(c)  如果是字母...
        iscntrl(c)  如果是控制字符...
        isdigit(c)  如果是数字...
        isgraph(c)  如果不是空格,但可以打印...
        islower(c)  如果是小写字符...
        isprint(c)  如果是可以打印字符...
        ispunct(c)  如果是标点符号...
        isspace(c)  如果是空格...
        isupper(c)  如果是大写字母...
        isxdigit(c) 如果是十六进制数...
        tolower(c)  转换为小写字符
        toupper(c)  转换为大写字符
      如果测试失败,函数返回0,否则返回一个非零值,表示被测试字符符合条件.空白字符包含空格/制表符/垂直制表/回车符/换行符/进纸符.
  007 vector称为容器,是同一种类型的对象的集合,每个对象都有一个对应的整数索引值.
        #include <vector>
        using std::vector;
      vector不是一种数据类型,而只是一个类模板,可以定义任意多种数据类型.
        vector<int> ivec;    // ivec是一个保存int型数据集合的变量.
        vector<string> istr;
      vector对象的定义和初始化
        vector<T> v1;
        vector<T> v2(v1);
        vector<T> v3(n, i);  // v3包含n个值为i的元素.
        vector<T> v4(n);     // v4包含值初始化的元素的n个副本,类型T必须要有默认构造函数.
        vector<int> ivec1;
        vector<int> ivec2(ivec1);    //  ok
        vector<string> ivec3(ivec1); //  error, ivec1和ivec3不是相同的数据类型
      vector对象的重要属性在于可以"在运行时高效地"添加元素.虽然可以在初始化时预先分配内存,但是更有效的方式还是动态的增加元素.
  008 vector对象的操作.
        v.empty()         // 没有添加注解的操作均与string功能相同.
        v.size()          // 返回vector<T>::size_type类型.
        v.push_back(t)    // v的末尾增加一个值为t的元素.
        v[n]
        v1 = v2
        v1 == v2
        !=, <, <=, >, >=
  009 向vector中添加元素,索引元素.
         //  03009.cpp
        #include  < iostream >
        #include 
< string >
        #include 
< vector >

        
using  std::cin;
        
using  std::cout;
        
using  std::endl;
        
using  std:: string ;
        
using  std::vector;

        
int  main() {
        
string word;
        vector
<string> texts;

          
while(cin >> word){
            texts.push_back(word);
            
// 每加入一个字符串元素,都将texts中所有的元素输出一遍.
            
// c++程序员习惯于使用!=而不是<操作符来进行条件测试.
            
// 因为vector是动态增长的类型,所以应该每次判断时调用size()函数.
            for(vector<string>::size_type ix = 0; ix != texts.size(); ++ix){
              cout 
<< texts[ix] << " ";
            }

            cout 
<< endl;
          }


          
return 0;
        }

        // 编译及运行结果
        Nan@linux-g4n6:~/Documents> g++ -o o 03009.cpp
        Nan@linux-g4n6:~/Documents> ./o
        abc -123 234 95.5 s2 0xff34
        abc
        abc -123
        abc -123 234
        abc -123 234 95.5
        abc -123 234 95.5 s2
        abc -123 234 95.5 s2 0xff34
        ^d
        Nan@linux-g4n6:~/Documents>
      下标操作不能添加元素,应该该使用push_back(t)函数添加元素.
      与string一样,只能对已经存在的元素进行下标操作."缓冲区溢出"的错误,就是对不存在的元素进行下标操作的结果.
  010 迭代器iterator.是一种检查容器内元素并遍历元素的数据类型.所有的容器都定义了相应的迭代器类型,而少数支持下标操作.
      每种容器类型都定义了自己的迭代器,如vector, vector<T>::iterator iter;
      每种容器都定义了名为begin()和end()的函数,用于返回迭代器.如果容器中有元素的话,begin()返回的迭代器指向第一个元素.
      end()返回的迭代器指向末端元素的下一个,通常称为超出末端迭代器,指向了一个不存在的元素,如果容器为空,begin()==end().
      比如02009.cpp中的输出可修改为如下方式,注意迭代器的自增(++)/解引用(*iter)/比较(!=/==)的几个操作.
        for(vector<string>::iterator iter = texts.begin(); iter != texts.end(); ++iter){
          cout << *iter << " ";
        }
      每种容器还定义了const_iterator的类型,防止在遍历过程中对元素的修改,02009.cpp中的输出不涉及修改,所以可以修改为如下.
        for(vector<string>::const_iterator iter = texts.begin(); iter != texts.end(); ++iter){
          cout << *iter << " ";
          // *iter = ""; // error! const元素对象不能修改.
        }
      注意:不要把const_iterator对象与const的iterator对象混淆.const的iterator必须在定义时初始化,而且iterator不能自增操作.
        const vector<string>::iterator iter = texts.begin();
        *iter = "";  // ok, 可以修改迭代器指向元素的值.
        ++iter;      // error, 不可以修改const迭代器,使之指向其他元素.
      迭代器的算数操作.
        iter + n;
        iter - n;
        vector<type>::difference_type diff = iter1 - iter2;
      计算位于vector中间的元素的迭代器
        vector<string>::iterator mid = texts.begin() + texts.size()/2;
      任何改变vector长度的操作都会使已存在的迭代器实效.比如,在调用push_back之后,就不能再信赖指向vector的迭代器的值了.
      下边是应用于string类型的迭代器的例子,引用了string类型的begin()和end()操作
        string s("Expressions in C++ are composed...");
        string::iterator it = s.begin();
        while ((it != s.end()) && !isspace(*it)){
          *it = toupper(*it);
          ++it;
        }
  011 标准库bitset类型.
        #include <bitset>
        using std::bitset;
      构造函数
        bitset<n> b;                   // b有n位,每位都是0.
        bitset<n> b(u);                // b是unsigned long型u的一个副本.
        bitset<n> b(s);                // b是string对象s中含有的位串的副本.
        bitset<n> b(s, pos, n);        // b是s中从位置pos开始的n个位的副本.
      使用unsigned long作为bitset对象的初始值时,将该值转化为二进制的位模式.而bitset对象中的位集作为这种位模式的副本.
      若bitset长度大于unsigned long的位数,则其余高位将置0,如果biset长度小于位数,则只使用unsigned值中的低阶位,超过长度的高位被抛弃.
      下边这段话"本人持保留意见": 要注意机器的unsigned long的字长度,如下边这句代码:
        bitset<32> bitvec(0xffff); 对于16位机器,16到31位初始化为0,对于32位机器,全部都初始化为1.
      使用string初始化,要使用string类型初始化,而不是字符串值,另外注意位的描述,不要混淆.
        std::string strval("1100");  // 对于strval,第0第1位的值是字符1,第2第3位是字符0.
        bitset<16> bitvec(strval);   // 对于bitvec, 0000 0000 0000 1100, 第2和第3位是1,其他位是0.
      bitset对象的操作.
        b.any()      // 任意位置存在1,就返回true.
        b.none()     // 所有位置都为0,就返回true.
        b.count()    // 返回1的个数,返回一个size_t类型的值(size_t定义在cstddef头文件中).
        b.size()     // 返回b的长度(位数).
        b[pos]       // 返回b在pos位置的值.
        b.test[pos]  // 如果b在pos位置的值为1,返回true.
        b.set()      // 将所有位都重置为1.
        b.set(pos)   // 将pos位设置位1.
        b.reset()    // 将所有位都重新设置为0.
        b.reset(pos) // 将pos位设置为0.
        b.flip()     // 将所有位都取反.
        b.flip(pos)  // 将b中pos位取反,也可以这样用: b[pos].flip().
        b.to_ulong   // 用b中同样的二进制返回一个unsigned long值,b的长度必须小于unsigned long才可以用.
        os<<b        // 把b中的位集输出到os流中.
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值