[学习笔记]c++基础--day02

这篇博客详细介绍了C++的基础知识,包括函数的定义、调用、声明和分文件编写,深入讲解了指针的定义、内存空间、空指针、野指针以及const修饰指针的概念,同时探讨了结构体的定义、数组、指针访问成员以及结构体在函数中的应用。文章通过实例帮助读者理解这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、函数

1.1函数的定义:返回值类型、函数名、参数表列、函数体语句、return表达式

1.2函数的语法:

1.3 函数的调用:函数名 (参数)

1.4 值传递

1.5常见的函数样式

1.6函数的声明

1.7函数的分文件编写

2、指针

2.1指针变量定义语法:数据类型 *变量名;

2.2 指针的所占内存空间

2.3空指针

2.4 野指针:指针变量指向非法访问等的内存空间

2.5 const修饰指针

2.6 指针和数组:利用指针访问数组中的元素

2.7 指针和函数:利用指针作函数参数,可以修改实参的值

3、结构体

3.1 结构体的定义和使用

3.2 结构体数组

3.3 结构体指针:通过指针访问结构体成员

3.4 结构体嵌套结构体

3.5 结构体作函数参数:将结构体作为参数向函数中传递

3.6 结构体中const使用场景

3.7 例子

3.7.1 例1:

3.7.2 例2


1、函数

将一段常用的代码封装起来,减少重复代码

1.1函数的定义:返回值类型、函数名、参数表列、函数体语句、return表达式

1.2函数的语法:

返回值类型 函数名(参数表列){

函数体语句

    return表达式

}

例:

//两个数相加的函数
//返回值类型应该是一个数,
//函数名可自己命名,例如add
//参数应该是,两个数字,num1,num2
//函数体语句为求两数相加:int sum = num1+num2;
//return返回值是一个数
int add(int num1, int num2) {
    int sum = num1 + num2;
    return sum;
}

1.3 函数的调用:函数名 (参数)

int a = 10;
int b = 20;

//调用上述的add函数
//函数名 (参数)
//当调用函数时,实参的值会传递给形参
//a和b称为实参(实际参数)
add(a, b);

//函数add返回的是一个值,故可以直接打印结果
cout<< add(a, b)<<endl;

1.4 值传递

函数调用时实参将数值传入给形参

值传递时,形参发生任何改变,并不会影响实参

例:2个数字交换,内存的大致情况(创建变量时,会分配一个内存):值传递时,只是num1和num2的数据值交换,a和b不变。

数据

a

10

b

20

num1

num2

temp

10

1.5常见的函数样式

无参无返、有参无返、无参有返、有参有返

1.6函数的声明

告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

函数的声明可以多次,但是函数的定义只能有一次。

函数声明之后,定义该函数可以在main()函数之后。

补充:变量

定义 VS 声明

变量定义要给变量分配内存空间,而声明没有;定义可以初始化,声明不能。

声明: extern <类型名> <变量名>;

        头文件中使用extern语句对一个文件中的全局函数进行声明;

        函数使用一个全局变量但是还未见到其定义时使用extern语句对其进行声明。

1.7函数的分文件编写

让代码结构更加清晰

  • 创建后缀名为.h的头文件
  • 创建后缀名为.cpp的源文件
  • 在头文件中写函数的声明
  • 在源文件中写函数的定义

2、指针

通过指针间接访问内存

内存编号是从0开始记录的,一般用十六进制数字表示;可以利用指针变量保存地址

2.1指针变量定义语法:数据类型 *变量名;

int a = 10;
//定义指针
int *p;

//让指针记录变量a的地址
p = &a;
cout << "a的地址为:" << p << endl;

//使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加 * 代表解引用,找到指针指向的内存中的数据
*p = 1000;
//此时原先a的值已变为1000,*p即对应内存的数据内容

2.2 指针的所占内存空间

指针也是种数据类型,占4个字节空间(32位操作系统),64位操作系统下占8字节空间。

cout << "指针所占内存空间为:" << sizeof(int *) << endl;

2.3空指针

用于初始化指针变量;空指针指向的内存是不可以访问的

空指针:指针变量指向内存中编号为0的空间,而0-255之间的内存访问编号是系统占用的,因此不可以访问

例:

 

