第一步:学习c++基本语法

问题解决:

1.cmark版本不匹配

起初:

然后我又下载了dev-c++

后面我发现CMark如上图也可以! 

2.clion无法输出结果

Clion无法输出时候,可以重新开创一个项目,复制过去就解决了!

第1讲:变量的定义与输入输出

  • 内容

3部分(头文件+命名空间+main()函数)、变量的定义、cin、cout,scanf、printf

  • 练习代码

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
    /* int a=1,b=4;
     cout<<a+b<<' '<< a*b <<endl;
     cout << "Hello, World!" << endl;*/
   /* int c=3,d=5;
    printf("c+d=%d\nc*d-%d\n",c+d,c*d);*/
/*   float f=1.1,h=3.4;
//    scanf("%f",&f);
//    scanf("%f",&h);
    printf("f+h=%.2f\n",f+h);
    printf("f*h=%.5f\n",f*h);
    浮点数%f
    */
/*int j=6+3*4/2-2;
cout<<j<<endl;
float k=j*10+5/2;//整数相除得整数
float h=j*10+5.0/2.0;
cout<<k<<' '<<h<< endl;
cout<< 5%3<< endl;//取余数
cout<< -5%3<< endl;*/
/*int x=6,y=7;
    y+=6;//+-*%/
    cout<<x++<<endl;//先引用再自加
    cout<<++x<<endl;//先自加再引用
    cout<<y<<endl;*/
cout<<'A'+2<<endl;
cout<<char('A'+2)<<endl;
cout<<' '+2<<endl;
int a=3;
printf("%d",a);
    return 0;

}
  • 习题练习

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
//求和
int a=12,b=27;
cout<<a+b<<endl;
//读取4个数字,计算(A*B-C*D)的值
//求差
int A=7,B=5,C=2,D=3;
    printf("%d",A*B-C*D);
}

第2讲:判断语句

  • 内容

if...else...的用法、><==、与(&&)或者(||)非(!=)

  • 练习代码

#include <iostream>
using namespace std;

