c/c++

c++基础语法

2018-07-27  本文已影响0人  曾大稳丶

c和c++联系

  1. c++代码可以混编c代码,既可以写c也可以调用c
  2. c++面向对象,c面向过程
  3. 开源框架大部分都是基于c++写的

打印

#include "stdio.h"
#include <iostream>

using namespace std;

void main() {
    //打印
    //cout << "hello world " << endl;//换行
    cout << "hello world " ;//不换行
}

常量

void main() {
    //常量
    const int number = 0;
    //在c文件,这里可以通过指针修改值,但是在c++中不能通过地址修改值,一般编译器编译不能通过,但是某一些编译器可以,但是也不能修改值
    //int *number_p = &number;
    //*number_p = 20;

    getchar();
 }

引用

#include "stdio.h"
#include <iostream>

using namespace std;

//通过指针来变换
void swap(int *num1,int* num2) {
    int temp = 0;
    temp = *num1;
    *num1 = *num2;
    *num2 = temp;
}

//通过引用来变换
void swap(int &num1, int& num2) {
    cout << "number1p = " << &num1 << "  number2p = " << &num2 << endl;//number1p = 00BBFA08  number2p = 00BBF9FC
    int temp = 0;
    temp = num1;
    num1 =num2;
    num2 = temp;
}

void main() {
    //引用:四驱模型值的拷贝,引用其实是地址赋值,可以看成同一块内存的另外一个变量
    
    //交换值
    int number1 = 10;
    int number2 = 20;
    //通过指针
    //swap(&number1,&number2);
    //通过引用
    cout << " number1p = " << &number1 << "  number2p = " << &number2 <<endl; // number1p = 00BBFA08  number2p = 00BBF9FC
    swap(number1,number2);

    cout << "number1 = " << number1 << "  number2 = " << number2 << endl;// number1 = 20  number2 = 10


    //加深理解
    int a = 10;
    int b = a; //赋值  b 和 a分别指向不同的内存
    cout << "ap = " << &a << "  bp = " << &b << endl;// ap = 010FF730  bp = 010FF724

    int& c = a;//引用  a和c都指向一块地址
    cout << "ap = " << &a << "  cp = " << &c << endl;// ap = 010FF730  cp = 010FF730
    c = 20;
    cout << "a = " << a << "  c = " << c << endl;//a = 20  c = 20

    getchar();
 }

常量引用

#include "stdio.h"
#include <iostream>
#include <string.h>

using namespace std;

typedef struct 
{
    char  name[20];
    int age;
} Student;

//常量引用 const Student & stu只能读,不能修改
void insertStudent(/* const */ Student & stu) {
    //stu.name = "李四";  //不能修改
    strcpy_s(stu.name, "李四");  //这样的话就修改了值,如果不想修改stu,就在参数加上const 变为只读
}

void main() {
    Student stu = {"张三" ,45};
    insertStudent(stu);
    cout << "stu.name = " << stu.name << " stu.age = " << stu.age << endl;
    getchar();
 } 

重载 :c不支持重载 ,c++支持

#include "stdio.h"
#include <iostream>
#include <string.h>

using namespace std;

//重载
//int add(int number1, int number2) {
//
//  return number1 + number2;
//}

int add(int number1, int number2,bool cache = false) {

    cout << cache << endl;

    return number1 + number2;
}
int add(int number1, int number2,int number3) {

    return number1 + number2 + number3;
}


void main() {
    int number1 = 10;
    int number2 = 20;
    int number3 = 30;
    int sum1 = add(number1, number2);
    int sum2 = add(number1, number2 , number3);

    printf("%d , %d", sum1, sum2);

    getchar();
 } 

JAVA里的Class

#include "stdio.h"
#include <iostream>
#include <string.h>

using namespace std;

class Student{
private: // 私有 包装,影响下面所有的属性或者方法
    char * name;
    int age;

public://影响下面所有的方法或者属性
    
    void setAge(int age){
        this->age = age;
    }
    void setName(char*name) {
        this->name = name;
    }

    int getAge() {
        return this->age;
    }

    char * getName() {
        return this->name;
    }
};


void main() {
    Student stu;
    stu.setAge(25);
    cout << stu.getAge() << endl;

    Student *student = new Student();

    student->setAge(24);
    
    cout << student->getAge() << endl;

    getchar();
 } 

注意:在开发过程中,cpp或者c会被编译为dll或者so供其调用者使用,一般把public的函数定义到h文件,不然调用者都不知道有哪些函数。

构造函数

class Student{

public:
    //1.
    Student() {};

    //2. 
    Student(char * name):age(0) { // 相当于thix->age = 0
        this->name = name;
    };

