C++ 【第一篇】基础入门(二)

指针与结构体

一 指针

指针也是一种数据类型

int main() {

    //1、指针的定义
    int a = 10; //定义整型变量a
    
    //指针定义语法: 数据类型 * 变量名 ;
    int * p;

    //指针变量赋值
    p = &a; //指针指向变量a的地址
    cout << &a << endl; //打印数据a的地址
    cout << p << endl;  //打印指针变量p

    //2、指针的使用
    //通过*操作指针变量指向的内存
    cout << "*p = " << *p << endl;

    system("pause");

    return 0;
}
1指针定义
//总结:所有指针类型在32位操作系统下是4个字节
int main() {

    int a = 10;

    int * p;
    p = &a; //指针指向数据a的地址

    cout << *p << endl; //* 解引用
    cout << sizeof(p) << endl;
    cout << sizeof(char *) << endl;
    cout << sizeof(float *) << endl;
    cout << sizeof(double *) << endl;

    system("pause");

    return 0;
}
2指针占用空间
//总结:空指针和野指针都不是我们申请的空间,因此不要访问。

//空指针
int main() {

    //指针变量p指向内存地址编号为0的空间
    int * p = NULL;

    //访问空指针报错 
    //内存编号0 ~255为系统占用内存,不允许用户访问
    cout << *p << endl;

    system("pause");

    return 0;
}
//野指针
int main() {

    //指针变量p指向内存地址编号为0x1100的空间
    int * p = (int *)0x1100;

    //访问野指针报错 
    cout << *p << endl;

    system("pause");

    return 0;
}
3空指针与野指针
const修饰指针有三种情况

1. const修饰指针   --- 常量指针
2. const修饰常量   --- 指针常量
3. const即修饰指针,又修饰常量


