C++大学基础教程笔记(三)
66.文件处理
模式 描述
ios::app 将输出数据添加到文件的结尾
ios::ate 将一个文件打开作为输出文件,并移动到文件尾(一般用来为一个文件添加数据)
ios::in 打开一个文件作为输入文件
ios::out 打开一个文件作为输出文件
ios::trunc 如果文件有内容则将文件内容丢弃(这是ios::out的默认设置)
ios::binary 打开一个文件进行二进制输入输出
实例 ofstream outClientFile("client.dat", ios::out);
67.istream和ostream都提供了成员函数来重定位文件定位指针。在istream中,为seekg("seek get");在ostream中,为seekp("seek put")。例如:inClientFile.seekg(n); //默认:ios::beg
inClientFile.seekg(n, ios::cur);
inClientFile.seekg(n, ios::end);
68.成员函数tellg和tellp分别用来返回当前的指针位置。 例:long location = fileObject.tellg();
69.利用ostream的成员函数write写入字节数据
当把一个整数number写入文件时,语句
outFile << number;
对于一个4字节的整数最少可以打印1位,最多可以打印11位(10个数字加上1个符号位,每位需要一个字节的存储空间),可以使用语句代替:
outFile.write(reinterpret_cast<const char *>(&number), sizeof(number)); 这条语句使用二进制形式写入整数的4个字节。
70.reinterpret_cast操作是在编译阶段完成的,它不会改变指针所指对象的值。相反,它要求编译器将操作数重新解释为目标类型。
reinterpret_cast是与编译器相关的,程序在不同的平台上运行起来可能不一样。所以除非有绝对的必要,都不应该使用 reinterpret_cast运算符。
71.string类和字符串流处理
试图将一个int或者char通过声明初始化或者在构造函数中转化为一个string,都会导致编译错误。
实例
string error1 = 'c';
string error2('u');
string error3 = 33;
string error4(8);
但在一个赋值语句中,允许将单个字符赋给一个string对象:
string1 = 'n';
72.常用的成员函数:
复制:targetString.assign(sourceString, start, charactersNumber);
sourceString是被复制对象,start是开始下标,charactersNumber是要复制的字符个数
targetString.append(), targetString.at(), targetString.compare(),
子串
targetString.substr(int x1, int x2); 第一个参数指定想获取的子串的开始下标,第二个参数指定子串的长度。
交换
targetString.swap(sourceString);实现两个字符串交换。
int result = targetString.compare(2, 5, string1, 0, 5); 比较targetString和sting1的一部分。前两个参数分别代表targetString中要跟sting1比较的那部分的开始下标和长度,最后两个参数同理。compare()函数还有1个参数和3个参数的版本
int result = targetString.compare(string1);
int result = targetString.compare(0, string1.length(), string1);
73.string类的特征
string类提供了收集字符串的大小、长度、容量、最大长度和其他特征的成员函数。容量(capacity)是指在不获取更多内存的情况下字符串所能存储的最大字符数。最大长度是一个字符串所能拥有的最大字符数目。如果超出这个值,将抛出一个length_error异常。成员函数:stringRef.capacity(),stringRef.resize(), stringRef.max_size(), stringRef.size(), stringRef.length(),stringRef.empty() stringRef.resize(stringRef.length() + 10)将stringRef的长度增加10个字符。增加的元素被设置为空字符。
74.查找字符串中的子串和字符
string1.find("is"), 在string1中找到字符串“is”。如果找到,则返回该字符串在string中的开始下标。
string1.rfind("is"), 反序查找(也就是从右到左)。
string1.find_first_of("misop"), 查找“misop”中的字符最先出现在string1中的位置。从string1的头部开始搜索。 string1.find_last_of("misop"), 查找“misop”中的字符最后出现在string1中的位置。从string1的尾部开始搜索。
75.在字符串中替换字符
string1.erase(n), 删除从(包含)位置62到string1末尾的所有内容。
string1.replace(pos, 2, "xxxx;;yyy", 5, 2), string1.insert()
76.转换为C风格的基于指针的char *字符串 char *ptr = 0; ptr = string1.data();或者string1.c_str()
77.字符串流处理
首先必须包含<sstream>和<iostream>头
ostringstream对象使用一个string对象来存储输出数据。类ostringstream的成员函数str返回字符串的副本。
实例
ostringstream outputString; cout << outputString.str();
78.STL容器的通用函数 描述
默认构造函数
复制构造函数
析构函数
empty 容器中没有元素则返回true
insert 在容器中插入一个元素
size 返回当前容器中的元素个数
operator= 把一个容器赋值给另一个
operator< 当一个容器小于第二个容器则返回true;否则返回false
operator<=
operator>
operator>=
operator==
operator!=
swap 交换两个容器中的元素 只适用首类容器的元素
max_size 返回一个容器中的最大元素个数
begin 有两个版本,返回引用容器中第一个元素的iterator或const_iterator
end 有两个版本,返回引用容器末端之后位置的iterator或const_iterator
rbegin 有两个版本,返回引用容器末端位置的reverse_iterator或const_reverse_iterator
rend 有两个版本,返回引用容器第一个元素之前位置的reverse_iterator或const_reverse_iterator
erase 删除容器中的一个或多个元素
clear 删除容器中的所有元素
79.标准库容器的头文件
<vector>
<list>
<deque>
<queue> 包含queue和priority_queue
<stack>
<map> 包含map和multimap
<set> 包含set和multiset
<valarray>
<bitset>
80.迭代器#include <iterator>
使用istream_iterator用于输入,使用ostream_iterator用于输出
实例:
int main()
{
cout << "Enter two integers: ";
istream_iterator<int> inputInt(cin);
int number1 = *inputInt; ++inputInt; int number2 = *inputInt;
ostream_iterator<int> outputInt(cout);
cout << "The num is: ";
*outputInt = number1 + number2; //copy(listRef.begin(), listRef.end(), outputInt);
cout << endl;
}
81.迭代器类型
类型 描述
输入迭代器(input) 用于从容器读取元素。输入迭代器每次只能向前移动一个元素。输入迭代器只支持一遍扫描算法, 不能使用相同的输入迭代器两次遍历一个序列容器。
输出迭代器(output)
正向迭代器(forward) 综合输入和输出迭代器的功能,并能保持他们在容器中的位置
双向迭代器(bidirectional) 正向迭代器基础上增加了向后移动的功能,支持多遍扫描算法
随机访问迭代器(random access) 在双向迭代器基础上增加了直接访问容器中任意元素的功能,即可以向前或向后跳转任意个元素
对于输入和输出迭代器,不能在保存迭代器之后再使用保存的值。
82.迭代器操作 注意:对每种迭代器的操作包括了前面类型的操作
适用所有迭代器的操作
++p
p++
输入迭代器
*p
p = p1
p == p1
p != p1
输出迭代器
*p
p = p1
正向迭代器
正向迭代器提供了输入和输出迭代器的所有功能
双向迭代器
--p
p--
随机访问迭代器
p += i
p -= i
p + i或i + p
p - i
p - p1
p[i]
p < p1
p <= p1
p > p1
p >= p1
83.vector不对下标进行自动越界检查,不过vector类模板提供了一个成员函数at来实现这一功能
84.在vector的尾部进行插入操作是高效的。vector只是简单的变长来适应新加入的元素。但是在vector的中间插入或删除元素是低效的。
85.需要经常在容器两端进行插入和删除操作的应用进程通常使用deque,需要经常在容器两端或中部进行插入和删除操作的应用进程通 常使用list
86.只有随机访问迭代器支持<运算符。在测试是否到达容器末尾时最好使用!=运算符和end函数。
87.list序列容器
list类模板实现了一个双向链表——list容器中的每个节点都含有一个指向前一个节点和一个指向后一个节点的指针。
list类模板还提供了9个其他的函数:splice, push_front, pop_front, remove, remove_if, unique, merge, reverse, sort
实例:
list< int > values;
list< int > otherValues;
//删除otherValues的中元素,并把它们插入到第一次迭代器参数指定的位置之前
values.splice(values.end(), otherValues);
//把otherValues中的所有元素删除,并把它们按已排序的顺序插入到value中
values.merge( otherValues );
//删除list中的第一个元素和删除list中的最后一个元素
values.pop_front();
values.pop_back();
//删除list中重复的元素
values.unique();
88.关联容器
STL的关联容器可以通过关键字来存取元素。4种关联容器是multiset, set, multimap, map。每种关联容器都按已排序的方式保存着 所有的关键字。
multiset和set类提供了控制数值集合的操作,其中元素就是关键字,multiset和set之间的主要差别是multiset允许重复的关键字 multimap和map类提供了处理与关键字相关联的值(这些值有时作为映射的值)的功能。
还提供了其他的成员函数,find, lower_bound, upper_bound, count
#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>
using namespace std;
typedef multiset< int, less< int > > Ims;
int main()
{
const int SIZE = 10;
int a[SIZE] = {7, 22, 9, 1, 18, 30, 100, 22, 85, 13};
Ims intMultiset;
ostream_iterator< int > output( cout, " " );
//函数count(可用于所有关联容器)来计算multiset中值为15的元素个数
cout << "There are currently " << intMultiset.count(15) << " values of 15 in the multiset\n\n";
//向multiset中插入值15
intMultiset.insert(15);
intMultiset.insert(15);
cout << "After inserts, there are " << intMultiset.count(15) << " values of 15 in the multiset\n\n";
//定义与此容器类相关的迭代器
Ims::const_iterator result;
//用find确定值15的位置,返回一个指向最早出现的那个搜索值的迭代器
result = intMultiset.find(15);
if(result != intMultiset.end())
cout << "Did not find value 20\n";
intMultiset.insert(a, a + SIZE);
cout << "\nAfter insert, intMultiset contains:\n";
copy(intMultiset.begin(), intMultiset.end(), output);
//函数lower_bound和upper_bound(可用于所有关联容器)来确定multiset中22最早出现和
//最后出现的位置
cout << "\n\nLower bound of 22: " << *(intMultiset.lower_bound(22));
cout << "\nUpper bound of 22: " << *(intMultiset.upper_bound(22));
//pair类的实例p,关联一对值,有两个成员变量first和second
pair< Ims::const_iterator, Ims::const_iterator > p;
p = intMultiset.equal_range(22);
cout << "\n\nequal_range of 22: " << "\n Lower bound: " << *(p.first) << "\n Upper bound: " << *(p.second);
cout << endl;
}
89.multimap关联容器
实例:
typedef multimap< int, double, less< int > > Mmid;
Mmid pairs;
//使用函数insert在multimap中插入一个新的关键字/值对,表达式Mmid::value_type(15, 2.7)创建了一个pair对象,
//它的成员first为int关键字15,成员second为double值2.7
pairs.insert( Mmid::value_type( 15, 2.7 ) );
//输出容器中的值
for(Mmid::const_iterator iter = pairs.begin(); iter != pairs.end(); ++iter)
cout << iter->first << "\t" << iter->second << "\n";
90.map关联容器
Mid pairs;
//通过下表运算符创建一个新的关键字/值对,如果关键字25中已经有值存在,则将用新值替换
pairs[25] = 999.9;