stl基础

C++

基础语法

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类型来一定程度上代替字符串

#include<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();

C++语法特性

动态开辟内存

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;
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