int main() {

    int a = 10;
    int b = 10;

    //const修饰的是指针,指针指向可以改,指针指向的值不可以更改
    const int * p1 = &a; 
    p1 = &b; //正确
    //*p1 = 100;  报错
    

    //const修饰的是常量,指针指向不可以改,指针指向的值可以更改
    int * const p2 = &a;
    //p2 = &b; //错误
    *p2 = 100; //正确

    //const既修饰指针又修饰常量
    const int * const p3 = &a;
    //p3 = &b; //错误
    //*p3 = 100; //错误

    system("pause");

    return 0;
}
4const修饰指针
int main() {

    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

    int * p = arr;  //指向数组的指针

    cout << "第一个元素: " << arr[0] << endl;
    cout << "指针访问第一个元素: " << *p << endl;

    for (int i = 0; i < 10; i++)
    {
        //利用指针遍历数组
        cout << *p << endl;
        p++;
    }

    system("pause");

    return 0;
}
5指针与数组
//值传递
void swap1(int a ,int b)
{
    int temp = a;
    a = b; 
    b = temp;
}
//地址传递
void swap2(int * p1, int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

int main() {

    int a = 10;
    int b = 20;
    swap1(a, b); // 值传递不会改变实参

    swap2(&a, &b); //地址传递会改变实参

    cout << "a = " << a << endl;

    cout << "b = " << b << endl;

    system("pause");

    return 0;
}
6指针与函数
**案例描述:**封装一个函数,利用冒泡排序,实现对整型数组的升序排序

例如数组:int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
//冒泡排序函数
void bubbleSort(int * arr, int len)  //int * arr 也可以写为int arr[]
{
    for (int i = 0; i < len - 1; i++)
    {
        for (int j = 0; j < len - 1 - i; 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() {

    int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
    int len = sizeof(arr) / sizeof(int);

    bubbleSort(arr, len);

    printArray(arr, len);

    system("pause");

    return 0;
}
7指针,数组,函数
函数指针:一个指针变量,存放的是函数的地址
定义形式:
 类型 (*指针变量名)(参数列表);

如:
 int (*p)(int x,int y);
    p是一个指针,它指向一个函数,该函数有2个整形参数,返回类型为int。p首先和*结合,表明p是一个指针。然后再与()结合,表明它指向的是一个函数。指向函数的指针也称为函数指针。

include <stdio.h>
#include <stdlib.h>
 
void printfWelcome()
{
      printf("hello world!\n");
}
 
 
int add(int a,int b)
{ 
    return a + b;
}
 
int main()
{   
    //1.定义函数指针
    void (*p2)();//1.如何表示指针:*  2.如何知道是函数:()  3.函数指针是专用的,
               //格式要求很强(参数类型,个数,返回值都要一样)
               
    //2.给函数指针赋值
    p2 =  printfWelcome;//函数名就是地址,就像数组一样,数组名就是地址
    
    //3.如何通过函数指针调用函数
           //法一
    p2();//直接通过指针名字 + ()
           //法二
    (*p2)();//取内容  (*指针名字())
    
    
    int (*padd)(int a,int b);
    padd = add;
    //int ret = padd(1,2);//法一
    int ret = (*padd)(1,2);//法二
    //(*padd)(1,2);//法三
    printf("ret = %d\n",ret);
    
    system("pause");
    return 0;
}
函数指针

 

 

二引用

int main() {

    int a = 10;
    int &b = a;

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    b = 100;

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    system("pause");

    return 0;
}
1基本使用
int main() {

    int a = 10;
    int b = 20;
    //int &c; //错误,引用必须初始化
    int &c = a; //一旦初始化后,就不可以更改
    c = b; //这是赋值操作,不是更改引用

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;

    system("pause");

    return 0;
}
2不可更改
//1. 值传递
void mySwap01(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

//2. 地址传递
void mySwap02(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

//3. 引用传递
void mySwap03(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {

    int a = 10;
    int b = 20;

    mySwap01(a, b);
    cout << "a:" << a << " b:" << b << endl;

    mySwap02(&a, &b);
    cout << "a:" << a << " b:" << b << endl;

    mySwap03(a, b);
    cout << "a:" << a << " b:" << b << endl;

    system("pause");

    return 0;
}
3引用作函数参数
//返回局部变量引用
int& test01() {
    int a = 10; //局部变量
    return a;
}

//返回静态变量引用
int& test02() {
    static int a = 20;
    return a;
}

int main() {

    //不能返回局部变量的引用
    int& ref = test01();
    cout << "ref = " << ref << endl;
    cout << "ref = " << ref << endl;

    //如果函数做左值,那么必须返回引用
    int& ref2 = test02();
    cout << "ref2 = " << ref2 << endl;
    cout << "ref2 = " << ref2 << endl;

    test02() = 1000;

    cout << "ref2 = " << ref2 << endl;
    cout << "ref2 = " << ref2 << endl;

    system("pause");

    return 0;
}
4引用作为返回值
//发现是引用,转换为 int* const ref = &a;
void func(int& ref){
    ref = 100; // ref是引用,转换为*ref = 100
}
int main(){
    int a = 10;
    
    //自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改
    int& ref = a; 
    ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;
    
    cout << "a:" << a << endl;
    cout << "ref:" << ref << endl;
    
    func(a);
    return 0;
}
5引用本质(指针)
//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {
    //v += 10;
    cout << v << endl;
}

int main() {

    //int& ref = 10;  引用本身需要一个合法的内存空间,因此这行错误
    //加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
    const int& ref = 10;

    //ref = 100;  //加入const后不可以修改变量
    cout << ref << endl;

    //函数中利用常量引用防止误操作修改实参
    int a = 10;
    showValue(a);

    system("pause");

    return 0;
}
6常量引用

 

三 结构体

//结构体定义
struct student
{
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
}stu3; //结构体变量创建方式3 


int main() {

    //结构体变量创建方式1
    struct student stu1; //struct 关键字可以省略

    stu1.name = "张三";
    stu1.age = 18;
    stu1.score = 100;
    
    cout << "姓名:" << stu1.name << " 年龄:" << stu1.age  << " 分数:" << stu1.score << endl;

    //结构体变量创建方式2
    struct student stu2 = { "李四",19,60 };

    cout << "姓名:" << stu2.name << " 年龄:" << stu2.age  << " 分数:" << stu2.score << endl;


    stu3.name = "王五";
    stu3.age = 18;
    stu3.score = 80;
    

    cout << "姓名:" << stu3.name << " 年龄:" << stu3.age  << " 分数:" << stu3.score << endl;

    system("pause");

    return 0;
}
1结构体定义
//结构体定义
struct student
{
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
}

int main() {
    
    //结构体数组
    struct student arr[3]=
    {
        {"张三",18,80 },
        {"李四",19,60 },
        {"王五",20,70 }
    };

    for (int i = 0; i < 3; i++)
    {
        cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 分数:" << arr[i].score << endl;
    }

    system("pause");

    return 0;
}
2结构体数组
//结构体定义
struct student
{
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};


int main() {
    
    struct student stu = { "张三",18,100, };
    
    struct student * p = &stu;
    
    p->score = 80; //指针通过 -> 操作符可以访问成员

    cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
    
    system("pause");

    return 0;
}
3结构体指针
//学生结构体定义
struct student
{
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};

//教师结构体定义
struct teacher
{
    //成员列表
    int id; //职工编号
    string name;  //教师姓名
    int age;   //教师年龄
    struct student stu; //子结构体 学生
};


int main() {

    struct teacher t1;
    t1.id = 10000;
    t1.name = "老王";
    t1.age = 40;

    t1.stu.name = "张三";
    t1.stu.age = 18;
    t1.stu.score = 100;

    cout << "教师 职工编号: " << t1.id << " 姓名: " << t1.name << " 年龄: " << t1.age << endl;
    
    cout << "辅导学员 姓名: " << t1.stu.name << " 年龄:" << t1.stu.age << " 考试分数: " << t1.stu.score << endl;

    system("pause");

    return 0;
}
4结构体嵌套结构体
//学生结构体定义
struct student
{
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};

//值传递
void printStudent(student stu )
{
    stu.age = 28;
    cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;
}

//地址传递
void printStudent2(student *stu)
{
    stu->age = 28;
    cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age  << " 分数:" << stu->score << endl;
}

int main() {

    student stu = { "张三",18,100};
    //值传递
    printStudent(stu);
    cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl;

    cout << endl;

    //地址传递
    printStudent2(&stu);
    cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;

    system("pause");

    return 0;
}
5结构体做函数传递
/学生结构体定义
struct student
{
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};

//const使用场景
void printStudent(const student *stu) //加const防止函数体中的误操作
{
    //stu->age = 100; //操作失败,因为加了const修饰
    cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;

}

int main() {

    student stu = { "张三",18,100 };

    printStudent(&stu);

    system("pause");

    return 0;
}
6结构体const使用

案例一:

案例描述:

学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下

设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员

学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值

最终打印出老师数据以及老师所带的学生数据。

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

void allocateSpace(Teacher tArray[] , int len)
{
    string tName = "教师";
    string sName = "学生";
    string nameSeed = "ABCDE";
    for (int i = 0; i < len; i++)
    {
        tArray[i].name = tName + nameSeed[i];
        
        for (int j = 0; j < 5; j++)
        {
            tArray[i].sArray[j].name = sName + nameSeed[j];
            tArray[i].sArray[j].score = rand() % 61 + 40;
        }
    }
}

void printTeachers(Teacher tArray[], int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << tArray[i].name << endl;
        for (int j = 0; j < 5; j++)
        {
            cout << "\t姓名:" << tArray[i].sArray[j].name << " 分数:" << tArray[i].sArray[j].score << endl;
        }
    }
}

int main() {

    srand((unsigned int)time(NULL)); //随机数种子 头文件 #include <ctime>

    Teacher tArray[3]; //老师数组

    int len = sizeof(tArray) / sizeof(Teacher);

    allocateSpace(tArray, len); //创建数据

    printTeachers(tArray, len); //打印数据
    
    system("pause");

    return 0;
}
案例一

 

案例二:

案例描述:

设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。

通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果

五名英雄信息如下:

  {"刘备",23,"男"},
  {"关羽",22,"男"},
  {"张飞",20,"男"},
  {"赵云",21,"男"},
  {"貂蝉",19,"女"},

//英雄结构体
struct hero
{
    string name;
    int age;
    string sex;
};
//冒泡排序
void bubbleSort(hero arr[] , int len)
{
    for (int i = 0; i < len - 1; i++)
    {
        for (int j = 0; j < len - 1 - i; j++)
        {
            if (arr[j].age > arr[j + 1].age)
            {
                hero temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
//打印数组
void printHeros(hero arr[], int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << "姓名: " << arr[i].name << " 性别: " << arr[i].sex << " 年龄: " << arr[i].age << endl;
    }
}

int main() {

    struct hero arr[5] =
    {
        {"刘备",23,""},
        {"关羽",22,""},
        {"张飞",20,""},
        {"赵云",21,""},
        {"貂蝉",19,""},
    };

    int len = sizeof(arr) / sizeof(hero); //获取数组元素个数

    bubbleSort(arr, len); //排序

    printHeros(arr, len); //打印

    system("pause");

    return 0;
}
案例二

 

posted @ 2022-07-17 14:51  风hua  阅读(48)  评论(0)    收藏  举报