2.4 野指针:指针变量指向非法访问等的内存空间

例如:直接定义一个指针变量,且直接指向一个非法内存空间;

int *p = (int *)0x1100;运行时会发生异常,没有访问权限。

2.5 const修饰指针

const修饰指针  ---常量指针:const int *p = &a,指针的指向可以修改,指针指向的值不可以改

const修饰常量  ---指针常量:int * const p = &a;指针的指向不可以改,指针指向的值可以改

const既修饰指针,又修饰常量:const int * const p = &a;指针的指向和指针指向的值不可以改

2.6 指针和数组:利用指针访问数组中的元素

//指针访问数组元素
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int *p = arr;//arr就是数组首地址
    for (int i = 0; i < 10; i++) {
        cout << "指针访问数组第"<< i << "个元素:" << *p << endl;
        p++;
}

2.7 指针和函数:利用指针作函数参数,可以修改实参的值

地址传递

void swap(int *num1, int *num2) {
    int temp =*num1;
    *num1 = *num2;
    *num2 = temp;
}

int main() {
    int a = 10;
    int b = 20;
    swap(&a, &b);
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;

    system("pause");
    return 0;
}

内存数据

a(假设内存地址为0x0011)

10 -> 20

b(假设内存地址为0x0022)

20 -> 10

*num1

0x0011

*num2

0x0022

temp

10

若想修改实参,使用地址传递;若不想修改实参,就使用值传递。

例:封装一个函数,利用冒泡排序,实现对整型数组的升序排序

//冒泡升序排序 参数1 数组的首地址 参数2 数组的长度
void bubbleSort(int *arr,int len) {
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            //如果j>j+1的值,则交换数据
            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[9] = { 4,2,8,0,5,7,1,3,9 };
    bubbleSort(arr,9);//需要传入的参数是数组和数组的长度
    printArray(arr,9);//打印排序后的数组

    system("pause");
    return 0;
}

3、结构体

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型

3.1 结构体的定义和使用

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

通过结构体创建变量的方式有三种:

struct 结构体名 变量名

struct 结构体名 变量名 = {成员1值,成员2值...}

定义结构体时顺便创建变量

例:创建学生数据类型:学生姓名,年龄,分数

struct student {
    string name;//姓名
    int age;//年龄
    int score;//分数
}s3;//定义结构体时顺便创建变量

int main()
{ //通过学生类型创建具体学生
    //struct 结构体名 变量名;struct 可省略
    //通过 . 访问成员
    struct student s1;
    s1.name = "李四";
    s1.age = 18;
    s1.score = 75;
    cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 分数:" << s1.score << endl;
    //struct 结构体名 变量名 ={成员1值,成员2值...}
    struct student s2 = { "张三",20,80 };
    cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 分数:" << s2.score << endl;

    s3.name = "王五";
    s3.age = 22;
    s3.score = 60;
    cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 分数:" << s3.score << endl;

    system("pause");
    return 0;
}

3.2 结构体数组

将自定义的结构体放入到数组中方便维护

struct 结构体名 数组名{元素个数} = {{},{},{}...}

struct student {
    string name;//姓名
    int age;//年龄
    int score;//分数
};

int main()
{ //结构体数组
    //创建结构体数组
    struct student StuArray[3] = { {"张三",20,80},{"李四",18,75} };
    //给结构体数组中的元素赋值
    StuArray[2].name = "王五";
    StuArray[2].age = 22;
    StuArray[2].score = 65;

    //遍历结构体数组
    cout << "姓名  " << "年龄 " << "分数  " << endl;
    for (int i=0; i < 3; i++) {
        cout << StuArray[i].name<<"   " << StuArray[i].age << "   " << StuArray[i].score << endl;
    }

    system("pause");
    return 0;
}

3.3 结构体指针:通过指针访问结构体成员

利用操作符 -> 可以通过结构体指针访问结构体属性

//创建学生结构体变量
student s = {"张三",18,99};

//通过指针指向结构体变量
student *p = &s;

//通过指针访问结构体变量中的数据
string st = p->name;
cout << st << endl;//输出结果是张三

3.4 结构体嵌套结构体

结构体中的成员可以是另一个结构体

例:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体

//定义学生结构体
struct student {
    string name;//姓名
    int age;//年龄
    int score;//分数
};

