标准库类型

string 类型支持长度可变的字符串,C++ 标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作。

#include <string>
using std::string;

 

字符串字面值与标准库 string 类型不是同一种类型。

用 iostream 和 string 标准库,使用标准输入输出操作符来读写 string 对象

读取并忽略开头所有的空白字符(如空格,换行符,制表符)。
读取字符直至再次遇到空白字符,读取终止。

读入未知数目的 string 对象

使用 getline 读取整行文本

getline 函数从输入流的下一行读取,并保存读取的内容到不包括换行符。和输入操作符不一样的是,getline 并不忽略行开头的换行符。只要 getline 遇到换行符,即便它是输入的第一个字符,getline 也将停止读入并返回。如果第一个字符就是换行符,则 string 参数将被置为空 string。由于 line 不含换行符,若要逐行输出需要自行添加。

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

int main()
{
   string word;
   // read until end-of-file, writing each word to a new line
   while (cin >> word)
   {
       cout << word << endl;
   }
   string line;
   // read line at time until end-of-file
   while (getline(cin, line))
   {
       cout << line << endl;
   }
   return 0;
}

 关于size_type:
string 类类型和许多其他库类型都定义了一些配套类型(companion type)。通过这些配套类型,库类型的使用就能与机器无关(machine-independent)。size_type 就是这些配套类型中的一种。它定义为与 unsigned 型(unsigned int 或 unsigned long)具有相同的含义,而且可以保证足够大能够存储任意 string 对象的长度。

string 关系操作符
关系操作符比较两个 string 对象时采用了和(大小写敏感的)字典排序相同的策略
如果两个 string 对象长度不同,且短的 string 对象与长的 string 对象的前面部分相匹配,则短的 string 对象小于长的 string 对象。
如果 string 对象的字符不同,则比较第一个不匹配的字符

两个 string 对象相加

string 对象的加法被定义为连接(concatenation)。也就是说,两个(或多个)string 对象可以通过使用加操作符 + 或者复合赋值操作符 +=连接起来。

string和字符串字面值的连接
当进行 string 对象和字符串字面值混合连接操作时,+ 操作符的左右操作数必须至少有一个是 string 类型的

从 string 对象获取字符
string 类型通过下标操作符([ ])来访问 string 对象中的单个字符。下标操作符需要取一个 size_type 类型的值,来标明要访问字符的位置。
string 对象的下标从 0 开始。如果 s 是一个 string 对象且 s 不空,则 s[0] 就是字符串的第一个字符, s[1] 就表示第二个字符(如果有的话),而 s[s.size() - 1] 则表示 s 的最后一个字符。

引用下标时如果超出下标作用范围就会引起溢出错误。
下标操作可用作左值

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

int main()
{
    string s1 = "hello";   // no punctuation
    string s2 = "world";
    string s3 = s1 + ", ";           // ok: adding a string and a literal
    //string s4 = "hello" + ", ";      error: no string operand
    string s5 = s1 + ", " + "world"; // ok: each + has string operand
    //string s6 = "hello" + ", " + s2; error: can't add string literals

    for (string::size_type ix = 0; ix != s5.size(); ++ix)
    {
        cout << s5[ix];
    }
    cout << endl;
    for (string::size_type ix = 0; ix != s5.size(); ++ix)
    {
         s5[ix] = '*';
    }
    
    return 0;
}

 

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

int main()
{
    string line;
    getline(cin,line);
    
    int alpha = 0;
    int digit = 0;
    int punct = 0;
    int space = 0;

    for(string::size_type index=0; index != line.size(); ++index)
    {
         if(isalpha(line[index]))
         {
             ++alpha;
         }
         if(isdigit(line[index]))
         {
             ++digit;
         }
         if(ispunct(line[index]))
         {
             ++punct;
         }
         if(isspace(line[index]))
         {
             ++space;
         }
    }
    cout << "alpha : " << alpha << endl;
    cout << "digit : " << digit << endl;
    cout << "punct : " << punct << endl;
    cout << "space : " << space << endl;
    
    return 0;
}

 

vector 是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。和 string 对象一样,标准库将负责管理与存储元素相关的内存。

一个容器中的所有对象都必须是同一种类型的。

#include <vector>
using std::vector;

vector 不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector 类型的每一种都指定了其保存元素的类型。因此,vector<int> 和 vector<string> 都是数据类型。

虽然可以对给定元素个数的 vector 对象预先分配内存,但更有效的方法是先初始化一个空 vector 对象,然后再动态地增加元素.