    //3.
    //构造函数相互调用 先调用两个参数的,在调用一个参数的
    Student(char*name) :Student(name,0) { // 相当于thix->age = 0
    };

    //4.
    Student(char*name,int age) {
        this->name = name;
        this->age = age;
    };

private:
    char * name;
    int age;

public:
    
    void setAge(int age){
        this->age = age;
    }
    void setName(char*name) {
        this->name = name;
    }

    int getAge() {
        return this->age;
    }

    char * getName() {
        return this->name;
    }
};

析构函数


class Student{

public:
    Student() {};

    Student(char*name,int age) {
        this->name = (char*)malloc(sizeof(char)*100);
        strcpy(this->name,name);
        this->age = age;
    };

    //析构函数:对象被回收的时候会被调用,只能有一个,不能有参数
    ~Student()  {
        //释放内存  这里name使用malloc举个例子
        free(this->name);
    }


private:
    char * name;
    int age;

public:
    
    void setAge(int age){
        this->age = age;
    }
    void setName(char*name) {
        this->name = name;
    }

    int getAge() {
        return this->age;
    }

    char * getName() {
        return this->name;
    }
};

malloc free new delete区别

  1. malloc/free一起用 new/delete一起用
  2. malloc/free不会调用构造函数和析构函数,new/delete会调用构造函数和析构函数
  3. 如果用了new,一定要记得delete释放内存

拷贝构造函数

Class(const Class& C)  
    {  
        //..赋值
    }  
  

https://blog.csdn.net/lwbeyond/article/details/6202256

可变参数 java的Object...


#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

//可变参数
int sum(int count,...) {
    va_list vp;
    //可变参数指定开始  count代表从哪里开始
     va_start(vp,count);
     int sum = 0;
     for (int i = 0; i < count; i++) {
         sum += va_arg(vp, int);
     }
     va_end(vp);
     return sum;
}

int main()
{

    cout<<sum(3, 2, 3, 4)<<endl;
    getchar();
    return 0;
}

static

#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

class Student
{
public:
    char * name;
    int age;
    static int tag;


    Student() {
        tag = 10;
    }

    static void change() {
        tag += 20;
    }

     void change2() {
        tag += 20;
    }

};


//静态属性 在c++中必须初始化,初始化必须这么写
int Student::tag =15;

int main()
{
    cout << Student::tag << endl;//15

    Student stu;
    cout << Student::tag << endl;//10

    Student::change(); //静态函数调用静态变量
    cout << Student::tag << endl;//30

    stu.change2(); //非静态函数调用静态变量
    cout << Student::tag << endl;//50

    getchar();
    return 0;
}
// 1. 调用使用 双冒号 ::
// 2. 静态属性 必须初始化
// 2. 静态函数只能操作静态的相关函数和属性

const函数


#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

class C
{
public:
    int age;
public:
    const void change() {
        this->age += 12;
    }

    //const 在()之后主要用来限制this关键字
    void change2() const {
        //this->age += 12; //不能对类的属性进行修改
    }

    C(int age) {
        this->age = age;
    }

};


int main()
{
    C *c = new C(15);
    c->change();
    cout << c->age << endl;

    
    getchar();
    return 0;
}

友元函数

#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

class Person
{
public:
    Person(int age) {
        this->age = age;
    };
    
    int getAge() {
        return this->age;
    }
    //友元函数 申明之后,friend_change就可以调用私有属性
    friend void friend_change(Person * person, int age);


private:
    int age = 0;


};

void friend_change(Person * person, int age) {
    //age private修饰,在类的内部才能访问私有函数。如果非要访问,就得用到友元函数
    //如果该方法设置为友元函数,那么在外部可以访问其私有属性
    person->age = age;
}





int main()
{
    Person person = Person(24);
    friend_change(&person,20);
    cout << person.getAge() << endl;//20
    getchar();
    return 0;
}

构造函数,析构函数,拷贝构造函数,普通函数,静态函数,友元函数实现

Student.h

#include "stdafx.h"

class Student
{
private:
    int age;
    int time;

public:
    //静态属性的申明
    static int tag;

public:
    //构造函数
    Student();
    Student(int age);
    Student(int time, int age);

    //析构函数
    ~Student();
    //拷贝构造函数 
    Student(const Student &student );


public:
    void setAge(int age);
    void setTime(int time);

    int getAge();
    int getTime();

    void print() const;
    //静态函数
    static void changeTag(int tag_replease);
    //友元函数
    friend void changeAge(Student* stu,int age);

};



实现类 Student.cpp

#include "stdafx.h"
#include "Student.h"
#include <iostream>


//实现类,不一定都要全部实现


//静态属性的申明
int Student::tag = 0;


//构造函数
Student::Student(){ 
    
};

Student::Student(int age):time(200) { //time默认赋值
    this->age = age;
}

