c++输入输出流
标准I/O 从键盘输入数据到屏幕
文件I/O 从磁盘文件输入数据
串I/O 对内存中指定的空间进行输入输出,通常指定一个字符数组作为存储空间。
标准输入流
char c = cin.get();//读一个字符,换行会在缓冲区中
char buf[1024];
cin.get(buf,1024);//两个参数,读一个字符串,不会把换行符拿走,遗留在缓冲区中
cin.getline(buf,1024);//把换行符读取,并且扔掉
cin.ignore();//忽略,没有参数代表忽略一个字符
cin.ignore(n);//忽略n个字符
c = cin.peek();
c = cin.get();//偷窥一眼,再放入缓冲区,peek()函数也就是读了一次再放回去了
c = cin.get();
cin.putback(c);//将拿走的放回缓冲区
案例 让用户输入1到10的数字,输入有误就重新输入
main()
{
int num;
while(true){
cin >> num;
if(num <= 10 && num >= 1){
cout << num << endl;
break;
}
cin.clear;//重置标志位
cin.sync;//清空缓冲区
cout << " 标志位 " << cin.fail() << endl;//标志位0正常,标志位1不正常,假如输入了一个字母,就会出现标志位错误
}
}
标准输出流
cout.flush();//刷新缓冲区,linux下有效
cout.put('a').put('b');//向缓冲区写字符,可以链式编程
char buf[1024] = "....";
cout.write(buf,strlen(buf));//从buffer中写n个字节到输出流
流对象有关成员函数
还有更多…
控制符格式化输出
#include <iomanip>//使用头文件
文件读写
#include <fstream>
//写文件
ofstream ofs;
ofs.open("test.txt",ios::trunc | ios::out);//后期指定
ofstream ofs("test.txt",ios::trunc | ios::out);//前期指定
if(!ofs.is_open())
cout << "fail";
ofs << "....." << endl;//写入数据
ofs.close();
//读文件
ifstream ifs("test.txt",ios::in);
ifs.open("test.txt",ios::in);
if(!ifs.is_open())
cout << "fail";
//第一种方式
char buf[1024]
while(ifs >> buf)//按行读取
{
cout << buf << endl;
}
//第二种方式
while(!ifs.eof())//读到文件尾部
{
ifs.getline(buf,sizeof(buf));
cout << buf << endl;
}
//第三种方式不推荐
char c;
while((c = ifs.get()) != EOF)
{
cout << c;
}
ifs.close();
STL(标准模板库)
广义上分为:容器,算法,迭代器
容器和算法之间通过迭代器无缝连接
六大组件:容器,算法,迭代器,适配器,仿函数,空间配置器
容器通过空间适配器取得数据存储空间,算法通过迭代器存储容器的内容,仿函数可以协助算法完成不同策略的变化,适配器可以修饰仿函数。
vector<int> v;
vector<int>::iterator itbegin = v.begin();
vector<int>::iterator itend = v.end();
while(itbegin != itend)
{
cout << *itbegin <<endl;
++itbegin;
}//第一种
for(vector<int>::iterator it = v.begin(); it != v.end(); ++it){
cout << *it <<endl;
}//第三种,利用算法
void myprint(int v){
cout << v << endl;
}
for_each(v.begin(),v.end(),myprint);
嵌套
vector<vector<int>> v;
for(vector<vector<int>>::iterator it = v.begin(); it != v.end(); ++it){
for(vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); it++){
cout << (*vit) << endl;
}
}
string容器
赋值操作
string str;//默认构造
string str2(str);//拷贝构造
string str3 = str;
string str4 = "abcd";
string str5(10,'a');//有10个a
str = "hello";
str3.assign("abcdef",4);//将"abcd"赋值给str3
str2.assign(str,0,3);//把字符串str从0开始3个字符赋值给str2 (字符串是从0开始索引的) "hel"
存取操作
string s = ".......";
for(int i = 0; i < s.size(); i++){
cout << s[i];
cout << s.at(i);
//[]访问越界直接挂掉,at会抛出异常
}
try{
cout << s.at(100);
}catch(out_of_range &e){
cout << e.what() << endl;
}
拼接查找操作
string s1 = "i";
string s2 = "m"
s1 += s2;//拼接
s1.append("zzz");//拼接 imzzz
int pos = s1.find("m");//查找m的位置(pos=1),找不到返回-1
int pos = s1.rfind("m");//(pos依旧唯一),只是内部查找顺序相反
s1.replace(1,3,"1111");//结果i1111z,从1开始的三个字符改为1111,不是只能改三个字符
比较操作
string s1 = "abc";
string s2(s1);
if(s1.compare(s2) == 0)//在等于时返回0,
{
cout << "相等";
}//大于时返回1,小于时返回-1
//比较区分大小学,参考字典序,排在前面的小
string子串
string s1 = "12345";
string s2 = s1.substr(1,3);//返回从1开始数的3个字符
插入和删除
string s1 = "aaaaaaa";
s1.insert(1,"111");//插入,a111aaaaaa
//删除111
s1.erase(1,3);//从1开始删除3个字符
*string和char 转换
string s1 = "123456";
const char *p = s1.c_str();//转换为char *
string s2(p);//转换为string
//const char *可以隐式类型转换为string
//string不能隐式类型转换为char *
注意重新分配内存的问题
vector容器
vector容器的扩张策略不是两倍。
所谓的动态增长,并不是在原有空间之后接上新的空间(因为无法保证原空间之后尚有可配置的空间),而是一块更大的内存空间,然后将原数据拷贝到该内存空间,并释放原空间,因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就失效了。
int arr[10] = {...};
vector<int> v(arr,arr + sizeof(arr)/sizeof(int));
vector<int> v2(v.begin(),v.end());
vector<int> v3(n,elem);//有n个elem分配给v3
vector<int> v4;
v4.assign(v3.begin(),v3.end());
v4.swap(v2);//v2和v4相互交换
v4.size();//大小(不是容量)
if(v4.empty())
cout << "NULL";
v4.resize(10,num);//重新指定大小为10,如果多了的数默认为0,当然可以添加参数num,多了的数就位num。变短了就会删除超出的元素
v4.capacity();//容量
巧用swap收缩空间
vector<int>(v).swap(v);
//vector<int>(v)利用v初始化匿名对象,交换之后,系统会自动回收匿名对象
**reserve(int len)**容器预留len个长度,预留位置不初始化,元素不可访问。
vector<int> v;//
v.reserve(10000);//直接开辟10000的容量,不用多次开辟,提高效率
for(int i = 0; i < 10000; i++)
//cin >> v[i];//错误,不能这么使用
v.push_back(i);//正确
vector<int> v;
v.front();//第一个元素
v.back();//最后一个元素
v.insert(v.begin(),2,100);//第一个参数为1个迭代器,参2为插入几个数,参3为具体的数
v.pop_back(v);//删除尾部元素
v.erase(v.begin());//删除一个
v.erase(v.begin(),v.end());//删除区间内的
v.clear();//清空所有数据
//逆序遍历,需要使用逆序迭代器reverse_iterator
for(vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
//vector迭代器是随机访问迭代器,支持跳跃式访问
vector<int>::iterator it = v.begin();
it = it + 3;
//如果上述写法不报错就为随机访问迭代器
deque容器
双端数组
//很多与vector相同的api
deque<int> d;
deque::const_iterator it = d.begin();
d.push_front();//头插
d.pop_front();//头删
bool cmp(int v1,int v2)
return v1 > v2;