int main() {
    //循环if,else
   int score;
    cin>>score;
    if(score>=60)
    {
        cout<<"pass"<<endl;
    } else{
        cout<<"no"<<endl;
        cout<<"fight!"<<endl;
    }

   //如果>=0输出x,否则-x
   int x;
   cin >>x;
   if(x>=0)
   {
       cout<<x<<endl;
   }else{
       cout<<(-x)<<endl;
   }
   //abc比较大小
  
   int a,b,c;
   cin>>a>>b>>c;
 if(a>=b&&b>=c){//前面不满足直接短路,不再执行并且(&&)或者(||)非!
     cout<<"a is the largest!"<<endl;
 }else{
     cout<<"a is not the largest!"<<endl;
 }
  • 习题练习

    #include <iostream>
    using namespace std;
    
    int main() {
     
       //abc比较大小
       int a,b,c;
       cin>>a>>b>>c;
      if (a>=b)
        {
            if (a>=c){
                cout<<"a is the largest!"<<endl;
            } else{
                cout<<"c is the largest!"<<endl;
            }
        }else{
            if (b>=c){
                cout<<"b is the largest!"<<endl;
            } else{
                cout<<"c is the largest!"<<endl;
            }
        }
     //判断是否是闰年
     int year;
     cin>> year;
        if (year%100==0&&year%400==0||year % 100 != 0&&year % 4 == 0){
            cout<<"yes"<<endl;
        } else {
                cout << "NO" << endl;
            }
        return 0;
    }
    

    第3讲:循环语句

  • 内容

while、do...while、for、break、continue

  • 练习代码

    #include <iostream>
    using namespace std;
    
    int main() {
        //while循环
        int i;
        cin>>i;
        while (i<=5){
            cout<<i<<endl;
            i++;
        }
       //求1-10所有立方和
      int a=1,sum=0;
        while (a<=10)
        {
            sum=sum+a*a*a;
            a++;
        }
        cout<<sum<<endl;
    //do...while循环:先执行后判断
    //计算1-10的和
    
    int b=0,s=0;
    
     //用do...while
      do{
        s+=b;
        b++;
    } while (b<=10);
        cout<<s<<endl;
    //用while
        while (b<=10){
            s+=b;
            b++;
        }
        cout<<s<<endl;*/
     //for(①开始执行;②条件;③表达式(每次都会执行)){}
       //利用for循环:输出1-10
       int s=0;
        for (int i = 0; i <=10; i++){
            s+=i;
        }
       cout<<s<<endl;
     //continue跳过单次,break整体退出
     int sum=0;
        for (int i = 0; i <= 3; i++) {
            if(i==2)continue;
          *//*  if (i==2)break;*//*
            sum+=i;
        }
        cout<<sum<<endl;
        return 0;
    }
    

    第4讲:数组

  • 内容

一维数组、二维数组的定义、初始化、调用、memset赋值,sizeof返回字节,memcpy复制

#include <iostream>
#include <cstring>
using namespace std;

int main() {
   //程序=逻辑+数据,数组是存储数据的强而有力的手段
 /*   int c[5]={0};
    for (int i = 0; i < 5; ) {
        cout<<c[i]<<endl;
        i++;
    }*/
/*int a[3]={1,5,3};
    for (int i = 0; i < 3; i++) {
        cout<<a[i]<<endl;
    }*/
   /* int b[]={1,4,5,7,9};//数组下标从0开始

    cout<<b[0]*2<<endl;*/
/*   //输入n个数,再逆序输出
    int n;
int a[100];
cin>>n;
    for (int i = 0; i <n ; i++)
        cin>>a[i];
    for (int i = n-1; i >=0; i--)
        cout<<a[i]<<' ';
        cout<<endl;*/
/*
 //二维数组定义与初始化
 int x[3]={0,1,2};
int y[3][4]={{1,3,4,5},
             {1,3,7,9},
             {1,2,3,4}};
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            cout<<y[i][j]<<' ';

        }
        cout<<endl;
    }*/
/*//赋值
int a[10],b[10];
    cout<<sizeof a<<endl;//数组中1个占4字节
    memset(a,-1,40);//byte为1,一般全部赋值为0/-1
    for(int i=0; i< 10;i++){
    cout<<a[i]<<' ';
}*/
//复制
/*int a[10],b[10];
//memcpy(目标,原,长度)
    memcpy(b,a,sizeof a);
    for(int i=0; i< 10;i++){
        cout<<a[i]<<' ';
    }
    cout<<endl;
    for(int i=0; i< 10;i++)
            cout<<b[i]<<' ';
    return 0;*/

}
  • 习题练习

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main() {
    //输入一个整数v,输出一个长度为10的数组,数组第一个元素为v,后续每个为上一个的2倍
    int a[10],v;
    cin>>v;
        for (int i = 0; i < 10; i++) {
            a[i]=v;
            cout<<a[i]<<endl;
            v*=2;
        }
        return 0;
    }
    

    第5讲:字符串

  •  内容

字符与整数、字符串的输入输出(fgets、getline)、3个重要的函数(长度strlen、比较大小strcmp、复制strcpy)

  •  练习代码

#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;

int main() {
/*//字符串是计算机与人类沟通的重要手段
//英文常用字符都对应一个-128-127的数字,两者可以相互转化
char c='a';
cout<<(int)c<<endl;
cout<<(char)97<<endl;
//输出128个符号
    for (int i = 0; i <128 ; i++) {
        cout<<(char)i<<endl;
    }
    //符号做差,字符可以参与整数运算
    printf("%d\n",'h'-'a');*/
/*//字符串就是字符数组+\0.所以字符数组要比字符串的长度多1!
 //输入
char a1[]={'c','+','+'};
char a2[]={'c','+','+','\0'};
char a3[]="c++";
    cout<<sizeof a1<<'\0'<<sizeof a2<<'\0'<<sizeof a3<<'\0'<<endl;
  //输出
    char a4[]={'A','B','C','\0'};
    cout<<a4<<endl;
    cout<<a4+1<<endl;
    cout<<a4+2<<endl;*/
/*char a5[100];
   scanf("%s",a5);
    cin>>a5;
    printf("%s\n",a5);
  cout<<a5<< endl;*/
   /* //读入一行到数组里面变量
    char b1[100];
        cin>>b1;
    cout<<b1<<endl;//遇见空格就停止
    fgets(b1,100,stdin);
    cout<<b1<<endl;
    //读入一行到字符串里面
    string b2;
    getline(cin,b2);
    cout<<b2<<endl;*/
/*char b2[100];
    scanf("%s",b2);
    puts(b2);
    printf("%s",b2);
    */
//3个重要的函数

/*char c[100];
 * //strlen求string的length
    scanf("%s",c);
    cout<<strlen(c)<<endl;*/
/*
 * //strcmp比较两个字符串的大小(字典比,例如10<2,第一位),<返回-1,==返回0,>返回1
 * char c1[100],c2[100];
    scanf("%s%s",c1,c2);
cout<<strcmp(c1,c2)<<endl;*/
   /* char c3[100];
    scanf("%s",c3);
    cout<<strcmp(c3,"abc")<<endl;*/
    //string copy,后给前
  /* char a4[100],a5[100];
   cin>>a4;
    strcpy(a5,a4);
    printf("%s",a5);*/
  
    return 0;
}
  • 习题练习

    #include <string.h>
    using namespace std;
    
    int main() {
    //遍历字符数组中的字符
    /*char s1[100];
        fgets(s1,100,stdin);
        for (int i = 0; i < strlen(s1); i++) {//每循环一次strlen都要执行一次
            cout<<s1[i]<<endl;
        }*/
    /*char s2[100];
    int s3;
        fgets(s2,100,stdin);
        s3=strlen(s2);//提前保存,提高效率
        for (int i = 0; i < s3; i++) {
            cout<<s2[i]<<endl;
        }*/
    
        return 0;
    }

     第6讲:函数

  • 内容

函数的定义、调用、参数传递(有/无返回值)、数组传递

  • 练习代码

    #include <iostream>
    #include <cstring>
    #include <string.h>
    using namespace std;
    /*//最简单的函数
    void output(){
        cout<<"yuzuru"<<endl;
    }
    int main() {
    //函数让代码变得更简洁
    output();
        return 0;
        */
    //函数求和
    /*int sum(int s){
        int sum=0;
        for (int i = 0; i <=s; i++) {
            sum+=i;
        }
        return sum;
    }
    int main() {
        int n;
        cin>>n;
        int s= sum(n);
     cout<<s<<endl;
        return 0;*/
    /*//当初始化一个非引用类型的变量时,初始值被拷贝给变量。
    // 此时,对变量的改动不会影响初始值。
    int f(int x){
        x=5;
    }
    int main() {
    int  x=10;
        f(x);
        cout<<x<<endl;
        return 0;*/
    /*int f(int &x){//加入引用&后,会改变外面的值,可以用于返回多个值
        x=5;
    }
    int main() {
        int  x=10;
        f(x);
        cout<<x<<endl;
        return 0;*/
    /*
     * 运用&,去交换2个值
     * void swap(int &a,int &b){
        int t=a;
        a=b;
        b=t;
    }
    int main(){
        int x,y;
        cin>>x>>y;
        cout<<x<<' '<<y<<' '<<endl;
        swap(x,y);
        printf("change after:\n");
        cout<<x<<' '<<y<<' '<<endl;
    return 0;
    }*/
    /*//输出2个数当中,较大的数值
    int max(int a,int b){
        if (a>=b){
            return a;
        } else{
            return b;
        }
    }
    int main() {
        int a,b;
        cin>>a>>b;
        cout<<max(a,b)<<endl;
        return 0;*/
    /*//函数输出一维数组
    int  output2(int n,int a[]){
        for (int i = 0; i <n ; i++) {
            cout<<a[i]<<' '<<endl;
        }
    }
    int main() {
    int b[]={1,2,3,4,5};
        output2(5,b);
        return 0;
    }*/
    //函数输出二维数组
    /*int output3(int k,int h,int c[][3]){//第一个可以省略,第二个不可以省略
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < h; j++) {
                cout<<c[i][j]<<' ';
            }
    cout<<endl;
        }
    }
    int  main(){
        int d[4][3]={
                {1,2,3},
                {4,5,6},
                {7,8,9},
                {1,5,7},
        };
        output3(4,3,d);
        return 0;
    }*/
    void l(int a,int b=7,int c=3){//默认值必须在后面
        cout<<a<<' '<<b<<' '<<c<<endl;
    }
    int main(){
        l(5);//b不传值就不变!
        l(5,9);//b传值就改变
        return 0;
    }
    

     第7讲:类、结构体、指针与引用

  • 内容

类的定义与调用、指针的读取,修改,引用,链表的遍历,增删改;

  • 类和结构体的练习代码

#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;
//类可以将变量、数组和函数完美打包一起
class person{//结构体struct默认共有public-数据和函数较少,class默认private-复杂的打包
private:
    int age,height;//私有只能内部使用
    double money=0;
    string book[100];

public:
    string name;
    void say(){
        cout<<"I'm"<<name<<endl;
    }
    int  get_age(){
        return age;
    }
    void add_money(double x){
        money+=x;
    }
};
int main(){
person c;
c.name="yuzuru";
c.add_money(1000);
    return 0;
}
//构造函数
struct person{
    int age,height;
    double money;
    person(){}
    person(int _age):age(_age){}//更快速的赋值方式
    person(int _age,int _height){
        age=_age;
        height=_height;
    }
    person(int _age,int _height,double _money){
        age=_age;
        height=_height;
        money=_money;
    }
};
int main(){
    person p1(18,175,150.00);
    person p2={17,180,200.000};
    person p3(22,155);

    return 0;
}
  • 指针的练习代码

#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;
//char a,b;//堆空间
int main(){
//指针指向存放变量的值的地址。因此我们可以通过指针来修改变量的值。
//查看地址
/*char c='a';//栈空间地址
cout<<(void*)&c<<endl;
char d;
    cout<<(void*)&d<<endl;
    cout<<(void*)&a<<endl;
    cout<<(void*)&b<<endl;
//地址存放变量的下标*/
//读取指针的值
/*int a=10;
int* p=&a;//int*:int类型的指针,p是变量(p是a的地址)
int** q=&p;//p也是一个变量,也有存它的地址
cout<<q<<endl;//q是指针的指针,q为存放指针p的地址
printf("指针输出:");
cout<<*p<< endl;//*p用地址取值
printf("变量输出:");
cout<<a<< endl;
//修改
*p=7;//运用地址修改变量的值,类似通过数组下标修改数组的值
    printf("修改后,指针输出:");
    cout<<*p<< endl;
    printf("修改后,变量输出:");
    cout<<a<< endl;*/
//数组也是指针,存放的数组的开始地址
/*int c;
int  d[]={1,2,3,4};
    cout<<(void*)&c<< endl;
    cout<<(void*)d<< endl;//存放首地址
    cout<<(void*)&d[0]<<endl;//int包含4个字节
    cout<<(void*)&d[1]<<endl;
    cout<<(void*)&d[2]<<endl;*/
   /* int j1;
    int  j2[]={1,2,3,4};
    int  *p1=j2;
    cout<<(void*)j2<< endl;
    cout<<p1+1<< endl;//不是1变2,是加变量长度,int需要+4
    double k1;
    double k2[]={1,2,3,4};
    double  *p2=k2;
    cout<<(void*)k2<< endl;
    cout<<p2+1<< endl;
    long long h1;
    long long h2[]={1,2,3,4};
    long long *p3=h2;
    cout<<(void*)h2<< endl;
    cout<<p3+1<< endl;*/
/*   //取值可以用指针,也可以用数组
    int  l[]={1,3,7,4};
    int *o=l;
    cout<<o<<endl;
    cout<<*(o)<<endl;
    cout<<o+2<<endl;
    cout<<*(o+2)<<endl;
    cout<<l<<endl;
    cout<<*(l)<<endl;
    cout<<l+2<<endl;
    cout<<*(l+2)<<endl;*/
//引用
int m=7;
int &n=m;//n为m的别名
cout<<m<<endl;
cout<<n<<endl;
m=9;
    cout<<m<<endl;
    cout<<n<<endl;
    return 0;
}
  • 链表的练习代码

    #include <iostream>
    #include <cstring>
    #include <string.h>
    using namespace std;
    //定义一个结构体
    struct Node{
        int val;//值
        Node* next;//指针
        Node(int _val):val(_val),next(NULL){//构造函数
    
        }
    };
    
    int main(){
    Node p1=Node(1);//返回一个变量
        p1.val;//变量调用
        Node* p2=&p1;
        //合成一步
        Node* p= new Node(2);//new 返回地址,new动态开辟一个结构体
        p->next=p2;//->指针调用,不是指针就用xx .xx进行调用,指向自己
       Node* q= new Node(3);//
       Node* o=new Node(7);
       p->next=q;//p2指向q的地址
        q->next=o;//链表:p->q->0->null;头结点p,一般存放地址到head中
       //如何遍历链表?
       Node* head=p;
        for (Node* i=head; i ; i=i->next) {//起为head,终止为0,每次指向下一个结点
            cout<<i->val<<endl;
        }
        cout<<endl;
        //如何在链表前面再添加一个节点?
        Node* a=new Node(1);
        a->next=head;//把a添加到头结点前面
        head=a;//在把头结点的地址移动到a的地址
        for (Node* i=head; i ; i=i->next) {//起为head,终止为0,每次指向下一个结点
            cout<<i->val<<endl;
        }
        cout<<endl;
        //如何删除一个节点?
        //链表的删除并不是删除该节点,而是把这个节点跳过,把前面的连接到后面(遍历不到)
        //所以,必须知道该节点的前后节点
       // a->next=q;
       head->next=head->next->next;//头部连接到头部的下下个
        for (Node* i=head; i ; i=i->next) {//起为head,终止为0,每次指向下一个结点
            cout<<i->val<<endl;
        }
        return 0;
    }
    

     第8讲:STL、位运算、常用库函数

  • https://zhuanlan.zhihu.com/p/344558356(学习素材链接)
  • 内容

STL 是“Standard Template Library”的缩写,中文译为“标准模板库”。

组件

描述
容器(Containers)

容器是用来管理某一类对象的集合。

C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。

算法(Algorithms)算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。
迭代器(Iterators)
适配器(Adapters)
仿函数(Functors)

1.vector(矢量)

vecctor是一种「变长数组」,即“自动改变数组长度的数组”。

#include <vector>//要使用vector,需要添加头文件:
  • vector的定义

#include <iostream>
#include <cstring>
#include <vector>//要使用vector,需要添加头文件:
using namespace std;

int main(){
//STL提高C++编写效率的一个利器
//vector(矢量),是一种「变长数组」,即“自动改变数组长度的数组”。
//vector的定义:vector<类型名>变量名;
//类型名可以是int、double、char、struct
// 也可以是STL容器:vector、set、queue。
    vector<int> a;
    vector<double> b;
    vector<char> c;
    vector<struct node> node();
    vector<vector<int> >e;
    //注意:vector<vector<int> > name; >>之间要加空格。
    //vector数组就是一个一维数组
    // 如果定义成vector数组的数组,那就是二维数组。
    //vector<int> array[SZIE]; //二维变长数组
    //低维是高维的地址。比如二维数组中,它的一维形式就是地址。
    int arr[3][2];//定义一个3行2列的地址
    cout<<arr[0]<<endl; //输出arr第1行的地址
    cout<<arr[1]<<endl; //输出arr第2行的地址
    cout<<arr[2]<<endl; //输出arr第3行的地址
    return 0;
}
  • vector容器内元素的访问

2种方式:

(1)通过下标访问

#include <iostream>
#include <cstring>
#include <vector>//要使用vector,需要添加头文件:
using namespace std;

int main(){
    vector<int> vi={1,3,4};
    vi.push_back(7);//push_back()函数:将一个新的元素加到vector的最后面,
    cout<<vi[3]<<endl;// 位置为当前最后一个元素的下一个元素
    cout<<vi[2]<<endl;
    cout<<vi[1]<<endl;
    cout<<vi[0]<<endl;
    return 0;
}

 (2)通过迭代器访问

迭代器(iterator)可以理解为指针:

vector<类型名>::iterator 变量名;

例如:

vector<int>::iterator it;
vector<double>::iterator it;

 比如:

#include <iostream>
#include <cstring>
#include <vector>//要使用vector,需要添加头文件:
using namespace std;

int main(){
    vector<int> a;
    for (int i = 0; i < 5; i++) {
        a.push_back(i+2);//每次添加2,依次添加vector的后面
        cout<<a[i]<<" ";
    }
    cout<<endl;
    vector<int>::iterator it=a.begin();//a.begin()返回a的首元素地址
    for (int i = 0; i < a.size();i++){
        cout<<it[i]<<" ";//it[i] = *(it+i) //这两个写法等价
    }
    return 0;
}

 例外遍历的简单写法:

include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    //vector的迭代器不支持it<v.end()的写法,因此循环条件只能it!=v.end()
    for (vector<int>::iterator it=v.begin(); it!=v.end();it++)
    {
        cout<<*it<<" ";
    }
    return 0;
}

  • vector常用函数实例解析

