基础语法
cout
是输出
cout<<"Hello World!"<<endl;
endl等于回车’\n’ 但细节有所不同
endl可以清空缓存
cin
相当于scanf
cin>>a
cin的速度更慢(哪怕关了同步)
1e5以上容易TLE
cin.getline
用于读一行,但需加入上限
cin.getline(cstring,1000);//gets(cstring);
getline
string line;
getline(cin,line);
bool
只能true和false
cin判断EOF
int n,m;
while(cin>>n>>m){
}
这种处理方式适用于以文件作为输入,或者在键盘手动输入文件结束符作为结尾标记。
在windows上输入EOF的方法为Ctrl+Z
其它平台上输入EOF的方法为Ctrl+D
string
C++提供了string类型来一定程度上代替字符串
值得注意的是cin/cout可以直接读写string,却不能读写字符数组
string类型还可以直接相加
string line;
while(getline(cin,line)){
int sum =0,x;
//创建字符串流
//像读取cin一样读取ss即可
stringstream ss(line);
while(ss>>x) sum+=x;
cout<<sum<<"\n";
}
string的拼接
string s1 ="Hello ";
string s2="World!";
s1.append(s2);
//Hello World!
string s3="Hello ";
string s4="Hello World!";
s3.append(s4,6,5);//从第六位开始,后面五位拼接
//Hello World
string s5="Hello ";
s5.append(10,'A');
//Hello AAAAAAAAA
strng s6=s1+s2;
//Hello World!World!
stringstream
#include<sstream>
<sstream>定义了三个类:istringstream ostringstream stringstream
分别用来进行流的输入、输出和输入输出操作
<sstream>主要用来数据类型转换,由于<sstream>使用string对象来代替字符数组,避免了缓冲区溢出的危险
而且,因为传入参数和目标对象的类型会被自动推导出来,所以不存在错误的格式化符号的问题
示例:
#include<string>
#include<sstream>
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
stringstream sstream;
string strResult;
int nValue = 1000;
//将int类型放入输入流中
sstream<<nValue;
//将sstream中抽取前面插入的int类型的值,赋给string类型
sstream>>strResult;
cout<<strResult<<endl;
print("%s",strResult.c_str());
return 0;
}
结果如下
1000
1000
它还可以用于多个字符串的拼接
stringstream sstream;
//多个字符串放入
sstream<<"first"<<" "<<sstream.str()<<endl;
sstream<<" second string";
cout<<sstream.str()<<endl;
//清空sstream
sstream.str("");
stream<<"third string";
cout<<stream.str()<<end;
结果如下:
first string,second string
third string
因此我们可以知道:
-
可以使用str()方法,将stringtream类型转换为string类型
-
可以将多个字符串放入stingstream中,实现字符串拼接的目的
-
如果想清空stringstream,必须使用sstream.str(“”)方法 ,clear()适用于进行多次数据类型转换的情况,如下
stringstream的清空
清空stringstream有两种方法 clear()和str(“”)
clear()如下:
//插入字符串
sstream<<"456";
//转换为int类型
sstream>>first;
//多次转换前必须清空
sstream.clear();
动态开辟内存
int* number = new int;
int* arr =new int[100];
int* carr =(int*)malloc(100*sizeof(int));
c++不支持边长数组
int n=10;
int num[n];
这只在c合法
引用
c++中用&来创建引用。可以把引用当作一个不能改变指向对象的指针。
引用一般在函数传参的时候才用
void swapint(int& a, int& b)
{
int c=a;
a=b;
b=c;
}
int main(){
int a=1,b=2;
swapint(a,b);
}
函数重载
C++中,函数是以函数名+参数列表来区分的
支持两个函数名字相同,参数不同
struct
结构不再和C语言中需要加struct,可以直接使用结构的名字
struct node{
int number;
node* next;
};
node* head;
struct可以加入与结构同名,无返回值的构造函数,在创建的时候会自动调用构造函数。
struct node
{
int number;
node* next;
node(int nuu = 0, node* nextt= NULL){
number=nuu;
next =nextt;
}
}
这样不必重复初始化
不初始化为默认值,初始化为初始化值
int main(){
node a= node(0);
node *b = new node(1,&a);
}
vector数组
可以被看作作超级数组,既可以用下标访问又可以像链表一样动态改变长度
要加头文件vector
出入组
vector<int> arr1(100);
int arr2[100];
vector<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(4);
出去是
pop_back();
顺序类似于栈
迭代器(iterator)
vector也可以用指针遍历,STL中的指针被称为迭代器
vector<int>::iterator p1 = arr1.begin();//指向头一个元素
int* p2 =arr2;//等价
p++;//移到下一个位置
遍历
与普通数组差不多
不过输入不同,迭代器不同
for( p1 =arr1.begin(); p1 != arr2.end();p1++ ){
cout<<*p1<<endl;
}//遍历并输出每一个元素
常见操作
list.size();//数组元素个数
list.clear();//一键清空数组
list.empty();//数组是否为0
list.begin();//首元素迭代器
list.end();//数组最后一个元素的下一个迭代器,实际是不存在的
list.erase(p1);//删除数组某个迭代器所在位置的数字
list.push_back(1);//往后添加
list.pop_back();//出栈
string基本操作
string str = "hello";//注意str是字符串名
str.length(); str.size();// O(n)
str.insert(1,"aaa");//在下标为1处插入一个字符或字符串 插在后面 O(1)
str.insert(str.begin(),'a');//效果差不多 O(n)
str c_str();//返回C语言字符串,用于printf O(n)
str.append(str2);//把str2追加到后面 O(n)
str.compare(str2);//strcmp(str,str2)
str == str2;//strcmp(str,str2)==0;
str += str2;//str.append(str2);
str += 'a';//str.push_back('a');
sort快排
实际上是根据元素量进行选择
可以自定义比较函数
bool cmp(int a, int b){
return a>b;
}
sort(arr.begin(),arr.end(),cmp);//这样就可以得到降序
int a[]={45,12,34,77,90,11,2,4,5,55};
sort(a,a+10);
甚至可以排序结构体
不过需要自己写比较函数
其他algorithm函数
//取最大最小
min(1,2);max(1,2);
//数组最大最小指针 O(n)
min_element(arr.begin(),arr.end());
max_element(arr.begin(),arr.end());
//把数组中第n小的(从0开始算),放到第n个位置
//类似快排,并且保证左边数比它小,右边数比它大
//O(n)
nth_element(arr.begin(), arr.begin()+n, arr.end());
//交换任意两个同类型变量
swap(arr[0],arr[1]);
//反转数组
//O(n)
reverse(arr.begin(),arr.end());
//假设arr已经排好序
//使arr中不出现重复数字
//返回去重数组后结束指针
//其实就是重复的被放在了最后无效的
//O(n)
int nl= unique(arr.begin(),arr.end()) - arr.begin();
//需要排好序后才用
lower_bound一般用来二分查找
灵活运用可以得到有序数组中第一个比查找值大、小的值
int f = lower_bound(arr.begin(),arr.end(),2)-arr.begin();
int l = upper_bound(arr.begin(),arr.end(),2)-arr.begin();
stack
stack<int> sta;
sta.push(1);
int t = sta.top();
sta.pop();
sta.empty();
sta.size();
queue
包含queue和priority_queue
queue<int> que;
int f = que.front();
....//基本同stack
priority_queue<int> que2;//优先队列 .....
set
包含set和multiset
set用来保存很多元素,并且能在O(logn)的时间查找、删除、添加元素
set自带去重,mulitiset允许重复,count可以获取某个元素数量
set是用某种平衡树实现的
set<int> st;
st.insert(1);
st.fing(1);
st.erase(1);
multiset<int> mst;
mst.insert(1);
mst.insert(1);
mst.count(1);//2
map
pair<string,int> ori;
ori = make_pair("sss",110);//构造一对
//map
map<string,int> sth;
sth["小明"]=170;
sth.insert(ori);//把ori插进去
查找元素
当所查找的关键key出现时,它返回数据所在对象的位置,如果沒有,返回iter与end函数的值相同。
// find 返回迭代器指向当前查找元素的位置否则返回map::end()位置
iter = mapStudent.find("123");
if(iter != mapStudent.end())
cout<<"Find, the value is"<<iter->second<<endl;
else
cout<<"Do not Find"<<endl;
删除元素
//迭代器刪除
iter = mapStudent.find("123");
mapStudent.erase(iter);
//用关键字刪除
int n = mapStudent.erase("123"); //如果刪除了會返回1,否則返回0
//用迭代器范围刪除 : 把整个map清空
mapStudent.erase(mapStudent.begin(), mapStudent.end());
//等同于mapStudent.clear()
map大小
int msize=mapStudent.size();
bitset
biset是只由0 1构成的数组,占用空间小
bitset不仅可以和数组一样用下标访问,还可以位运算
状态压缩动态规划详解/
unordered_map/set
这两种数据结构不允许按大小遍历,但可以O(1)访问和添加
基于hash
万能头文件
#include<bits/stdc++.h>
一些细节
1s运算大约1e8
G++输出double要用%f
数据范围在1e9内是 可以
const int INF = 0x3f3f3f3f;
表示无穷大
文件IO
重定向
最简单的文件IO
在main的入口处添加
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
上述语句使得scanf从input.txt读入 printf写入output
在比赛中通常这么用
int main(){
#define LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt,"w",stdout);
#endif
}
fopen
若比赛禁用重定向,可以用fopen
FILLE *fin,*fout;
fin=fopen("data.in","rb");
fout=fopen("data.out","wb");
int x,n=0,min=INF,max=-INF,s=0;
while(fscanf(fin,"%d",&x)==1){
s+=x;
if(x<min) min=x;
if(x>max) max=x;
n++;
}
fprintf(fout,"%d %d %.3f",min,max,(double)s/n;
fclose(fin);
fclose(fout);
总结
重定向和fopen各有优劣
重定向简单,但不可以同时标准输入输出
fopen繁琐,但灵活,若要改为标准输入输出,只需要
fin=stdin;
fout=stdout;