Student::Student(int age,int time) { 
    this->age = age;
    this->time = time;
}

//析构函数
Student::~Student() {
    //资源回收
}
//拷贝构造函数
Student::Student(const Student& student) {

}

//普通方法
void Student::setAge(int age) {
    this->age = age;
}
void  Student::setTime(int time) {
    this->time = time;
}

int  Student::getAge() {
    return  this->age;
}
int Student::getTime() {
    return  this->time;
}

// const函数
void Student::print() const {
    //this->age = 20;//不能操作this
        std::cout << this->age << "  " << this->time << "   "<< tag << std::endl;
}

//静态函数
void Student::changeTag(int tag_replease) {
    tag = tag_replease;
}

//友元函数  不需要加 Student::
void changeAge(Student* stu, int age) {
    stu->age = age;
}


demo:

#include "stdafx.h"
#include "Student.h"


void main() {
    Student* stu = new Student(24, 1000);
    //调用const函数
    stu->print();

    //调用静态函数
    Student::changeTag(36);
    stu->print();

    //调用友元函数
    changeAge(stu, 37);
    stu->print();


    delete(stu);

    getchar();
}

友元类 :java的反射获取属性可以理解为就是有一个Class类的友元类

class ImageView {
 public:
     //申明Class是ImageView 的友元类
     friend class Class;
 private:
     int age;
};

 class Class{
 public:
     void changeAge(int age) {
         //正常情况下这是不能直接用的,申明友元类就可以用了
          aObj.age = age;
     }

    int getAge() {
        //正常情况下这是不能直接用的,申明友元类就可以用了
         return aObj.age;
     }
 private :
     ImageView aObj;
 };


 void main() {
     Class b;
     b.changeAge(10);
     std::cout << b.getAge() << std::endl; // 10
     getchar();
 }

操作运算符


#include <iostream>

using namespace std;


class  Vector
{
public:
    Vector(int x, int y){
        this->x = x;
        this->y = y;
    }

    Vector(const Vector &vector){
        this->x = vector.x;
        this->y = vector.y;
        cout << "拷贝构造函数" << endl;
    }
private:
    int x;
    int y;

public:
    void setX(int x){
        this->x = x;
    }
    void setY(int y){
        this->y = y;
    }

    int getX(){
        return this->x;
    }
    int getY(){
        return this->y;
    }

    // 重载减号运算符
    // 为什么要用引用,为了防止重复创建对象
    // const 关键常量,为了防止去修改值
    Vector operator - (const Vector &vector){
        int x = this->x - vector.x;
        int y = this->y - vector.y;
        Vector res(x, y);
        return res;// 不建议返回引用
    }

    // 自增减运算符
    void operator ++ (){// ++X
        this->x = this->x++;
        this->y = this->y++;
    }

    void operator ++ (int){// X++
        this->x = this->x++;
        this->y = this->y++;
    }

    // 自减
    // 输出运算符
    friend ostream & operator << (ostream &_Ostr, const Vector &vector){
        _Ostr << vector.x << "," << vector.y << endl;
        return _Ostr;
    }

    // 条件运算符
    bool operator == (const Vector &vector){
        return (this->x == vector.x && this->y == vector.y);
    }
};

// 定义在类的外面,一般来讲我们定义在类的里面
// 重载运算 + :operator +
Vector operator + (Vector vector1, const Vector vector2){
    int x = vector1.getX() + vector2.getX();
    int y = vector1.getY() + vector2.getY();
    Vector vector(x,y);
    return vector;
}

void main(){
    Vector vector1(2, 3);
    Vector vector2(2, 3);

    // java 中 string + string 

    // char* str = "123" + "456";

    // 重载运算符 +
    // Vector vector = vector1 - vector2;

    // Vector vector(1, 2);
    // vector++;
    // ++vector;

    // cout << vector.getX() << " , " << vector.getY() << endl;
    // cout << vector << vector;
    bool isEqual = vector1 == vector2;
    cout << isEqual << endl;

    // 可以重载加其他对象 Person

    getchar();
}



// 括号运算符
class Array
{
public:
    Array(int size){
        this->size = size;
        this->array = (int*)malloc(sizeof(int)*size);
    }
    ~Array(){
        if (this->array){
            free(this->array);
            this->array = NULL;
        }
    }

    Array(const Array& array){
        this->size = array.size;
        this->array = (int*)malloc(sizeof(int)*array.size);

        // 值的赋值
        for (int i = 0; i < array.size; i++)
        {
            this -> array[i] = array.array[i];
        }
    }

private:
    int size;
    int* array;

public:
    void set(int index,int value){
        array[index] = value;
    }

    int get(int index){
        return this->array[index];
    }