后面添加一个push_back(),指定添加insert(),

后面删除一个pop_back(),全部删除clear(),指定删除erase()

长度size()

(1)push_back()

void std::vector<int>::push_back(const int &__x)

push_back(item)就是在vector后面添加一个元素item。

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);//依次存入
    }
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    return 0;
}

 (2)pop_back()

pop_back()一次删除一个

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    cout<<"pop_back,before:"<<endl;
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    v.pop_back();
    cout<<"pop_back,after:"<<endl;

    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    return 0;
}

 (3)size()

size()返回vector中所含元素的

(4)clear()个数

clear()用于一键清空vector中的所有元素时间复杂度为O(N),其中N为vector中原属和元素的个数。

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    cout<<"pop_back,before:"<<endl;
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    v.pop_back();
    cout<<"pop_back,after:"<<endl;

    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    v.clear();
    cout<<"clear,after:"<<endl;
cout<<endl;
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<v.size()<<endl;
    return 0;
}

(5)insert()

与push_back()在尾部添加元素不同的是,insert()是根据指定位置在vector中插入元素。

insert(__position,__x);
insert(要插入的地址,要插入的元素);

参数:
__position:– A const_iterator into the %vector.
__x:– Data to be inserted.

练习:

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    cout<<"pop_back,before:"<<endl;
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    //原来输出为0,1,2,3,4
    //在2,3之间添加-1
    v.insert(v.begin()+3,-1);
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    return 0;
}

 (6)erase()

