bilibili 黑马程序员课程

Day 1

1.1 变量
作用:方便管理内存空间;

  1. int a=10;

1.2 常量
作用:不可更改的数据;
定义: # define 宏常量 或 const 修饰的变量

#define day 7
const int month=12;

1.3 关键字
作用:C++预先保留的单词(标识词)
1.4 标识符
开头只能是字母或数字,见名知意

  1. 数据类型

2.1 作用:给变量分配合适的内存空间

整形
(区别在于所占内存空间不同)
short (短整型)
int(整型)
long (长整型)
long long (长长整型)
2字节
4字节
window为4字节,linux为 4字节、8字节
8字节
实型(浮点型) float 单精度
double双精度
7位有效数字
15-16位有效数字
float f1=3.14f,加f是为了避免默认的double.
默认情况下,输出一个小数会显示6位小数。
科学计数法:f2=3e2, 其实是 3*10^2
字符型 char 1个字节 显示单个字符,单引号,char ch = ‘a’;
是将字符对应的ASCII编码放到存储单元;a-97,A-65.
转移字符 \n
\t
\\
换行符
水平制表符
反斜杠
短斜杠
水平制表符默认8个位置,4个空格,但可以整齐输出数据
字符串 char
string
char str1[]=”hello” 注意[ ]和双引号, C风格
string str2=”hello” 要包含头文件 ,C++风格
布尔类型 bool 1个字节 true , false . 其实就是1和0

2.2 sizeof
运算符,统计数据类型所占内存大小

sizeof(short/num1); //sizeof(变量或数据类型)

2.3 数据

int a=0;
cin>>a;  //输入
cout<<a;  //输出
  1. 运算符 | 算术运算符 | 处理四则运算,+ - / %(取余) ++(递增) —(递减) | 两个小数不可取余数,必须有一个整数.
    前置 ++a, —a, 后置 a++, a— .
    前置,先变量+1,在进行表达式运算,后置,先进行表达式运算,在变量+1. | | —- | —- | —- | | 赋值运算符 | = += -+
    = /= %= | | | 比较运算符 | == != < > <= >= | 输出1或0 | | 逻辑运算符 | ! && || | |

  2. 程序流程结果

  • 顺序结构
  • 选择结构
  • 循环结构

4.1 顺序结构——if 、 if else 、 switch

//单行格式if语句
if (score>600){
    cout<<"Success!"<<endl;
}
//多行格式if语句
if(score>600){
    cout<<"Success!"<<endl;
}else{
    cout<<"Fail!"<<endl;
}
//多行条件if语句
if(score>600){
    cout<<"Success!"<<endl;
}else if(score>400){
    cout<<"Fail-1!"<<endl;
}else if(score>200){
    cout<<"Fail-2!"<<endl;
}else{
    cout<<"Fail-3!"<<endl;
}

//还有一种嵌套if
if(score>600){
    if(score>700){
         cout<<"Success-1!"<<endl;
    }else{
         cout<<"Success-2!"<<endl;
    }
}else if(score>400){
    cout<<"Fail-1!"<<endl;
}else if(score>200){
    cout<<"Fail-2!"<<endl;
}else{
    cout<<"Fail-3!"<<endl;
}

Day 2

案例一:三只小猪称体重, 找最重的。

#include<iostream>
using namespace std;

int main(void){

    int num1,num2,num3;
    char flag;
    cout<<"请输入三只小猪的体重:"<<endl;
    cin>>num1>>num2>>num3;
    if(num1>=num2){
        flag=num1>=num3?'A':'C';
        cout<<"小猪"<<flag<<"最重"<<endl;
    }else{
        flag=num2>=num3?'B':'C';
        cout<<"小猪"<<flag<<"最重"<<endl;
    }

    system("pause");
    return 0;
}

三目运算符,可以返回值,也可以返回变量(继续赋值)。

switch(表达式){
  case 结果1: 语句1; break;
  case 结果2: 语句2; break;
  case 结果3: 语句3; break;
  default :    语句4;break;
}

相比于if:
switch只能判断整型和字符型,不可以是一个区间,但是结构清晰,执行效率高。

4.2 循环结构——while 、 do…while 、for 、嵌套循环

while(循环条件){
  循环语句;
}


do{
  循环语句;
}while(循环条件);
//先执行一次


for(int i=0;i<100;i++){
    循环语句;
}

//嵌套循环