    int getSize(){
        return this->size;
    }

    // 操作符[]
    int operator[](int index){
        return this->array[index];
    }
};

void printfArray(Array array){
    for (int i = 0; i < array.getSize(); i++)
    {
        cout << array[i] << endl;
    }
}

void main(){
    
    Array *array = new Array(5);

    array->set(0,0);
    array->set(1, 1);
    array->set(2, 2);

    printfArray(*array);

    delete(array);
    getchar();
}


类的继承 : 类继承,构造函数调用顺序:先父类 -> 再子类 ,析构函数调用顺序 : 先子类 -> 再父类


// 初始化属性
class Person{
    // 变量修饰符
public:// 本类中使用
    // protected :子类中能使用 (默认)
    // public :公开,任何地方都可以
    char* name;
    int age;

public:
    Person(char* name, int age){
        this->name = name;
        this->age = age;
        cout << "Person 构造函数" << endl;
    }

public:
    void print(){
        cout << this->name << " , " << this->age << endl;
    }
};


class Student : public Person
{
private:
    char* courseName;
public:
    // : Person(name,age) 调用构造函数初始化父类的属性
    // 不光可以给父类初始化属性,还可以给本类的属性进行初始化,用 , 隔开即可
    Student(char* name, int age, char* courseName) :Person(name, age), courseName(courseName){// 调用父类构造函数
        cout << "Student 构造函数" << endl;
    }

    void print(){
        cout << "courseName: " << courseName << endl;
    }
};

class Teacher: public Person
{
public:
    Teacher(char*name,int age):Person(name,age){
        
    }
};

void main(){
    Student stu("张三",24,"语文");
    stu.print();
    getchar();
}

#include <iostream>
using namespace std;

class Person {
protected:
    char* name;
    int age;
public:
    Person(char* name, int age){
        this->name = name;
        this->age = age;
    }
};

class Course
{
private:// java String
    string name;
public:
    Course(string name){
        this->name = name;
    }

public:
    string _name(){
        return this->name;
    }
};


class Student : public Person
{
private:
    Course course;
public:
    Student(char* name, int age, string courseName) : Person(name, age), course(courseName){ // 初始化父类的属性
    }

    void print(){
        cout << name << "," << age << "," << course._name().c_str() << endl;
    }
};

多继承

#include <iostream>
using namespace std;

class Person{
private:
    char * name;

public:
    Person(char * name){
        this->name = name;
    }

    char* _name(){
        return this->name;
    }
};

class Child
{
    int age;
public:
    Child(int age){
        this->age = age;
    }

    int _age(){
        return this->age;
    }
};

// 多继承,在 java 里面是不允许多继承 , c++ 是可以的,但是你也不能有二义性(歧义)
class Student : public Person, public Child // 多继承 , 并没有实现(接口)
{
public:
    Student(char* name,int age):Person(name),Child(age){

    }
};

虚继承:解决二义性

class A{
public:
    char* name;
};

class B : virtual public A{ // virtual 确保继承过来的相同属性或者函数,只存在一份拷贝

};
 
class C :virtual public A{

};

class D : public B ,public C
{

};


多态:c++里面分为动态多态(子父类 需要virtual修饰),静态多态(函数的重载),区别是编译过程确定性。

class Activity
{
public:
    virtual void onCreate(){ // 支持多态,虚函数
        cout << "Activity 中的 onCreate" << endl;
    }
};

class MainActivity : public Activity
{
public:
    void onCreate(){
        cout << "MainActivity 中的 onCreate" << endl;
    }
};

class WelcomeActivity : public Activity
{
public:
    void onCreate(){
        cout << "WelcomeActivity 中的 onCreate" << endl;
    }
};

void startActivity(Activity* activity){
    activity->onCreate();
}

void main(){
    Activity *activity1 = new MainActivity();// 父类 = new 子类对象
    Activity *activity2 = new WelcomeActivity();

    // activity->onCreate();
    // c++ 中的多态是怎样的,默认情况下不存在
    // 父类指向子类的引用,重写 ,里氏替换原则 
    // 程序在编译期间并不知晓运行的状态(我需要运行那个函数),只要在真正运行的过程中才会去找需要运行的方法
    startActivity(activity1);//如果Activity里面onCreate不加virtual,那么将会执行Activity的onCreate不会执行MainActivity的onCreate
    startActivity(activity2);

    // c++ 多态:动态多态(子父类),静态多态(函数的重载)(编译过程确定性的区别)

    getchar();
}

抽象类,抽象函数

// java 中类似的 抽象类,接口 纯虚函数
class BaseActivity // 跟 java 中的抽象类一个概念
{
public:
    void onCreate(){// 普通函数
        initView();
        initData();
    }