与clear()简单清空vector不同的是erase(),删除指定位置的元素。

#include <iostream>
#include <vector>
using namespace std;

int main(){
    vector<int> v;
    for (int i = 0; i < 7; i++)
    {
        v.push_back(i);
    }
    cout<<"pop_back,before:"<<endl;
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    //原来输出为0,1,2,3,4
    //删除1和区间3,4,5
    v.erase(v.begin()+1);
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    cout<<endl;
    v.erase(v.begin()+2,v.begin()+5);
    for (int i = 0; i < v.size(); i++)
    {
        cout<<v[i]<<" ";
    }
    return 0;
}
  • vector常见用途

(1)储存数据

vector本身可以作为数组使用,而且在一些元素个数不确定的场合可以很好地节省空间。

(2)用邻接表存储图

使用vector实现邻接表,更为简单。

2.set(集合)

set(集合),是一个内部自动有序不含重复元素的容器。

被插入set集合后,set内部的元素自动递增排序,并且自动去除了重复元素

set可以去重。

要使用set,需要添加头文件:

#include <set>
using namespace std;
  • set的定义

像定义变量一样定义set变量:

set<类型名> 变量名;

类型名可以是int、double、char、struct,也可以是STL容器:vector、set、queue。

用例:

set<int> name;
set<double> name;
set<char> name;
set<struct node> name;
set<set<int> > name;//注意:> >之间要加空格

