《C++Primer》读书笔记---标准类型库

标准类型库

1 标准库string类型

1.1 string对象的初始化和定义
string类型支持长度可变的字符串,内存由标准库管理,需要使用<string>头文件 和std namespace
构造函数:
string s1; 默认构造函数,s1为空串
string s2(s1);   初始化为s1的副本
string s3("value") 初始化为字符串字面值(由于对C的兼容,字符串字面值和string类型不是同一类型,需要注意)
strings4(n, 'c') 初始化为n个‘c’的副本

1.2 string对象的读写
使用iostream读取:
string s;
cin>>s;
读取并忽略开头所有空白字符(换行符,制表符,空格)   "  hello world!"  -->   s为 "hello"
读取字符直至遇到空白字符,读取终止
cin >> s1 >> s2;
cout << s1 << s2 << endl;
------> "helloworld"

C语言中为了确定字符串的长度,字符串以'\0'结尾,而c++中string对象可以通过str.length()获得长度,因此string不必要加\0来结尾。string中'\0'只是一个普通的字符,并不代表字符串结束。 (string类型和字符串字面值不是一个概念)

1.3 string操作的相关函数
s.empty() //  Returns true if s is empty; otherwise returns false
s.size() // Returns number of characters in s
s[n] // Returns the character at position n in s; positions start at 0.
s1 + s2 //Returns a string equal to the concatenation of s1 and s2
s1 = s2 // Replaces characters in s1 by a copy of s2
v1 == v2 // Returns true if v1 and v2 are equal; false otherwise
!=, <, <=,
>, and >= //Have their normal meanings
string.size()返回string所含的字符个数,返回值类型为string::size_type,是一个无符号的类型,最好不要用int去接收,因为有时可能一个int不够表示一个stirng的大小。

1.4 string对象的关系操作符
*如果两个string对象的长度不同,且短的string对象与长的string对象的前面部分相匹配,则短的对象小于长的string对象
*如果两个string对象的字符不同,则比较第一个不匹配的字符
例如:
string substr = "Hello";
string phrase = "Hello World";
string slang = "Hiya";
then substr is less than phrase, and slang is greater than either substr or phrase.

1.5string对象跟字符串字面值(literal)的加法
string s1("hello");
string s2("world");
string s3 = s1 + ", " + s2 + "\n";
string对象跟字符串字面值的加法, 加号左右两边至少有一个是字符串对象才可以相加,string的“+”运算符返回一个string对象,因此s5中s1+","返回一个string对象不会报错
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

1.6string对象中单字符的处理函数  需要包含头文件cctype
isalnum(c) TRue if c is a letter or a digit.
isalpha(c) true if c is a letter.
iscntrl(c) true if c is a control character.
isdigit(c) true if c is a digit.
isgraph(c) true if c is not a space but is printable.
islower(c) true if c is a lowercase letter.
isprint(c) TRue if c is a printable character.
ispunct(c) TRue if c is a punctuation character.
isspace(c) true if c is whitespace.
isupper(c) TRue if c is an uppercase letter.
isxdigit(c) true if c is a hexadecimal digit.
tolower(c) If c is an uppercase letter, returns its lowercase equivalent; otherwise returnsc unchanged.
toupper(c) If c is a lowercase letter, returns its uppercase equivalent; otherwise returns c unchanged.

2 标准库类型:vector

vector是同一种类型对象的集合,每个对象都一个对应的整数索引值和string对象一样,标准库负责管理与存储元素的相关内存。
vector是一个 类模板(class template),vector本身不是类型,但vector<int>、vector<class type>是一种数据类型。

2.1.1vector对象的定义和初始化
构造函数:
vector<T> v1;     vector保存类型为T的对象,默认构造函数v1为空
vector<T> v2;     v2是v1的一个副本
vector<T> v3(n, i);     v3是包含n个值i的元素  例如: vector<string> svec(10, "hi");
vector<T> v4(n);            v4含有值初始化的元素的n个副本 
vector元素的内存连续存储,但最好不要对vector对象进行预先分配内存,更有效的方法是先初始化一个空的vector,然后再动态地增加元素。

2.1.2值初始化
如果没有给定的初始化时,标准库将自行提供一个元素的初始值进行初始化,具体值为什么由包含元素的数据类型决定。
1 内置类型元素标准库将用0来初始化
2 含有构造函数的类类型元素,将使用构造函数来初始化
3 既非内置类型也没有构造函数,标准库仍将进行初始化,第12章将讲到。

2.2.1 vector对象的操作
vector提供得了类似string对象的操作:
v.empty()<span style="white-space:pre">		</span>// Returns true if v is empty; otherwise returns false
v.size() <span style="white-space:pre">		</span>//Returns number of elements in v
v.push_back(t)<span style="white-space:pre">		</span>//Adds element with value t to end of v
v[n] <span style="white-space:pre">			</span>//Returns element at position n in v
v1 = v2<span style="white-space:pre">			</span>//Replaces elements in v1 by a copy of elements in v2
v1 == v2<span style="white-space:pre">		</span>//Returns TRue if v1 and v2 are equal
!=, <, <=,
>, and >=<span style="white-space:pre">		</span>//Have their normal meanings
2.2.2 vector对象的size、添加元素、下标操作
使用size_type需要制定类型的定义处:
vector<int>::size_type<span style="white-space:pre">	</span>// ok
vector::size_type <span style="white-space:pre">	</span>// error
使用push_back在尾部添加一个新的元素,类似string通过index(下标)访问元素
string word;
vector<string> text; <span style="white-space:pre">	</span>// empty vector
while (cin >> word) {
text.push_back(word); <span style="white-space:pre">	</span>// append word to text
}
 
 必须是已存在的元素才能用下标操作符进行索引,通过下标操作进行赋值时不会添加任何元素。 