案例:猜数字,随机1-100 ,while

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    //添加随机数种子,根据系统时间生成,防止每次生成的随机数都一样
    srand((unsigned int)time(NULL));
     //生成随机数1-100,rand()%区间
    int num=rand()%100+1;  

    int val=0;
    while(1){
        cout<<"请输入您的猜测:"<<endl;
        cin>>val;
        if(val>num){
            cout<<"过大"<<endl;
        }else if(val<num){
            cout<<"过小"<<endl;
        }else{
            cout<<"猜对了"<<endl;
            break;
        }
    } 

    system("pause");
    return 0;
}

案例:输出所有三位数中的水仙花数,每个位子上的数字的三次幂之和等于其本身 do…while

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    int num=100;
    int ge=0,shi=0,bai=0;
    do{
        ge=num%10;
        shi=num/10%10;
        bai=num/100;
        if(ge*ge*ge+shi*shi*shi+bai*bai*bai==num){
            cout<<num<<endl;
        }
        num++;
    }while(num<1000);

    system("pause");
    return 0;
}

案例:敲桌子,从1报到100,含7或7的倍数,输出敲桌子 for

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    for(int i=1;i<100;i++){
        if(i/10==7||i%10==7||i/7==0){
            cout<<"敲桌子"<<endl;
        }else{
            cout<<i<<endl;
        }
    }
    system("pause");
    return 0;
}

案例:星图 嵌套循环

#include<iostream>
#include <time.h>

using namespace std;

int main(void){
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            cout<<"* ";
        }            
        cout<<endl;
    }    

    system("pause");
    return 0;
}

案例:乘法口诀 嵌套循环

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    for(int i=1;i<10;i++){
        for(int j=1;j<=i;j++){
            cout<<j<<"*"<<i<<"="<<i*j<<"    ";
        }            
        cout<<endl;
    }    

    system("pause");
    return 0;
}

4.3 跳转语句 break 、 contiinue 、goto
break:用在switch、 循环 、嵌套中,跳出循环
continue :跳出本次循环,执行下一次循环。
goto:无条件跳转。goto FLAG;FLAG:xxxxx;

5 数组
放在一块连续的内存空间。通过下标访问。存放相同数据类型。
5.1 一维数组

//创建,第一种
int arr[5];
arr[0]=1;

//创建,第二种
int arr[3]={1,2,3};

//创建,第三种
int arr[]={1,2,3};

数组名用途:

  • 统计长度、元素个数 sizeof(arr); sizeof(arr[0]);
  • 获取在内存的首地址 cout<<arr<endl; cout<<&arr[0]<<endl; 首地址其实就是第一个元素地址

案例:五只小猪称体重,找最大。

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    int weight[5],w_max=0;
    cout<<"请依次输出小猪的重量:"<<endl;
    for(int i=1;i<5;i++){
        cin>>weight[i];
        if(w_max<weight[i]){
            w_max=weight[i];
        }
    }  
    cout<<"最重的小猪重量为:"<<w_max<<"kg"<<endl;

    system("pause");
    return 0;
}

案例:元素逆置,首尾交换

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    int num_arr[5];
    cout<<"请依次输入元素:"<<endl;
    for(int i=0;i<5;i++){
        cin>>num_arr[5-1-i];
    } 
    for(int i=0;i<5;i++){
        cout<<num_arr[i]<<"  ";
    }  

    system("pause");
    return 0;
}


//或者 交换
#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    int num_arr[5];
    cout<<"请依次输入元素:"<<endl;
    for(int i=0;i<5;i++){
        cin>>num_arr[i];
    }

    int start=0,end=sizeof(num_arr)/sizeof(num_arr[0])-1;
    int temp=num_arr[start];
    while(start<end){
        temp=num_arr[start];
        num_arr[start]=num_arr[end];
        num_arr[end]=temp;
        start++;end--;
    }

    for(int i=0;i<5;i++){
        cout<<num_arr[i]<<" ";
    }

    system("pause");
    return 0;
}

案例:冒泡排序 升序

#include<iostream>
#include <time.h>
using namespace std;