set数组的定义和vector相同:

set<类型名> array[SIZE];

例如:

set<int> arr[10];
  • set容器内元素的访问

set只能通过迭代器(iterator)访问

set<int>::iterator it;
set<char>::iterator it;

这样,就得到了迭代器it,并且可以通过*it来访问set里的元素。

#include <iostream>
#include <vector>
#include <set>
using namespace std;

int main(){
set<int> a;
    a.insert(7);
    a.insert(5);
    a.insert(9);
    a.insert(5);
    a.insert(5);
    a.insert(5);
    a.insert(5);
    for (set<int>::iterator it = a.begin(); it != a.end(); it++)
    {
        cout << *it << endl;
    }
    return 0;
}
  • set常用函数实例解析

(1)insert()

#include <iostream>
#include <set>
using namespace std;

int main()
{
    set<char> st;
    st.insert('C');
    st.insert('B');
    st.insert('A');
    for (set<char>::iterator it = st.begin(); it != st.end(); it++)
    {
        cout << *it << endl;
    }
    return 0;
}

(2)find()

find(value)返回的是set中value所对应的迭代器,也就是value的指针(地址)

#include <iostream>
#include <set>
using namespace std;
int main()
{
    set<int> st;
    for (int i = 1; i <= 3; i++)
    {
        st.insert(i);
    }

    set<int>::iterator it = st.find(2); //在set中查找2,返回其迭代器
    cout << *it << endl;

    // 以上可以直接x携程
    cout << *(st.find(2)) << endl;
    return 0;
}

(3)erase()

erase()有两种用法:删除单个元素、删除一个区间内的所有元素。

1.删除单个元素

删除单个元素有两种方法:

  • st.erase(it),其中it为所需要删除元素的迭代器。时间复杂度为O(1)。可以结合find()函数来使用。
#include <iostream>
#include <set>
using namespace std;

int main()
{
    set<int> st;
    st.insert(100);
    st.insert(200);
    st.insert(200);
    st.insert(200);
    st.insert(100);
    st.insert(300);
    // 删除单个元素
    st.erase(200);
    st.erase(st.find(100)); //利用find()函数找到100,然后用erase删除它
    for (set<int>::iterator it = st.begin(); it != st.end(); it++)
    {
        cout << *it << endl;
    }
    return 0;
}

2.删除一个区间内的所有元素

st.erase(iteratorBegin , iteratorEnd)可以删除一个区间内的所有元素。

其中iteratorBegin为所需要删除区间的起始迭代器

iteratorEnd为所需要删除区间的结束迭代器的下一个地址

也即是[iteratorBegin,iteratorEnd)

#include <iostream>
#include <set>
using namespace std;

//2.删除一个区间内的所有元素

int main()
{
    set<int> st;
    st.insert(100);
    st.insert(200);
    st.insert(600);
    st.insert(300);
    st.insert(400);
    st.insert(500);
    st.insert(700);
    st.insert(800);
    st.insert(900);
    set<int>::iterator it;
    for (it = st.begin(); it != st.end(); it++)
    {
        cout << *it<<" ";
    }
    cout<<endl;
    //删除800及之后的(包括800)
    set<int>::iterator it1 = st.find(800);
    st.erase(it1, st.end());
    for (it1 = st.begin(); it1 != st.end(); it1++)
    {
        cout << *it1<<" ";
    }
    cout<<endl;
    //删除200及前的(不包括200)
    set<int>::iterator it2 = st.find(200);
    st.erase(st.begin(), it2);
    for (it2 = st.begin(); it2 != st.end(); it2++)
    {
        cout << *it2 <<" ";
    }
    cout<<endl;
    //删除300,400,500
    set<int>::iterator it3 = st.find(300);
    set<int>::iterator it4 = st.find(600);
    set<int>::iterator it5=st.erase(it3, it4);
    for (it5 = st.begin(); it5 != st.end(); it5++)
    {
        cout << *it5 <<" ";
    }
    cout<<endl;
    return 0;
}

