c++基础语法
c和c++联系
- c++代码可以混编c代码,既可以写c也可以调用c
- c++面向对象,c面向过程
- 开源框架大部分都是基于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区别
malloc/free
一起用new/delete
一起用- malloc/free不会调用构造函数和析构函数,new/delete会调用构造函数和析构函数
- 如果用了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
对象添加到容器需要注意的:
- java 中把对象添加到了集合,c++ 中会调用对象的拷贝构造函数,存进去的是另一个对象
- 在c++中将对象加入到容器,需要有默认的构造函数
- 析构函数也可能回调用多次,如果说在析构函数中释放内存,需要在拷贝构造函数中进行深拷贝
仿函数
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();
}