2.3.1迭代器
除了使用下标访问容器,标准库还提供另一种方法:迭代器(iterator),迭代器是一种检查容器内元素病遍历元素的数据类型。(具体将在后边讲到)
每种容器类型都定义了自己的迭代器类型,如vector:
vector < int > :: iterator iter;
2.3.2begin和end操作
iter = ivec.begin() 返回迭代器指向的第一个元素
iter = ivec.end() 指向迭代器指向的“末端元素的下一个”,称为超出末端迭代器(off -the-end iterator ),他表明指向了一个不存在的元素(并不指向任意一个元素)。如果为空end和begin返回相同。
2.3.3 vector迭代器的自增和解引用运算
迭代器定义了一些操作来获取迭代器所指向的元素,并允许程序员要将迭代器从一个元素移动到另一个元素。
迭代器可以使用 解引用操作符(*)来访问所指向的元素。
*iter  = 0;    //iter所指向的元素赋值为0;
由于end操作返回的迭代器不指向任何元素,因此不能对他进行解引用或者则增操作;
2.3.4迭代器的其他操作
用==或者!=操作符来比较两个迭代器是否指向同一个元素,如果是则想等,否则不相等。
2.3.5 示例:
对类型为vector <int> 的ivec变量将所有元素重置为0:
1、使用下标完成
// reset all the elements in ivec to 0
for (vector<int>::size_type ix = 0; <span style=ix != ivec.size(); ++ix)  //尽量使用!=*.size()去判断
ivec[ix] = 0;
2、使用迭代器完成
// equivalent loop using iterators to reset all the elements in ivec to 0
for (vector<int>::iterator iter = ivec.begin();
iter != ivec.end(); ++iter)
*iter = 0; // set element to which iter refers to 0

const_iterator类型用于读取容器内元素的值,但不能对指向的元素进行写操作。const_iterator本身是可以使用自增或者加减操作,可变(即指向不同的元素)。

2.4.1迭代器的算术操作
iter + n;
iter - n;
迭代器加减操作产生一个新的迭代器,位置在iter所知元素之前(加)或之后(减)n个元素的位置。加或者减后必须指向vector中某个元素或者 末端后一个元素,加上或者减去的值类型应该是vector < T > :: size_type或者difference_type类型
iter1 - iter2
用来计算两个迭代器对象的距离,距离是名为difference_type的signed类型。
可以用迭代器算术运算符将迭代器指向某元素,例如下面语句直接定位于vector的中间元素:
vector<int>::iterator mid = vi.begin() + vi.size() / 2;
任何改变vector长度的操作都会使已存在的迭代器失效,例如在调用push_back后就不能依赖指向vector的迭代器的值了。

思考:
vector<int>::iterator mid = (vi.begin() + vi.end()) / 2;           //未定义的迭代器加法运算符                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
2.5 标准库 bitset

2.5.1 bitset对象的定义和初始化
bitset类型对象对象的区别在于其长度而不在其类型。在定义bitset时需要明确bitset含有多少位,长度值必须是常量表达式,或者已用常量值初始化的整型const对象。
初始化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 开始的&nbps;n 个位的副本。
bitset<32> bitvec;                 32bits, all zero 编号从0 ~ 31   0位开始是低位   32结束的位串是高阶位

2.5.2 用unsigned值初始化bitset对象

当用 unsigned long 值作为 bitset 对象的初始值时,该值将转化为二进制的位模式。而 bitset 对象中的位集作为这种位模式的副本。如果 bitset 类型长度大于 unsigned
long 值的二进制位数,则其余的高阶位将置为 0;如果 bitset 类型长度小于 unsigned long 值的二进制位数,则只使用 unsigned 值中的低阶位,超过 bistset 类型长度的高阶位将被丢弃。
在 32 位 unsigned long 的机器上,十六进制值 0xffff 表示为二进制位就是十六个 1 和十六个 0(每个 0xf 可表示为 1111)。可以用 0xffff 初始化 bitset 对象:
bitset<16> bitvec1(0xffff); // bits 0 ... 15 are set to 1
bitset<32> bitvec2(0xffff); // bits 0 ... 15 are set to 1;16 ... 31 are 0
上面的三个例子中,0 到 15 位都置为 1。由于 bitvec1 位数少于 unsigned long 的位数,因此 bitvec1 的初始值的高阶被丢弃。bitvec2 和 unsigned long 长度相同,因此所有位正好放置了初始值。bitvec3 长度大于 32,31 位以上的高阶位就被置为 0。

2.5.3 用string 对象初始化 bitset 对象
当用 string 对象初始化 bitset 对象时,string 对象直接表示为位模式。从 string 对象读入位集的顺序是从右向左(from right to left):
string strval("1100"); bitset<32> bitvec4(strval); 
bitvec4 的位模式中第 2 和 3 的位置为 1,其余位置都为 0。如果 string 对象的字符个数小于 bitset 类型的长度,则高阶位置为 0。
  string 对象和 bitsets 对象之间是反向转化的:string 对象的最右边字符(即下标最大的那个字符)用来初始化 bitset 对象的低阶位(即下标为 0 的位)。当用 string 对象初始化 bitset 对象时,记住这一差别很重要。

不一定要把整个 string 对象都作为 bitset 对象的初始值。相反,可以只用某个子串作为初始值:
string str("1111111000000011001101");
bitset<32> bitvec5(str, 5, 4); // 4 bits starting at str[5], 1100
bitset<32> bitvec6(str, str.size() - 4); // use last 4characters










































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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值