学习-《从放弃C语⾔到使⽤C++刷算法的简明教程》by 柳婼-笔记

对照该学习材料对上述进行查漏补缺! (《从C语言转C++简明教程 v5.0+》 – 柳婼 の blog

1.string:输入、拼接

#include <iostream>
#include <set>
using namespace std;


int main(){
    string s1="hello  ";
    string s2="yuzuru";
    string s3=s1+","+s2+"!";//字符串的拼接,用+
    cout<<s3<<endl;
    cout<<s1.length()<<endl;
    cout<<s3.length()<<endl;
    string s4;
   cin>>s4;//以空格为分割线
    cout<<s4<<endl;
    cout<<s4.length()<<endl;
    string s5;
    getline(cin,s5);//包含空格
    cout<<s5<<endl;
    cout<<s5.length()<<endl;
    return 0;
}

 2.C++ STL之动态数组vector(⽮量)的使⽤

vector 可以⼀开始不定义⼤⼩,之后⽤ resize ⽅法分配⼤⼩,也可以⼀开始就定义⼤⼩,之后还可以对它插⼊删除动态改变它的⼤⼩.

#include <iostream>
#include <set>
#include <vector>
using namespace std;


int main(){
    vector<int> v(10); // 直接定义⻓度为10的int数组
    vector<int> v1;//先定义⼀个vector变量v1
    v1.resize(8); //然后将⻓度resize为8,默认这8个元素都是0
    vector<int> v3(100, 9);// 把100⻓度的数组中所有的值都初始化为9
    cout << v[0];
    return 0;
}

3.C++ STL之集合set的使⽤ 

.begin()、end()、insert()、find()、erase()

#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main(){
set<int> s;//定义空集合s
s.insert(1);//insert()插入1
cout<< *(s.begin())<< endl;//.begin() 是⼀个指针,指向容器的第⼀个元素
    //*表示对指针取值
    for (int i = 0; i <=7; i++) {//生成1,2,3,4,5,6,7
        s.insert(i);
    }
    for (auto it = s.begin(); it!=s.end(); it++) {
        cout << *it << " ";// ⽤迭代器遍历集合s⾥⾯的每⼀元素
    }
    cout << endl << (s.find(2) != s.end()) << endl; // 查找集合s中的值,如果结果等于s.end()表示未找到
    s.end();//表示未找到 (因为s.end()表示s的最后⼀个元素的下⼀个元素所在的位置)
    cout << (s.find(10) != s.end()) << endl; // s.find(10) != s.end()表示能找到10,
    s.erase(1); // 删除集合s中的1这个元素
    cout << (s.find(1) != s.end()) << endl; // 这时候元素1就应该找不到啦~返回0.
    return 0;
}

4.C++ STL之映射map的使⽤

map 是键值对,⽐如⼀个⼈名对应⼀个学号,就可以定义⼀个字符串 string 类型的⼈名为 ,学
int 类型为 ,如 map<string, int> m; 当然键、值也可以是其它变量类型~ map 会⾃动将所有的
键值对按照键从⼩到⼤排序, map 使⽤时的头⽂件 #include <map> 以下是 map 中常⽤的⽅法:

 .begin()、end()、rbegin()、size()

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(){
map<string,int>m;
m["AA"]=01;//AA-01
m["BBBB"]=07;//BBBB-07
m["CC"]=05;//CC-05
m["dddd"]=03;//dddd-03
m["ee"]=02;//ee-02
cout<<m["BBBB"]<<endl;//返回键值
cout<<m["BB"]<<endl;//如果不存在,就返回0
    for (auto it = m.begin(); it != m.end(); it++) {
        cout << it->first << "-" << it->second << endl;
    }
    // 访问map的第⼀个元素,输出它的键和值
    cout << m.begin()->first << " " << m.begin()->second << endl;
    // 访问map的最后⼀个元素,输出它的键和值
    cout << m.rbegin()->first << " " << m.rbegin()->second << endl;
    // 输出map的元素个数
    cout << m.size() << endl;
    m["ee"]=03;//把ee-02修改为ee-03
    for (auto it = m.begin(); it != m.end(); it++) {
        cout << it->first << "--" << it->second << endl;
    }
    return 0;
}

5.C++ STL之栈stack的使⽤

stack 在头⽂件 #include <stack> 中,是数据结构⾥⾯的栈~

push()、top()、size()、pop()

#include <iostream>
#include <stack>
using namespace std;
int main() {
    stack<int> s; // 定义⼀个空栈s
    for (int i = 0; i < 1; i++) {
        s.push(i+2); // 将元素i压⼊栈s中
    }
    cout << s.top() << endl; // 访问s的栈顶元素
    cout << s.size() << endl; // 输出s的元素个数
    s.pop(); // 移除栈顶元素
    return 0; }

6.C++ STL之队列queue的使⽤

