C转C++记录
最近的博客都是很久之前完成的内容,直接从本地搬上来的
部分来源:柳婼大佬 柳婼 の blog – 我不管,反正我最萌~ (liuchuo.net),还有一些我作为纯小白在用C++刷题时学到的新语法特性
一、基本篇
1. 基础部分
这部分之前已有了解甚至在C中已经接触使用过了,不多赘述
#include<iostream>/*输入输出流的头文件*/
// #include<cstring>
// #include<cmath>
using namespace std;/*命名空间*/
int main(){
bool flag = true;
// bool flag0 = True;不合法
bool flag0 = -1;//只要非0都是1
cout<<flag0<<endl<<flag;
// _getch();
return 0;
}
如果没有命名空间,所有std命名空间的函数(cin, cout, endl等等)都要声明一下,会变成这样:
#include<iostream>
int main(){
int n;
std::cin >>n;
std::cout << "rumen\t" << ++n << std::endl;
/*cin,cout比原来两个底层scanf和printf耗时更多,如果TLE就换回原来的*/
return 0;
}
然后是关于define和const的异同(才知道const是C++特有用法)
#include<iostream>
using namespace std;
#define MAX 200
/*define是各种意义上的单纯的替换,只要合法啥都能替换*/
int main(){
const int a = 10;/*声明一个常量,不可以被改变*/
cout << a <<endl;
return 0;
}
2. string类、getline函数、s.length()
string类和getline函数
直接上代码
#include<iostream>
#include<string>
using namespace std;
int main(){
string s = "hello";
string s1 = " world!";
string s3 = s + s1;
cout << s3 << endl;
string a;
// cin >> a;
/*上面这种输入方式如果有前导白色空格字符(空格、制表或者换行),后面的内容就会进缓冲区
并且如果后面还有输入的话用户根本没机会输入(不是输入后没读进去,是直接跳过下一次的输入)
cin会把之前缓冲区的剩余字符读出来*/
getline(cin,a);
/*上面用这种写法可以读取一整行的内容,只要没有换行就能读取*/
cout << a << endl;
return 0;
}
关于getline有些小东西,它的形式是这样的:
getline(cin, inputLine);
在C++中本质上有两种getline函数:
第一种:在头文件
第二种:在头文件
s.length()长度
cout << s.length() << endl;
length()是对象s的一个方法
s.substr(n,m)或s.substr(n)子串
s = "wojiaozhangyuekai";
s_sub = s.substr(4,3);
cout << s_sub;
/*会输出从脚标为4的字符开始连着三个字符串"aoz",
如果是s.sub(4)的话会直接输出到最后,"aozhangyueyuekai"*/
别忘了字符是从0开始的
3.结构体
#include<iostream>
using namespace std;
struct stu{
string name;
int age;
};
int main(void){
stu a[10];
/*不难发现C++可以直接删掉struct,不需要typedef*/
}
4.引用&和传参
#include<iostream>
using namespace std;
void plus(int &a){
a += 1;
}
int main(void){
int a = 4;
plus(a);
cout << a <<endl;
}
会发现输出的是5,也就是说引用的话是直接把值扔进去了。不会有传参时候的形参实参的转变。
(话说直接把&理解成取地址也能说得通)
二、STL篇
vector,set,map,stack,queue都是容器类,可以用一些通用的方法(和字符串类似),比如vector.size()来获取长度
顺便,适用于大多数OJ的万能头文件
#include<bits/stdc++.h>
1.vector动态数组/不定长数组
说起来不定长数组和向量本来就是一回事。用到的头文件是
#include<vector>
vector也在namespace std中
#include<iostream>
#include<vector>
using namespace std;
int main(void){
vector <int> v;
cout << v.size() <<endl;//可以发现没有初始化的vector的长度是0
vector <int> k(10,2);//这个的意思是size是10(10个元素),每个元素都是2
/* k(10,0)相当于k(10) */
vector <int> zyk;
zyk.resize(10);//此时再看的话就会发现size变成了10
/* resize方法的初始化也会把元素初始化为0 */
for(int i=0;i<10;i++){
zyk[i]=i;
}//这个循环就给zyk每个元素一个值
zyk.push_back(100);//这样可以给zyk后面加一个元素,值为100
return 0;
}
resize函数的实际用途其实更方便,但是好像只能扩建不能缩减,缩减之后还是可以访问,只不过size会变小。
resize() 函数( void resize( size_type size, TYPE val ) )改变当前vector的大小为size,且对新创建的元素赋值val,省略val就默认为0
迭代器(注意只能C++11才能用
for(auto p=zyk.begin();p!=zyk.end();p++){
cout << *p << " ";//p就是指针
}
/* begin就是最前面的元素,end是终止符 */
但是C98没有auto声明,所以为什么不试试自己写个迭代器呢
for(int i=0;i<zyk.size();i++){
cout << zyk[i] << endl;
}
好像也能跑
2.set组,集合
头文件、插入,find,end
#include<set>
#include<iostream>
using namespace std;
int main(void){
set <int> s;/*这个不能像vector一样初始化,因为集合中的元素是有互异性的,你也不能说这个集合里有多个元素但是不知道是多少*/
/*因此集合创建之初是没有元素的,要用到insert方法*/
s.insert(2);
s.insert(1);
s.insert(3);
/*输入元素之后会自动从小到大排序*/
cout << (s.find(2)!=s.end()) <<endl;//注意整体有括号,并且输出的是一个布尔值,能找到2所以输出1
cout << (s.find(4)!=s.end()) <<endl;//因为没有找到4这个元素,所以返回值和end()一样,就是集合的最后一个元素的后一个的地址
/*s.find()返回的是指针指向的地址*/
s.erase(1);//这样就删除了元素1
cout << (s.find()!=s.end()) <<endl;//因为删除了
return 0;
}
在支持C++11版本的编译器上也可以用那个迭代器遍历,没有支持的话自己写一个
/*C++11版本的*/
for(auto p=s.begin();p!=s.end();p++){
cout << *p << " ";
}
3.map键值对
添加,访问,遍历,获取长度
#include<iostream>
#include<map>
using manespace std;
int main(){
map <string,int> m;/*前面是键,后面是值*/
m["hellow"]=114514
m["world"]=834757
/*键值对在输入后也会自动排序,通过键的字典序(字符对应的是ASCII码的字典序)来从小到大排序*/
/*还有我们熟悉的迭代器*/
for(auto p=m.degin();a!=m.end();p++){
cout << p->first << : << p->second << endl;
/*所以p是一个结构体指针,键值对其实是个结构体,p可以直接访问结构体中的元素*/
}
cout << m["hellow"] << endl;
/*如果不存在这个键,那么会输出0*/
}
4.stack栈
#include<iostream>
#include<stack>
using namespace std;
int main(){
stack <int> s;
s.push(1);//压栈
s.push(2);
s.push(3);
s.pop();//出栈
/*输出栈顶元素*/
cout << "栈顶元素:" << s.top();
cout << "栈的长度:" << s.size();
//栈不支持迭代器,队列也一样
}
关于迭代器:这么写是不对的:
for(auto p=s.begin();p!=s.end();p++){
cout << *p <<end;
}
因为我们只能访问和操作栈顶
5.队列
先进先出
#include<iostream>
#include<queue>
using namespace std;
int main(){
queue <int> q;
q.push(5);
q.push(1);
q.push(4);
cout << "队首是:" << q.front() << endl;
cout << "队尾是:" << q.back() << endl;
q.pop();//从队首出队
}
6.unordered_map和unordered_set
这是C++11的特性,蓝桥杯不要用哦!
#include<unordered_map>
#include<unordered_set>
#include<iostream>
int main(){
unordered_map <string,int> m;
unordered_set <int> s;
/*排序和输出有规律但是和哈希有关,这么做只是为了节省时间*/
}
三、进阶算法
1.bitset位运算
bitset是一个字符数组,只有1和0,它从二进制的低位到高位依次排列
用来处理二进制的话很方便
#include<bitset>
#include<iostream>
using namespace std;
int main(){
bitset <5> b(19);/*5表示二进制数最多是5位,19表示转化为十进制数是19*/
bitset <5> k;/*什么都不说就初始化为0*/
bitset <5> y("101")/*意思是最低几位就是"101",前面都是0*/
bitset <5> z(s,pos,n)//就是字符串的操作,从s[pos]开始,取n位长度。不常用
cout << b << endl; /*注意因为是要表示数字,所以输出的是先是高位再是低位,这和一般的字符串不同*/
for(int i=0;1<5;i++){
cout << b[i] << " ";
}/*这里是先输出低位再输出高位,就和之前的输出是反着的*/
cout << "数位中是否有1:" << b.any() << endl;
cout << "数位中是否不存在1:" << b.none() << endl;
cout << "数位中1的个数:" << b.count() << endl;
cout << "下标为i的元素是不是1:" << b.treat(i) << endl;/*下标从低位的0开始*/
y.flip();//所有位都取反
y.flip(2);//只有下标为2(就是第三位)的那个数取反
y.reset(3);//下标为3的位归0
y.reset();//全部归0
unsigned long a = b.to_ulong();//二进制转十进制
}
2.algorithm库和sort
#include<iostream>
#include<algorithm>
#include<vector>
bool cmp(int x, int y){
return x>y;//只能用大于或小于不能等于(会造成越界!?)。cmp相当于快排的判断,返回false时会交换两个指针的数
}
using namespace std;
int main(){
vector <int> m(10);
for(int i=9;i>=0;i--) m[i]=10-i;
sort(m.begin(),m.end());//别忘记m.end()是最后一项的后一个,sort不会排右边的这个。默认从小到大排序
sort(m.begin(),m.end(),cmp);//cmp是自定义的排序函数,就是compare的简写,注意定义好之后不需要打括号的
/*如果返回值为真,就把x放在y前面;反过来说也对,想要x放在y前面就让返回值为真*/
}
例题:比较学生信息排序
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct stu{
string name;
int age;
};
bool cmp(stu a,stu b){
if (a.age != b.age) return a.age < b.age;
else return a.name < b.name;
}
int main(){
stu s[3];
for(int i=0;i<3;i++) cin >> s[i].name >> s[i].age;
sort(s,s+3,cmp);
for(int i=0;i<3;i++) cout << s[i].name << " " << s[i].age << endl;
}
3.cctype
就是c语言中的ctype,可以对char进行操作
char c = 'a';
isalpha(c);//字母
islower(c);//小写
isupper(c);//大写
isalnum(c);//字母或数字s
isspace(c);//空格或\t,\r,\n
//为true时未必是1,但一定不为0
toupper(c);//转化为大写字母
tolower(c);//转化为小写字母