c++基础语法

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();
}
  • foreach,transform
#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();
}
  • find,find_if
#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();
}
  • count,count_if
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();
}
  • megre: 两个有序数组进行合并 - 归并排序
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();
}
  • soft,random_shuffle
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();
}
  • copy,replace
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();
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AILearning

Map集合

Collection |--List:元素是有序的,元素可以重复,因为该集合体系有索引 |--ArrayList:底层的数据结构使用的是数据结构。特点:查询...

2366
来自专栏一“技”之长

Swift讲解专题五——集合类型 原

        Swift中提供了3种集合类型,Array数据类型,Set集合类型,Dictionary字典类型。Array用于存放一组有序的数据,数据角标从0...

783
来自专栏LinkedBear的个人空间

唠唠SE的集合-09——Map接口 原

将键映射到值的对象,一个映射不能包含重复的键,但值可以重复。每个键最多只能映射到一个值。

882
来自专栏黑泽君的专栏

java基础学习_集合类04_Map接口、Collections工具类_day18总结

============================================================================= ==...

771
来自专栏CRPER折腾记

JS数组去重!!!一篇不怎么靠谱的"深度"水文

数组去重,这是一个老梗了...今天我又拿出来说了... 我们在考虑全面一点的情况下,数组去重的实现,比如针对NaN,undefined,{}; 这其中涉及的知识...

1014
来自专栏LinkedBear的个人空间

唠唠SE的集合-01——Collection接口

当集合中存储的对象类型不同时,那么会导致程序在运行的时候的转型异常,所以jdk1.5加入了泛型机制。

652
来自专栏吾爱乐享

java之学习去除ArrayList中重复自定义对象元素

1526
来自专栏章鱼的慢慢技术路

顺序表示的线性表——顺序表

2164
来自专栏IT可乐

Java 集合详解

一、集合的由来   通常,我们的程序需要根据程序运行时才知道创建多少个对象。但若非程序运行,程序开发阶段,我们根本不知道到底需要多少个数量的对象,甚至不知道它的...

2609
来自专栏计算机视觉与深度学习基础

java在acm中大数运算教程

import java.io.*; import java.util.*; public class Main { public static void ...

2059

扫码关注云+社区