队列 queue 在头⽂件 #include <queue> 中,是数据结构⾥⾯的队列~
访问队列的队⾸元素 front ()、 访问队列的队尾元素 back () 输出队列的元素个数 size ()、 移除队列的队⾸元素 pop ()
#include <iostream>
#include <queue>
using namespace std;
int main() {
    queue<int> q; // 定义⼀个空队列q
    for (int i = 0; i < 6; i++) {
        q.push(i); // 将i的值依次压⼊队列q中
    }
    cout << q.front() << " " << q.back() << endl; // 访问队列的队⾸元素和队尾元素
    cout << q.size() << endl; // 输出队列的元素个数
    q.pop(); // 移除队列的队⾸元素
    cout << q.front() << " ";
    return 0;
}

7.C++ STLunordered_mapunordered_set的使⽤ 

unordered_map 在头⽂件 #include <unordered_map> 中,
unordered_set 在头⽂件 #include <unordered_set> 中~
unordered_map map (或者 unordered_set set )的区别是, map 会按照键值对的键 key 进⾏ 排序( set ⾥⾯会按照集合中的元素⼤⼩进⾏排序,从⼩到⼤顺序)
unordered_map (或 者 unordered_set )省去了这个排序的过程,如果偶尔刷题时候⽤ map 或者 set 超时了,可以考虑 ⽤ unordered_map (或者 unordered_set )缩短代码运⾏时间、提⾼代码效率~⾄于⽤法和
map set 是⼀样的~

8. C++的位运算bitset

bitset ⽤来处理⼆进制位⾮常⽅便。头⽂件是 #include <bitset> bitset 可能在 PAT 、蓝桥 OJ 中不常⽤,但是在LeetCode OJ 中经常⽤到~⽽且知道 bitset 能够简化⼀些操作,可能⼀些复杂的问题能够直接⽤ bitset 就很轻易地解决~
#include <iostream>
#include <bitset>
using namespace std;
int main() {
    // 初始化⽅式:
    // bitset<5> b; 都为0
    // bitset<5> b(u); u为unsigned int,如果u = 1,则被初始化为10000
    // bitset<5> b(s); s为字符串,如"1101" -> "10110"
    // bitset<5> b(s, pos, n); 从字符串的s[pos]开始,n位⻓度
    bitset<5>a("1001");//5表示5个⼆进位
    bitset<7>b("00101");//""里面只能是0/1
    for(int i = 0; i < 5; i++)
        cout << a[i];
    cout<<endl;
    for(int i = 0; i < 7; i++)
        cout << b[i];
    cout << endl << b.any(); //b中是否存在1的⼆进制位
    cout << endl << b.none(); //b中不存在1吗?
    cout << endl << b.count(); //b中1的⼆进制位的个数
    cout << endl << b.size(); //b中⼆进制位的个数
    cout << endl << b.test(2); //测试下标为2处是否⼆进制位为1
    cout<<endl;
    for(int i = 0; i < 7; i++)
        cout << b[i];
        cout<<endl;
    b.set(4); //把b的下标为4处置1
    for(int i = 0; i < 7; i++)
        cout << b[i];
        cout<<endl;

    b.reset(2); //b的下标3处归零
    for(int i = 0; i < 7; i++)
        cout << b[i];
    cout<<endl;
    b.reset(); //所有位归零
    for(int i = 0; i < 7; i++)
        cout << b[i];
    cout<<endl;
    b.flip(); //b的所有⼆进制位逐位取反
    for(int i = 0; i < 7; i++)
        cout << b[i];
    cout<<endl;
    unsigned long c = b.to_ulong(); //b转换为unsigned long类型

    return 0;
}

9.C++中的sort函数

sort 函数在头⽂件 #include <algorithm> ⾥⾯,主要是对⼀个数组进⾏排序( int arr[] 数组或
vector 数组都⾏)
vector 是容器,要⽤ v.begin() v.end() 表示头尾;
int arr[] arr 表示数组的⾸地址, arr+n 表示尾部~
注意 sort 函数的 cmp 必须按照规定来写,即必须只是 > 或者 < ,⽐如: return a > b;
return a < b; ⽽不能是 <= 或者 >= ,(实际上等于号加了也是毫⽆意义, sort 是不稳定的排
序),否则可能会出现段错误~
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool cmp(int a, int b) { // cmp函数返回的值是bool类型
    return a > b; // 从⼤到⼩排列
}
int main() {
    vector<int> v(10);
    for (int i = 0; i < 10; i++) {
        cin >> v[i];
    }
    sort(v.begin(), v.end());// 因为这⾥没有传⼊参数cmp,所以按照默认,v从⼩到⼤排列
    int arr[10];
    for (int i = 0; i < 10; i++) {
        cin >> arr[i];
    }
    sort(arr, arr + 10, cmp); // arr从⼤到⼩排列,因为cmp函数排序规则设置了从⼤到⼩
    return 0;
}

10.C++中使⽤sort⾃定义cmp函数

sort 默认是从⼩到⼤排列的,也可以指定第三个参数 cmp 函数,然后⾃⼰定义⼀个 cmp 函数指定
排序规则~ cmp 最好⽤的还是在结构体中,尤其是很多排序的题⽬~⽐如⼀个学⽣结构体 stu 有学 号和成绩两个变量,要求如果成绩不同就按照成绩从⼤到⼩排列,如果成绩相同就按照学号从⼩到⼤ 排列,那么就可以写⼀个 cmp 数组实现这个看上去有点复杂的排序过程:
#include <iostream>
using namespace std;
struct stu { // 定义⼀个结构体stu,number表示学号,score表示分数
 int number;
 int score; }