int main(void){
    int length=8;
    int num_arr[length];
    int temp;
    cout<<"请依次输入8个元素:"<<endl;
    for(int i=0;i<8;i++){
        cin>>num_arr[i];
    }

    for(int i=0;i<length-1;i++){    //总共排序轮数为length-1
        for(int j=0;j<length-1-i;j++){   //内层对比次数 length-当前轮数-1
            if(num_arr[j]>num_arr[j+1]){
                temp=num_arr[j];
                num_arr[j]=num_arr[j+1];
                num_arr[j+1]=temp;
            }
        }
    }
    for(int i=0;i<8;i++){
        cout<<num_arr[i]<<"  ";
    }
    cout<<endl;

    system("pause");
    return 0;
}

5.2 二维数组

//创建 第1种
int arr[2][3];
arr[0][0]=1;  arr[0][1]=2;  arr[1][0]=1;

//创建 第2种
int arr[2][3]={ {1,2,3}, {4,5,6} };

//创建 第3种
int arr[2][3]={ 1,2,3,4,5,6 };

//创建 第4种  行数可省略
int arr[][3]={ 1,2,3,4,5,6 };

数组名: 查看数组所占内存空间sizeof, 获取数组首地址
案例: 统计考试成绩
image.png

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

int main(void){
    int score[3][3]={100,100,100,90,50,100,60,70,80};
    int result[3]={0};
    string names[3]={"张三","李四","王五"};
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++)
            result[i]+=score[i][j];
        cout<<names[i]<<"的总分是:"<<result[i]<<endl;
    }

    system("pause");
    return 0;
}

6 函数
实参 形参
值传递:函数调用时将实参传入形参。但形参的改变不会影响实参。 因为他们占据不同的内存空间。
函数声明:函数定义前,告诉编译器有这样的一个函数。
分文件编写: 头文件 (.h文件中写函数声明) 源文件(.cpp文件中写函数定义)

7 指针
7.1 作用:通过指针间接访问内存,通过一个指针来保存地址,指针就是地址。
定义: (&取地址符)
使用:解引用,即在指针前加*,就能找到指针指向的内存的中的数据

int a=10; 
int * p;  
p=&a;  (地址)
a=*p;  (值)

所占的内存空间:4个字节(32位操作系统下)8个字节(64位操作系统下) sizeof(int *)或 sizeof(p)
空指针:指针表里指向内存中编号为0的空间,用来初始化指针变量,指向的内存不可访问(0-255编号的内存是系统占用的)。
野指针:非法的内存空间。

7.2 用const修饰指针
const 修饰指针——常量指针; 指针前加const 如,const int p =&a; 是一个指针,指向一个常量。
指针的指向可以修改,但是指针指向的值不可以改。
p=20;不可以,但p=&b可以。
const修饰常量——指针常量; int const p =&a; 指针的指向不可以变,但是指针指向的值可以改 p=20;可以,但p=&b不可以。 是一个常量。
const既修饰指针,又修饰常量。 const int * const p =&a; 指针的指向和指针指向的值都不可以变。

7.3 指针和数组
利用指针访问数组元素

cout<<arr[0];  //传统方式

int * p=arr;  //arr就是数组首地址
cout<<"第一个元素"<<*p;
p++;  //指针偏移
cout<<"第2个元素"<<*p;

7.4 指针和函数
利用指针做函数参数,可以修改实参的值。
区别于值传递,形参的改变不影响实参,指针上的是地址传递,形参的改变影响实参。


void swap1(int a,int b){
    int temp=a;
    a=b;
    b=temp;
}
void swap2(int *a, int *b){
    int temp=*a;
    *a=*b;
    *b=temp;
}
int main(void){
    int a=1,b=2;
    cout<<a<<" "<<b<<endl;
    swap1(a,b);
    cout<<a<<" "<<b<<endl;
    swap2(&a,&b);
    cout<<a<<" "<<b<<endl;
    system("pause");
    return 0;
}

结果:
1 2
1 2
2 1

案例:封装一个函数,冒泡排序,整型数组升序

