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函数:
第一种:在头文件中,是iostream类的成员函数。
第二种:在头文件中,是普通函数。

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);//转化为小写字母
posted @ 2023-02-25 14:33  Gearlesskai  阅读(66)  评论(0编辑  收藏  举报