如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行值初始化,具体值为何,取决于存储在 vector 中元素的数据类型

使用 size_type 类型时,必须指出该类型是在哪里定义的。vector 类型总是包括 vector 的元素类型:

向 vector 添加元素

vector 的下标操作类似于 string 类型的下标操作,vector 下标操作的结果为左值

下标操作不添加元素
下标只能用于获取已存在的元素。

必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。

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

int main()
{
     vector<int> ivec;   // empty vector
     
     // vector::size_type index; error!
     
     for (vector<int>::size_type ix = 0; ix != 10; ++ix)
     {
        // ivec[ix] = ix; disaster: ivec has no elements
        ivec.push_back(ix); //ok
     }
     for (vector<int>::size_type ix = 0; ix != 10; ++ix)
     {
        cout << ivec[ix] << endl;
     }
    
    system("pause");
    return 0;
}

 迭代器
迭代器(iterator)迭代器是一种检查容器内元素并遍历元素的数据类型。

所有的标准库容器都定义了相应的迭代器类型,而只有少数的容器支持下标操作

每种容器类型都定义了自己的迭代器类型,如 vector:

     vector<int>::iterator iter;

如果容器中有元素的话,由 begin 返回的迭代器指向第一个元素

由 end 操作返回的迭代器指向 vector 的“末端元素的下一个”。

如果 vector 为空,begin 返回的迭代器与 end 返回的迭代器相同

由 end 操作返回的迭代器并不指向 vector 中任何实际的元素,相反,它只是起一个哨兵(sentinel)的作用,表示我们已处理完 vector 中所有元素。

代器类型可使用解引用操作符(dereference operator)(*)来访问迭代器所指向的元素

代器类支持自增和自减操作

由于 end 操作返回的迭代器不指向任何元素,因此不能对它进行解引用或自增操作。(指向不确定数据)

用 == 或 != 操作符来比较两个迭代器,如果两个迭代器对象指向同一个元素,则它们相等,否则就不相等。

每种容器类型还定义了一种名为 const_iterator 的类型,该类型只能用于读取容器内元素,但不能改变其值。

它自身的值可以改变,但不能用来改变其所指向的元素的值。

不要把 const_iterator 对象与 const 的 iterator 对象混淆起来。声明一个 const 迭代器时,必须初始化迭代器。一旦被初始化后,就不能改变它的值:

迭代器的算术操作
iter + n

iter - n
其位置在 iter 所指元素之前(加)或之后(减) n 个元素的位置。
 
iter1 - iter2
该表达式用来计算两个迭代器对象的距离,该距离是名为 difference_type 的 signed 类型 size_type 的值
iter1 与 iter2 两者必须都指向同一 vector 中的元素,或者指向 vector 末端之后的下一个元素。

下面语句直接定位于 vector 中间元素:

任何改变 vector 长度的操作都会使已存在的迭代器失效。例如,在调用 push_back 之后,就不能再信赖指向 vector 的迭代器的值了

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

int main()
{
    vector<int> ivec1;
    
    for(int i=0; i<10; ++i)
    {
         ivec1.push_back(i+10);
    }
    for(vector<int>::iterator iter=ivec1.begin(); iter!=ivec1.end(); ++iter)
    {
         cout << *iter << " ";
    }
    cout << endl;
    
    vector<int> ivec2(10,9);
    cout << "ivec1 == ivec2 ? " << boolalpha << (ivec1 == ivec2) << endl;
    
    vector<int>::iterator mid = ivec1.begin() + ivec1.size() / 2;
    cout << "*(mid-2) = " << *(mid-2) << endl;
    cout << "*(mid+2) = " << *(mid+2) << endl;
    
    vector<int>::iterator iterBeg = ivec1.begin();
    cout << "*iterBeg = " << *iterBeg << endl;  //print the first number
    
    vector<int>::iterator iterEnd = ivec1.end();
    cout << "*iterEnd = " << *iterEnd << endl;    //will print a random number
    
    cout << "iterEnd - iterBeg = " << (iterEnd - iterBeg) << endl;
    
    for (vector<int>::const_iterator iter = ivec1.begin(); iter != ivec1.end(); ++ iter)
    {
       // *iter = 1;     error: *iter is const
       cout << *iter << " ";   //readonly
    }
    cout << endl;    
    
    vector<int> nums(10);  // nums is nonconst
    const vector<int>::iterator cit = nums.begin();
    *cit = 1;               // ok: cit can change its underlying element
    //++cit;               error: can't change the value of cit
    
        vector<int> vi;
    vi.push_back(4);
    vi.push_back(5);
    vi.push_back(6);
    vi.push_back(7);

    vector<int>::iterator iter = vi.begin();
    
    cout << *(iter+1) << endl;
    cout << *(iter+2) << endl;
    cout << *(iter+3) << endl;
    
    vi.push_back(8);
    
    cout << *(iter+1) << endl;
    cout << *(iter+2) << endl;
    cout << *(iter+3) << endl;
    cout << *(iter+4) << endl;  //will print 8?
    
    return 0;
}

 