void BubbleSort(int * arr,int len){
    for(int i=0;i<len-1;i++){
        for(int j=0;j<len-i-1;j++){
            if(arr[j]>arr[j+1]){
                int temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
}
void PrintArray(int *arr,int len){
    for(int i=0;i<len;i++){
        cout<<arr[i]<<endl;
    }
}

int main(void){
    int arr[10]={4,3,6,9,1,2,10,8,7,5};
    int len=sizeof(arr)/sizeof(arr[0]);
    BubbleSort(arr,len);
    PrintArray(arr,len);
    system("pause");
    return 0;
}

指针只是一个针,他需要指向一个类型

#include<iostream>
#include <string.h>
using namespace std;
class person{
    public:
        int m_age;
        string m_name;
        person(){}
        person(int age,string name):m_age(age),m_name(name){}
};  

int main(void){
    person * ptr=new person();
    //person * ptr; 就不行 没有指向任何东西
    ptr->m_age=18;
    cout<<ptr->m_age<<endl;


    //再如 ,直接 int *p; *p=10;就会报错
    int a=10;
    int * p=&a;
    cout<<*p<<endl;
    system("pause");
    return 0;
}

8 结构体
8.1 用户自定义的数据类型

struct 结构体名{
  结构体成员列表
};

//其实就是类型集合
struct Student{
  string name;
  int age;
  int score;
};

//创建,第1种方式  struct 在创建变量时可以省略
struct Student s1;
s1.name="Zhou";  s1.age=18;  s1.score=100;

//创建,第2种方式
struct Student s1={"Zhou",18,100};

//创建,第3种方式
//定义结构体时顺便定义变量
struct Student{
  string name;
  int age;
  int score;
}s3;
s3.name="Zhou";  s3.age=18;  s3.score=100;

8.2 结构体数组

Student StuArr[3]={
 {"Zhou",18,100},{"Wang",18,90},{"Tang",18,120}
};

8.3 结构体指针
利用操作符 —>来访问。

struct Student s= {"Zhou",18,100};
struct Student * p = &s;
cout<<s.name<<endl;
cout<<p->name<<endl;

Day 3

8.4 结构体嵌套结构体——子结构体

struct Student{
  string name;
  int age;
  int score;
}

struct Teacher{
  int id;
  string name;
  int age;
  struct Student stu;
}

8.5 结构体做函数参数
传递方式:值传递、地址传递

8.6 结构体中使用const
避免误操作

void PrintStudent1(const struct Student  * s)

案例:
image.png

#include<iostream>
#include <string.h>
#include<time.h>
using namespace std;
struct Student{
  string name;
  int score;
};

struct Teacher{
  string name;
  struct Student sArray[5];
};

void AllocateSpace(struct Teacher  tArray[], int length){
  srand((unsigned int)time(NULL));
  string nameSeed="ABCDE";
  for(int i=0;i<length;i++){
    tArray[i].name="Teacher_";
    tArray[i].name+=nameSeed[i];
    for(int j=0;j<5;j++){
      tArray[i].sArray[j].name="Student_";
      tArray[i].sArray[j].name+=nameSeed[j];
      tArray[i].sArray[j].score=rand()%41+60;;
    }
  }
}

void PrintInfo(struct Teacher  tArray[], int length){
  for(int i=0;i<length;i++){
    cout<<"Teacher Name:"<<tArray[i].name<<endl;
    for(int j=0;j<5;j++){
      cout<<"    Student Name:"<<tArray[i].sArray[j].name<<",Score:"
          <<tArray[i].sArray[j].score<<endl;
    }
  }
}

int main(void){
    Teacher tArray[3];
    int len=sizeof(tArray)/sizeof(tArray[0]);
    AllocateSpace(tArray,len);
    PrintInfo(tArray,len);

    system("pause");
    return 0;
}

案例:
image.png

#include<iostream>
#include <string.h>
#include<time.h>
using namespace std;
struct Hero{
  string name;
  int age;
  string sex;
};


void BubbleSort(struct Hero hArray[], int length){
  for(int i=0;i<length-1;i++){
    for(int j=0;j<length-i-1;j++){      
      if(hArray[j].age>hArray[j+1].age){
          Hero temp;
          temp=hArray[j];
          hArray[j]=hArray[j+1];
          hArray[j+1]=temp;
      }      
    }
  }
}

void PrintInfo(struct Hero hArray[], int length){
  for(int i=0;i<length;i++){
    cout<<hArray[i].name<<" "<<hArray[i].age<<"  "<<hArray[i].sex<<endl;
  }
}

int main(void){
    Hero hArray[5]={
      {"刘备",23,"男"},{"关羽",22,"男"},{"张飞",20,"男"},{"赵云",21,"男"},{"貂蝉",19,"女"}
    };
    int len=sizeof(hArray)/sizeof(hArray[0]);
    BubbleSort(hArray,len);
    PrintInfo(hArray,len);

    system("pause");
    return 0;
}

综合案例:通讯录管理系统
image.png