//定义老师结构体
struct teacher {
    int id;
    string name;
    int age;
    struct student stu;//老师辅导的学生
};

int main()
{ //结构体嵌套一个结构体
    teacher t;
    t.id = 012;
    t.name = "卢老师";
    t.age = 30;
    t.stu.name = "阿霞";
    t.stu.age = 20;
    t.stu.score = 95;

    cout << "老师姓名:" << t.name << "老师编号:" << t.id << "老师年龄:" << t.age << endl;
    cout << "老师辅导的学生姓名:" << t.stu.name << "学生年龄:" << t.stu.age << "学生成绩:" << t.stu.score << endl;

    system("pause");
    return 0;
}

3.5 结构体作函数参数:将结构体作为参数向函数中传递

值传递

printSt(st);//打印学生信息的函数,需传入学生结构体信息

void printSt(student st) {
    cout << st.name << st.age << st.score << endl;
}

地址传递

printSt2(&st);

void printSt2(student *st) {
    cout << st -> name << st->age << st->score << endl;
}

3.6 结构体中const使用场景

用const来防止误操作

将结构体作为参数向函数中进行地址传递时,实参值是可以改变的,若结构体参数前加上const即void printSt2(const student *st),此时,里面的数据就不可以修改了(原先值不改变)。

3.7 例子

3.7.1例1:

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

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

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

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

我的程序:

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

//例子1
//两个结构体,老师:姓名和存放5个学生的数组;学生:姓名和考试分数
//创建数组存放三名老师
//函数,给每个老师及所带的学生赋值
//打印老师数据以及所带的学生数据
//学生结构体
struct student {
    string sn;//学生姓名
    int score;//考试分数
};
struct teacher {
    string tn;//老师姓名
    student stu[5];
};
void data(teacher t[],int len) {
    //老师名字数组
    string tname[3] = {"老师1","老师2" ,"老师3" };
    string sname[3][5] = { "明", "红", "方", "何", "郑","丽", "简", "芬", "si", "me","橙", "佳", "穗", "熊", "ky" };
    int score[3][5] = { { 80,81,86,85,82 } , { 95,93,87,98,100 } ,{ 100,89,92,85,94 } };
    //给老师赋值
    for (int i = 0; i < 3; i++) {
        t[i].tn = tname[i];
        cout << t[i].tn << "所带的学生为:"<<endl;
        //给学生赋值
        for (int j = 0; j < 5; j++) {
            t[i].stu[j].sn = sname[i][j];
            t[i].stu[j].score = score[i][j];
            //打印信息
            cout << t[i].stu[j].sn;
            cout <<"("<<t[i].stu[j].score << "分) ";
        }
        cout << endl;
    }
}

int main()
{
    teacher t[3];
    data(t,3);

    system("pause");
    return 0;
}

打印结果:

注:我是直接用一个数组存储老师姓名,学生姓名和学生成绩,直接访问。

3.7.2 例2

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

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

//例2,花费19分钟
//一个英雄结构体
//结构体数组,存放5名英雄
//对年龄进行冒泡升序排序
//打印排序后的结果
#include <iostream>
#include<string>
using namespace std;

struct hero {
    string name;//姓名
    int age;//年龄
    string sex;//性别
};

//冒泡排序
void bubbleSort(hero h[],int len) {
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 5 - i - 1; j++) {
            if (h[j].age > h[j+1].age) {
                hero htemp = h[j];
                h[j] = h[j+1];
                h[j + 1] = htemp;
            }
        }
    }
}

//打印
void print(hero h[], int len) {
    for (int i = 0; i < 5; i++) {
        cout << "  " << h[i].name << "     " << h[i].age << "     " << h[i].sex << endl;
    }
}

int main() {
    hero h[5] = { {"刘备",23,"男"},
    {"关羽",22,"男"}, {"张飞",20,"男"},
    {"赵云",21,"男"}, {"貂蝉",19,"女"}};

    cout << "  姓名    年龄    性别" << endl;

    bubbleSort(h, 5);
    print(h, 5);

    system("pause");
    return 0;
}

写在最后:最后一道题我居然花了19分钟!!还是敲得不够多吧。基础语法和原理一定要弄懂滴,接着埋头练习算法吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值