    // 子类必须要实现 
    virtual void initData() = 0;// 虚函数,没有实现的,类似于 java 中的抽象方法,如果子类不实现会报错

    virtual void initView() = 0;

};

// 如果不实现父类的纯虚函数,那么 MainActivity 也会变成抽象类,抽象类不允许实例化
class MainActivity : public BaseActivity 
{
public:
    void initData(){
        cout << "initData" << endl;
    }

    void initView(){
        cout << "initView" << endl;
    }
};

void main(){
    
    BaseActivity *m_a = new MainActivity();

    m_a->onCreate();

    getchar();
}

接口


class ClickListener{// 所有的函数都是虚函数,那么就可以认为是接口
public:
    virtual void click() = 0;
};

class ImageClickListener : public ClickListener
{
public :
    void click(){
        cout << "图片点击" << endl;
    }
};

void main(){
    // 函数指针的时候:回调可以用 指针函数作为回调,纯虚函数类进行回调(接口)
    // ClickListener *listener = new ImageClickListener();

    //直接调用
    // listener->click();

    getchar();
}

模板函数 : java 中的泛型

// 模板函数的定义
template <typename T> T add(T number1, T number2){
    return number1 + number2;
}

void main(){
    
    int sum1 = add(1,2);

    cout << sum1 << endl;

    int sum2 = add(1.0, 2.0);

    cout << sum2 << endl;

    int sum3 = add(1.0f, 2.0f);

    cout << sum3 << endl;

    getchar();
}

模板类

template <typename T> class Callback{
public:
    void onError(){
        
    }

    void onSucceed(T result){
        cout << result << endl;
    }
};

// 模板类继承 ,子类如果也是模板类
// 如果子类不是模板类
class HttpCallback : public Callback<int>{
    
};

template <class T>
class HttpCallback : public Callback<T>{

};

void main(){
    HttpCallback<int> *callback = new HttpCallback<int>();

    callback->onSucceed(12);

    getchar();
}

如果开发中涉及到模板类,申明和实现要写在同一个类里面: hpp = h + cpp/c (编译)

例如:c++实现ArrayList

ArrayList.hpp

#include <malloc.h>
//------------------类的定义-------------------//

template<class E>
class ArrayList {
public:
    // 数组头指针
    E *array = NULL;
    // 数组长度
    int len = 0;
    // 数据大小
    int index = 0;
public:
    ArrayList();

    ArrayList(int len);

    ~ArrayList();

    ArrayList(const ArrayList &list);

public:
    bool add(E e);

    int size();

    E get(int index);

    E remove(int index);

private:
    void ensureCapacityInternal(int i);

    void grow(int capacity);
};

//------------------类的实现-------------------//
template<class E>
ArrayList<E>::ArrayList() {

}

template<class E>
ArrayList<E>::ArrayList(int len) {
    if (len == 0) {
        return;
    }
    this->len = len;
    this->array = (E *) malloc(sizeof(E) * len);
}

template<class E>
ArrayList<E>::~ArrayList() {
    if (this->array) {
        free(this->array);
        this->array = NULL;
    }
}

template<class E>
ArrayList<E>::ArrayList(const ArrayList &list) {
    this->index = list.index;
    this->len = list.len;
    // 深拷贝
    this->array = (E *) malloc(sizeof(E) * len);
    memcpy(this->array,list.array,sizeof(E) * len);
}

template<class E>
E ArrayList<E>::get(int index) {
    return this->array[index];
}

template<class E>
int ArrayList<E>::size() {
    return this->index;
}

template<class E>
E ArrayList<E>::remove(int index) {
    E old_value = this->array[index];
    // 计算出需要逻动的个数
    int numMoved = this->index - index - 1;

    // 从前面不断的逻动
    for (int i = 0; i < numMoved; ++i) {
        array[index + i] = array[index + i + 1];
    }

    this->index -= 1;
    return old_value;
}

template<class E>
bool ArrayList<E>::add(E e) {
    ensureCapacityInternal(index + 1);
    this->array[index++] = e;
    return true;
}

// 是否需要调整当前数组大小
template<class E>
void ArrayList<E>::ensureCapacityInternal(int minCapacity) {
    // 当前数组是不是空,或者 len 是不是 0
    if (this->array == NULL) {
        minCapacity = 10;// 第一次初始化大小
    }

    // 判断要不要扩容
    if (minCapacity - len > 0) {
        grow(minCapacity);
    }
}

// 扩容创建新的数组
template<class E>
void ArrayList<E>::grow(int capacity) {
    // 计算新数组大小的长度
    int new_len = len + (len >> 1);

    if (capacity - new_len > 0) {
        new_len = capacity;
    }

    // 创建新的数组
    E *new_arr = (E *) malloc(sizeof(E) * new_len);

    if (this->array) {
        // 拷贝数据
        memcpy(new_arr, array, sizeof(E) * index);
        // 释放原来的内存
        free(this->array);
    }

    array = new_arr;
    len = new_len;
}