bool cmp(stu a, stu b) { // cmp函数,返回值是bool,传⼊的参数类型应该是结构体stu类型
 if (a.score != b.score) // 如果学⽣分数不同,就按照分数从⼤到⼩排列
 return a.score > b.score;
 else // 如果学⽣分数相同,就按照学号从⼩到⼤排列
 return a.number < b.number; }
// 有时候这种简单的if-else语句,可以直接⽤⼀个C语⾔⾥⾯的三⽬运算符表示~
bool cmp(stu a, stu b) {
 return a.score != b.score ? a.score > b.score : a.number < b.number; }

11.关于cctype头⽂件⾥的⼀些函数

刚刚在头⽂件那⼀段中也提到, #include <cctype> 本质上来源于 C 语⾔标准函数库中的头⽂件 #include <ctype.h> ,其实并不属于 C++ 新特性的范畴,在刷 PAT ⼀些字符串逻辑题的时候也经常⽤到,但是很多⼈似乎不了解这个头⽂件中的函数,所以在这⾥单独提⼀下~
#include <iostream>
#include <cctype>
using namespace std;
int main() {
    char c='2';
    if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
        cout <<c<< " is alpha"; }
    else{
        cout << c<<" is not alpha";
    }
    cout<<endl;
    //用isalpha
    if (isalpha(c)) {
        cout << c<<" is alpha";
    }else{
        cout << c<<" is not alpha";
    }
    return 0;
}
isalpha 字⺟(包括⼤写、⼩写)
islower (⼩写字⺟)
isupper (⼤写字⺟)
isalnum (字⺟⼤写⼩写 + 数字)
isblank space \t
isspace space \t \r \n
cctype 中除了上⾯所说的⽤来判断某个字符是否是某种类型,还有两个经常⽤到的函数: tolower
toupper ,作⽤是将某个字符转为⼩写或者⼤写,这样就不⽤像原来那样⼿动判断字符 c 是否是⼤写,如果是⼤写字符就 c = c + 32; 的⽅法将 char c 转为⼩写字符啦~
#include <iostream>
#include <cctype>
using namespace std;
int main() {
    char c = 'A';
    char b='a';
    char t1 = tolower(c); // 将c字符转化为⼩写字符赋值给t
    char t2 = tolower(b);//如果c本身就是⼩写字符也没有关系~
    cout << t1<<endl; // 此处t为'a'
    cout << t2<<endl;
    return 0;
}

12.C++11⾥⾯很好⽤的auto声明

auto C++11⾥⾯的新特性,可以让编译器根据初始值类型直接推断变量的类型。⽐如这样:

auto x = 100; // x是int变量
auto y = 1.5; // y是double变量
当然这个在算法⾥⾯最主要的⽤处不是这个,⽽是在 STL 中使⽤迭代器的时候, auto 可以代替⼀⼤⻓串的迭代器类型声明:
// 本来set的迭代器遍历要这样写:
for(set<int>::iterator it = s.begin(); it != s.end(); it++) {
 cout << *it << " "; }
// 现在可以直接替换成这样的写法:
for(auto it = s.begin(); it != s.end(); it++) {
 cout << *it << " "; }

13.C++11特性中基于范围的for循环

#include <iostream>
#include <cctype>
using namespace std;
int main() {
    int arr[4] = {0, 1, 2, 3};
    for (int i : arr)
        cout << i << " ";// 输出数组中的每⼀个元素的值,每个元素占据⼀⾏
    cout<<endl;
        for (int &i : arr) // i为引⽤变量
        i = i * 2; // 将数组中的每⼀个元素都乘以2,arr[4]的内容变为了{0, 2, 4, 6}
    for (int i : arr)
        cout << i <<" ";
    return 0;
}
这种基于范围的 for 循环适⽤于各种类型的数组,将上述两段代码中的 int 改成其他变量类型如
double char 都是可以的~另外,这种 for 循环⽅式不仅可以适⽤于数组,还适⽤于各种 STL
器,⽐如 vector set 等~加上上⾯⼀节所讲的 C++11 ⾥⾯很好⽤的 auto 声明,将 int double 等变量类型替换成 auto ,⽤起来就更⽅便啦~
// v是⼀个int类型的vector容器
for (auto i : v)
 cout << i << " ";
// 上⾯的写法等价于
for (int i = 0; i < v.size(); i++)
 cout << v[i] << " ";

14.C++11特性中的to_string

to_string 的头⽂件是 #include <string> to_string 最常⽤的就是把⼀个 int 型变量或者⼀个数字转化为 string 类型的变量,当然也可以转 double float 等类型的变量。
#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1 = to_string(123); // 将123这个数字转成字符串
    cout << s1 << endl;
    string s2 = to_string(4.5); // 将4.5这个数字转成字符串
    cout << s2 << endl;
    cout << s2 + s1 << endl; // 将s1和s2两个字符串拼接起来并输出
    printf("%s\n", (s2 + s1).c_str()); // 如果想⽤printf输出string,得加⼀
    //个.c_str()
    return 0;
}

15.C++11特性中的stoistod

使⽤ stoi stod 可以将字符串 string 转化为对应的 int 型、 double 型变量,这在字符串处理的很
多问题中很有帮助~
不仅有 stoi stod 两种,相应的还有:
stof (string to float)
stold (string to long double)
stol (string to long)
stoll (string to long long)
stoul (string to unsigned long)
stoull (string to unsigned long long)
#include <iostream>
#include <string>
using namespace std;
int main() {
    string str = "123";
    int a = stoi(str);
    cout << a+11<<endl;
    str = "123.44";
    double b = stod(str);
    cout << b;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值