标准库提供的 bitset 类简化了位集的处理
#include <bitset>
using std::bitset;

 


按位置来访问,以 0 位开始的位串是低阶位(low-order),以 31 位结束的位串是高阶位(high-order)。

当用 unsigned long 值作为 bitset 对象的初始值时,该值将转化为二进制的位模式。

当用 string 对象初始化 bitset 对象时,string 对象直接表示为位模式。

size_t 类型定义在 cstddef 头文件中,该文件是 C 标准库的头文件 stddef.h 的 C++ 版本。它是一个与机器相关的 unsigned 类型,其大小足以保证存储内在中对象的大小。

可以用下标操作符来读或写某个索引位置的二进制位,
除了用下标操作符,还可以用 set;、test 和 reset 操作来测试或设置给定二进制位的值

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

int main()
{
    bitset<8> bs;
    cout << "bitset<8> : " << bs << endl;
    
    // bitvec1 is smaller than the initializer
    // bits 0 ... 15 are set to 1
    bitset<16> bitvec1(0xffff);    
    cout << "bitvec1 : " << bitvec1 << endl;
    
    // bitvec2 same size as initializer
    // bits 0 ... 15 are set to 1; 16 ... 31 are 0
    bitset<32> bitvec2(0xffff);   
    cout << "bitvec2 : " << bitvec2 << endl;
    
    // on a 32-bit machine, bits 0 to 31 initialized from 0xffff
    // bits 32 through 127 initialized to zero
    bitset<64> bitvec3(0xffff);  
    cout << "bitvec3 : " << bitvec3 << endl;
    unsigned long ulong = bitvec3.to_ulong();
    cout << "bitvec3.to_ulong() = " << ulong << endl;
    
    string strval("1100");
    bitset<32> bitvec4(strval);
    cout <<  "bitvec4 : " << bitvec4 << endl;
    
    string str("1111111000000011001101");
    bitset<32> bitvec5(str, 5, 4); // 4 bits starting at str[5], 1100
    cout <<  "bitvec5 : " << bitvec5 << endl;
    
    bitset<32> bitvec6(str, str.size() - 4);     // use last 4 characters
    cout <<  "bitvec6 : " << bitvec6 << endl;
    
    bitset<32> bitvec7; // 32 bits, all zero
    
    bool is_set = bitvec7.any();        // false, all bits are zero
    cout << "is_set : " << boolalpha << is_set << endl;
    
    bool is_not_set = bitvec7.none();  // true, all bits are zero
    cout << "is_not_set : " << boolalpha << is_not_set << endl;
    
    size_t bits_set = bitvec7.count(); // returns number of bits that are on
    cout << "bits_set : " << bits_set << endl;


    bitset<8> bitvec(strval);  // 00001100

    cout << boolalpha << "bitvec.test(0) : " << bitvec.test(0) << endl;
    cout << boolalpha << "bitvec.test(2) : " << bitvec.test(2) << endl;
    
    bitvec.set(6); // set all the bits to 0.
    cout << "after bitvec.set(6) : " << bitvec << endl;
    
    bitvec.reset(3); // set all the bits to 0.
    cout << "after bitvec.reset(3) : " << bitvec << endl;
    
    bitvec.reset(); // set all the bits to 0.
    cout << "after reset : " << bitvec << endl;
    
    bitvec.set();   // set all the bits to 1
    cout << "after set : " << bitvec << endl;
    
    bitvec.flip(0);   // reverses value of first bit
    cout << "after bitvec.flip(0) : " << bitvec << endl;
    
    bitvec[0].flip(); // also reverses the first bit
    cout << "after bitvec[0].flip() : " << bitvec << endl;
    
    bitvec.flip();    // reverses value of all bits
    cout << "after bitvec.flip() : " << bitvec << endl;

    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值