使用的时候引入ArrayList.hpp

#include "ArrayList.hpp"
#include <jni.h>
#include <string>
#include <android/log.h>

#include "ArrayList.hpp"

extern "C"
JNIEXPORT void
JNICALL
Java_com_zzw_demo_MainActivity_test(
        JNIEnv *env,
        jobject /* this */) {

    ArrayList<int> *list = new ArrayList<int>();//

    for (int i = 0; i < 100; ++i) {
        list->add(i);
    }

    for (int i = 0; i < list->size(); ++i) {
        __android_log_print(ANDROID_LOG_ERROR,"TAG","i = %d",list->get(i));
    }

    delete(list);
}


异常处理


class Exception
{
public:
    string msg;

public:
    Exception(string msg){
        this->msg = msg;
    }

public:
    const char *what(){
        return this->msg.c_str();
    }

};

// 异常的处理
void main(){
    // c++ 中有自己一套异常的体系,不要去强记
    // 但是 c++ 可以抛任何数据类型 try{}catch(数据类型 变量名){}
    // throw 抛异常

     try{
        int i = -1;

        if (i == 0){
            throw Exception("出异常了");
        }

        if (i< 0){
            throw 12.5f;
        }
     }
    catch (int number){
        cout << "捕捉到异常" <<number << endl;
    }
    catch (Exception exception){
        cout << "捕捉到异常:" << exception.what() << endl;
    }
    catch (...){
        cout << "捕捉到其他异常:" << endl;
    }

    getchar();
}

字符串常见操作

创建

void main(){

    string str1 = "123";
    string str2("123");
    string str3(5, 'A');// 5 个 A = AAAAA
    string *str4 = new string("123");

    // cout << str1.c_str() <<endl;
    // cout << str2.c_str() << endl;
    // cout << str3.c_str() << endl;
    // cout << str4->c_str() << endl;

    // string 与 char* 相互之间转换 c_str()
    // const char* c_str1 = str1.c_str();
    // cout << c_str1 << endl;

    // char* -> string
    char* c_str = "张三";
    string str(c_str);// 对象
    cout << str.c_str() << endl;


    getchar();
}

遍历

void main(){

    string str("1234567");

    // 1. 字符串的遍历
    for (int i = 0; i < str.length(); i++)
    {
        cout << str[i] << endl;
    }

    // 迭代器遍历
    for (string::iterator it = str.begin(); it < str.end(); it++)
    {
        cout << *it << endl;
    }

    try{
        for (int i = 0; i < str.length()+2; i++)
        {
            cout << str.at(i) << endl;// 如果越界会抛异常
        }

        for (int i = 0; i < str.length()+2; i++)
        {
            cout << str[i] << endl;// 会导致程序宕机,AS里面是可以的
        }
    }
    catch (...){
        cout << "异常了" << endl;
    }

    getchar();
}

添加

void main(){

    // 添加
    string str1 = "123";
    string str2 = "456";

    // str1 = str1 + str2;
    // str1.append(str2);


    cout << str1.c_str() << endl;

    getchar();
}


删除

void main(){

    // 删除
    string str1 = "123 abc 123 abc 123";

    // str1.erase(0,3);// 第一个参数:从哪里开始 ; 第二个参数:删除几个(默认值,字符串的结尾)

    // 迭代器删除  2 bc 123 abc 123 解释  第一次删除第一个位置1,变为23 abc....  ,第二次删除第二个位置3,变为2 abc.... ,第三次删除第三个位置a,就是2 bc ....
    for (string::iterator it = str1.begin(); it<str1.begin()+3; it++)// 删除一个字后都会从头开始计算
    {
        str1.erase(it);
    }

    cout << str1.c_str() << endl;

    getchar();
}

替换

void main(){

    string str1 = "123 abc 123 abc 123";
    // 第一个参数:从哪里开始
    // 第二个参数:替换几个
    // 第三个参数:替换成谁
    str1.replace(0,6,"1234");

    cout << str1.c_str() << endl;

    getchar();
}

查找


void main(){

    string str1 = "123 abc 123 abc 123";
    // 查找谁,从哪里开始
    // int position = str1.find("123",0);
    // 从后面往前面查
    int position = str1.rfind("123");

    cout << position << endl;

    getchar();
}

大小写转换

void main(){

    string str1 = "AAA abc BBB abc 123";
    // 转换成大写
    // transform(str1.begin(), str1.end(), str1.begin(), toupper);

    transform(str1.begin(), str1.end(), str1.begin(), tolower);

    cout << str1.c_str() << endl;

    getchar();
}


STL标准模板库 : 容器+迭代+算法

vector容器(数组)

https://zh.cppreference.com/w/cpp/container/vector

容量

    向量大小: vec.size();
    向量真实大小: vec.capacity();
    向量判空: vec.empty();


修改

    末尾添加元素: vec.push_back();
    末尾删除元素: vec.pop_back();
    任意位置插入元素: vec.insert();
    任意位置删除元素: vec.erase();
    清空向量元素: vec.clear();


迭代器
    开始指针:vec.begin();
    末尾指针:vec.end(); //指向最后一个元素的下一个位置
    指向常量的末尾指针: vec.cend();


元素的访问
    下标访问: vec[1]; //并不会检查是否越界
    at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
    访问第一个元素: vec.front();
    访问最后一个元素: vec.back();



stack容器(链表,数组)
https://zh.cppreference.com/w/cpp/container/stack

queue容器(数组,链表)
https://zh.cppreference.com/w/cpp/container/queue

list容器(链表)
https://zh.cppreference.com/w/cpp/container/list

set容器(红黑树,元素不重复)
https://zh.cppreference.com/w/cpp/container/set

multiset容器(元素可重复)
https://zh.cppreference.com/w/cpp/container/multiset

map容器(key不能重复)
https://zh.cppreference.com/w/cpp/container/map

multimap容器(以key分组)
https://zh.cppreference.com/w/cpp/container/multimap

对象添加到容器需要注意的:

  1. java 中把对象添加到了集合,c++ 中会调用对象的拷贝构造函数,存进去的是另一个对象
  2. 在c++中将对象加入到容器,需要有默认的构造函数
  3. 析构函数也可能回调用多次,如果说在析构函数中释放内存,需要在拷贝构造函数中进行深拷贝

仿函数


class Compare{
    // 重载了括号运算符
public:
    void operator()(){
        cout << "仿函数" << endl;
    }
};

void compare1(){
    cout << "普通函数" << endl;
}

// 函数对象(仿函数) 一元谓词,二元谓词
void main(){
    Compare compare;

    // 跟函数非常类似
    compare();//打印“仿函数”
    // 普通函数调用
    compare1();

    getchar();
}

谓词

一元谓词


// 一元谓词
void print(int number){
    cout << number << endl;
}

// 仿函数 - 一元谓词 (能够记录状态)
class PrintObj
{
public:
    int count = 0;
public:
    void operator()(int number){
        cout << number << endl;
        count++;
    }
};

// 回调函数和仿函数的区别
void main() {

    set<int> set1;
    set1.insert(1);
    set1.insert(2);
    set1.insert(3);
    set1.insert(4);

    // for_each 迭代器 ,非常重要的一点就是:仿函数如果要保存记录状态,要确保对象一致,可以用返回值
    // for_each(set1.begin(),set1.end(),print);//会打印
    PrintObj printObj;
    //for_each(set1.begin(), set1.end(), printObj);
    //cout << "个数:" << printObj.count << endl; //个数:0 ,要确保对象一致
    printObj = for_each(set1.begin(), set1.end(), printObj);
    cout << "个数:" << printObj.count << endl; //个数:4 ,对象一致

    getchar();
}


二元谓词


#include <set>
#include <iostream>

using namespace std;

class CompareObj{
public:
    int count = 0;
public:
    bool operator()(const string str1, const string str2) {
        return str1 > str2;
    }
};

void main() {
    // 二元谓词的仿函数
    set<string, CompareObj> set1;
    set1.insert("aaa");
    set1.insert("aAa");
    set1.insert("ccc");
    set1.insert("ddd");
    // 是否包含 aaa , 遍历比较 , 找方法
    for (set<string>::iterator it = set1.begin(); it != set1.end(); it++)
    {
        cout << (*it).c_str() << endl;
    }
    //ddd ccc aaa aAa
    getchar();
}

预定义函数对象(自定义重载 () 运算符),函数适配器

#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;


// 自定义重载 () 运算符
//预定义函数对象
void main(){
    // c/c++ 提供了很多定义好的函数对象
    // 常见的几个 less ,greater,plus,equal_to
    plus<string> strAdd;
    string str = strAdd("aaa","bbb");

    // cout << str.c_str() << endl;

    set<string, greater<string>> set1;
    set1.insert("aaa");
    set1.insert("bbb");
    set1.insert("ccc");

    // 判断是不是包含 aaa 
    // 怎么写仿函数,一定要确定好你的仿函数的参数
    // bind2nd 函数适配器 , aaa 相当于 equal_to 中的 right 
    set<string, greater<string>>::iterator find_it = find_if(set1.begin(), set1.end(),bind2nd(equal_to<string>(),"aaa"));
    if (find_it != set1.end()){
        cout << "找到了" << (*find_it).c_str() << endl;
    }
    else
    {
        cout << "没有找到" << endl;
    }

    getchar();
}

#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;

class Equal
{
private:
    int equal_number;
public:
    Equal(int equal_number) {
        this->equal_number = equal_number;
    }
public:
    bool operator()(const int& number) {
        return number == equal_number;
    }
};

void main() {
    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(2);
    vector1.push_back(3);
    vector1.push_back(2);
    vector1.push_back(4);
    vector1.push_back(2);

    // 找集合中 等于 2 的个数
    int count = count_if(vector1.begin(), vector1.end(), Equal(2));
    cout << "count = " << count << endl;

    // 预定义好的函数对象 + 函数适配器
    count = count_if(vector1.begin(), vector1.end(), bind2nd(equal_to<int>(), 2));
    cout << "count = " << count << endl;

    getchar();
}

#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;

void print(int number) {
    cout << number << endl;
}

// 进行修改
int transform_print(int number) {
    // cout << number << endl;
    return number + 3;
}

// foreach,transform,find,find_if,count,count_if,megre,sort,random_shuffle,copy,replace
// 常用预定义算法 循环,增,删,改,    
void main() {
    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(2);
    vector1.push_back(3);
    vector1.push_back(4);

    //for_each循环
    // for_each(vector1.begin(), vector1.end(),print); //1234
    vector<int> vector2;
    vector2.resize(vector1.size());

    //变换和循环
    transform(vector1.begin(), vector1.end(), vector2.begin(), transform_print);//4567

    for_each(vector2.begin(), vector2.end(), print);

    getchar();
}

#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;

void print(int number) {
    cout << number << endl;
}

// 进行修改
int transform_print(int number) {
    // cout << number << endl;
    return number + 3;
}

// foreach,transform,find,find_if,count,count_if,megre,sort,random_shuffle,copy,replace
// 常用预定义算法 循环,增,删,改,    
void main() {
    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(2);
    vector1.push_back(3);
    vector1.push_back(4);

    vector<int>::iterator find_it = find(vector1.begin(), vector1.end(), 2);

    if (find_it != vector1.end()){
        cout << "包含" << endl;
    }
    else
    {
        cout << "不包含" << endl;
    }

    // 有没有大于2的,自定义函数对象,预定义函数对象+函数适配器,省略...
    //findif() //上面有
    getchar();
}


void main(){
    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(2);
    vector1.push_back(3);
    vector1.push_back(2);
    vector1.push_back(4);

    int number = count(vector1.begin(), vector1.end(), 2);

    cout << "等于2的个数:" << number << endl;

    number = count_if(vector1.begin(), vector1.end(), bind2nd(less<int>(), 2));

    cout << "小于2的个数:" << number << endl;

    number = count_if(vector1.begin(), vector1.end(), bind2nd(greater<int>(), 2));

    cout << "大于2的个数:" << number << endl;

    getchar();
}


using namespace std;


void print(int number) {
    cout << number << endl;
}

// megre,sort,random_shuffle,copy,replace
void main() {

    // 两个有序数组进行合并 - 归并排序
    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(2);
    vector1.push_back(3);

    vector<int> vector2;
    vector1.push_back(4);
    vector1.push_back(5);
    vector1.push_back(6);

    vector<int> vector3;
    vector3.resize(6);
    merge(vector1.begin(), vector1.end(), vector2.begin(), vector2.end(), vector3.begin());
    for_each(vector3.begin(), vector3.end(), print);

    getchar();
}

void print(int number) {
    cout << number << endl;
}

// sort,random_shuffle
void main() {

    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(3);
    vector1.push_back(2);
    vector1.push_back(4);

    sort(vector1.begin(), vector1.end(), less<int>());
    for_each(vector1.begin(), vector1.end(), print);

    cout << "循环结束" << endl;

    // 打乱循序 
    random_shuffle(vector1.begin(), vector1.end());
    for_each(vector1.begin(), vector1.end(), print);

    getchar();
}


void print(int number) {
    cout << number << endl;
}

//copy,replace
void main() {

    vector<int> vector1;
    vector1.push_back(1);
    vector1.push_back(2);
    vector1.push_back(3);
    vector1.push_back(4);

    vector<int> vector2;
    vector2.resize(2);
    copy(vector1.begin(), vector1.begin() + 2, vector2.begin());
     for_each(vector2.begin(), vector2.end(), print);

    replace(vector1.begin(), vector1.end(), 2, 22);
    for_each(vector1.begin(), vector1.end(), print);

    getchar();
}
上一篇下一篇

猜你喜欢

热点阅读