C++学习进度好慢,是不是我的打开方式不对,所以导师给我上数据了...
上周进行了研究生生涯的第一次组会,虽然很紧张也不知道讲什么,但是开始开会的那一下子,瞬间就不紧张了,听师兄师姐讲研究进展,嗯,太厉害了,对这个方向的爱好好像就那么被再次提升了,自己汇报学习进展,好像没什么东西,最后也提了几个问题,不过最不懂的应该是那堆雷达公式和地球物理函数模型,怎么出来的,后人在研究的时候都是对这些公式进行了改进,具体算法上的改进我是看不懂了,也就明白多考虑了一定的因素,好像通了一点吧。
碎碎念:
最后确定了一个大体方向和最近的工作,实际上自己编程现在自学进度真的很慢两个星期编出一个可以读取HDF5数据,然后把测量数据和参考标准数据匹配起来生成csv的代码,嗯,听起来挺简单,excel好像就可以做到(耐心多一些),但是四天了,我现在头绪一团乱,我尝试了不学完C++直接找别人代码学,但是吧,首先我把代码粘贴过来运行都失败了,看就更。。。我现在不知道该自学还是继续看别人的代码,我有些懵,时间紧迫,我继续扣别人的代码吧还是
笔记正文
- 导学,本章内容
- 函数——程序的功能模块
- 函数的定义与调用
- 内联函数
- constexpr函数
- 带默认参数值的函数
- 函数重载
- 系统函数
- 函数定义
- 语法形式
-
- 形参表不占空间,后面调用的时候才占用空间;相当于局部变量
语句序列最后一句是return语句,返回类型为类型标识符的类型,如果无类型,则viod,无类型的可以不写return
- 函数调用
- 调用前需要先声明
- 定义和调用可能不在一个程序中或者一个程序中定义在调用后
- 调用形式
- 调用前需要先声明
-
- 递归调用
- power为函数名,()中有参数,x和n为形参
- 数制转换
- 把二进制数转换为十进制数
- 可以利用上面求x的n次方
-
- 第三行声明函数原型
- 编写程序求π
-
- 用功能分解的方式,不同的函数实现不同的部分
- 设计一个函数计算arctan:double arctan(double x)
- 主调函数用arctan
- 精度条件:“直到级数...”
- 代码
整数相除1/5,结果取整,所以写的时候写1/5.0;
e/i>1e-15 因为限制条件是直到级数某项绝对值不大于10的-15次方为止,所以可以循环的条件就是大于10的-15次方,停止条件是小于等于10的-15次方;
- 例题3.4
-
- 判断回文数,就要使数倒过来,那么就想到了除以10取余,每次取数的最后一位
先翻转,除以10取余,最先取出来的数,在结果中为最高位
m第一次的时候为0+一个数,所以第一个取出来的数是最后一位,每一次取出一个当前最低位,留商数下一次用
- 例3-5
-
- 先看k,两种关于r的条件,使用if语句
- 多次用到了sin函数,我们在例题中自己写(库中其实有sin)
- 精度,如果不大于了则停止
- sin函数
-
- 主函数
- 函数调用例3-6
- 投骰子
由一个函数专门模拟投骰子,另一个专门玩游戏
- 随机数
-
- rand函数
- 函数原型:int rand(void)
- 所需头文件:<cstdlib>
- 功能和返回值:求出并返回一个伪随机数
- 每次调用它都会产生一个整数,看不出什么规律
- 但是你下一次再从头调用的时候和上一次产生的整数一致
- srand函数
- rand函数
-
-
-
-
- 为了使rand产生一个随机数序列而设置的起始点
- 每次运行前给一个不同的种子,将产生不同的随机数列
- 代码
-
-
-
-
-
- case 7,11共用语句
- 投骰子过程
-
-
- 函数的嵌套调用
- 用栈保存了当前现场和地址,所以能返回前一次暂停的调用点
-
- 例子
-
- 函数一调用两次函数二,函数一仅仅是加了和
- 将求平方和这个过程分解成了求平方和求和
- 函数的递归调用
- 函数自己调用自己,函数直接或间接的调用自身
- 例子
-
-
- 当你解释什么是阶乘时,你解释n的阶乘是n-1的阶乘,照此递归下去,越来越小,直到你能计算下去
-
-
- 递归终结条件为n==0
- 递归例题3-9
- 题目,解释什么是组合的时候,又递归。
-
- 代码,两个递归深入,再逐级回退
- 例3-10汉诺塔
-
- 解析,n-1个解决不了,可以解决n-2个,等等往下推,直到某个时刻有解了,就解决了
-
- 核心
- 如果是一个盘子就直接移动
- 函数的参数调用
- 形参不占用内存空间,只有调用函数的时候,才会给形参空间,这叫参数传递
- 单向传递,双向传递
- 在函数被调用时才分配形参的存储单元
- 实参可以是常量、变量或表达式
- 实参类型必须与形参相符——不一样,会隐含转换,不能转会报错
- 值传递是传递参数值,即单向传递
- 引用传递可以实现双向传递(有的参数可以将函数的计算结果带回主调函数)
- 常引用作参数可以保障实参数据的安全
- 引用类型(有困惑,不完全懂)
- 引用(&)是标识符的别名
- 定义一个引用时,必须同时对它进行初始化,使它指向一个已存在的对象
- 例如:
- int i,j;
int&ri=i;//定义int引用ri,并初始化为变量i的引用——这个变量有两个名字:i&ri - j=10
ri=j;//j的值赋给ri,就相当于i=j
- int i,j;
- 一旦一个引用被初始化后,就不能改为指向其他对象
- 引用可以作为形参,实现参数的双向传递
- 不存在空引用,引用必须连接到一块合法的内存
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。(指针可以在任何时候指向到另一个对象)
- 引用必须在创建时被初始化。(指针可以在任何时间被初始化)
- 引用作参数,也符合定义分配空间的时候直接初始化的原则
- 因为函数被调用的时候才给形参分配存储空间
- 只有行实结合的时候这个引用才被定义
- 这个时候用实参的这个变量去初始化形参的引用
- 交换是一个常见的操作
- 例3-11输入两个整数并交换(值传递)——单向传递
-
- swap调用函数,void表示函数无返回,若放在函数的括号里则表示函数五参数
- 主函数中输出的时候发现两个值并没有交换,这是为什么?前面swap函数交换两个变量的值并没有错
- 用实参5去初始化形参a,实参10去初始化形参b,这样a和b都得到了值,但是a,b与x,y的联系从此就切断了;
- 交换a,b的时候只是单纯的在交换a和b,根本看不到x,y,因为它是主函数的变量,到子函数中已经离开它的作用域了;
- 返回主函数中,a,b就消亡了,输出的时候就不会有变化
-
- 参数是单向传递的,只有一开始实参和形参有联系
- 例3-12输入两个整数交换后输出(引用传递)
-
- int a,int b表示a,b准备好了,准备作别名用。定义函数的时候并不给它分配空间,调用的时候才会,让它与实参相结合
- x是它,a也是它,在子函数swap中我们就实际上用a,b去操纵x,y两个量
- 含有可变参数的函数
- 写参数不确定的函数
- 一般在写函数时,就把形参表确定了
- 含有可变参数的函数的语法规定(可变长度的形参表)
- C++标准库中提供了两种主要的方法
- 如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型
- 如果参数的,我们可以编写可变参数的模板(第九章)
- initializer_list
- 是一种标准库类型,用于表示某种特定类型的值的数组,该类型定义在同名的头文件中
- C++标准库中提供了两种主要的方法
-
-
-
-
- 使用方法
-
-
-
-
-
-
-
- 使用举例
- 在编写代码输出程序产生的错误信息时,最好统一用一个函数实现该功能,使得对所有错误的处理能够整齐划一;然而错误信息的种类不同,调用错误信息输出函数时传递的参数也会各不相同
-
-
-
- 内联函数
- 声明使用关键字inline
- 编译器编译时用函数体里的语句替换函数表达式
- 编译时在调用处用函数体进行替换,节省了参数传递,控制转移等开销
- 要求
- 内联函数体内不能有循环语句和switch语句
- 其定义必须出现在内联函数第一次被调用之前
- 对内联函数不能进行异常接口声明
- 应用
-
- inline建议编译器在我调用函数的时候直接拿内联函数来替换
- constexpr函数
- 语法规定
- constexpr修饰的函数,在其所有参数都是constexpr时一定返回constexpr
- 举例
- constexpr int get_size(){return 20;}//这个函数返回什么值,在编译阶段编译器就可以解决,即编译期间可计算的函数
- 可以去初始化一个常量表达式
- constexpr int foo=get size();//foo是一个常量表达式
- 语法规定
- 带默认参数值的函数
- 没给实参就用形参的默认值
- 可以预先设置默认的参数值,调用时给出实参,则采用实参值,否则用预先设置的
-
- 默认参数值的说明次序
- 有默认参数的形参必须列在形参表的最右,即默认参数值的右边不能有无默认参数值的参数;
- 调用时实参与形参的结合次序是从左向右
- 默认参数值的说明次序
-
- 默认参数值与函数的调用位置
- 如果一个函数有原型声明,且原型声明在定义之前,则默认参数值应在函数原型声明中给出
- 如果只有函数的定义,或函数定义在前,则默认参数值可以在函数定义中给出。
- 默认参数值与函数的调用位置
-
-
- 写一个函数,求长方体体积
-
-
-
- 代码
-
-
-
- 头文件为#include <iomanip>
- 其中io代表输入输出,manip是manipulator(操纵器)的缩写
- iomanip的作用:
- 主要是对cin,cout之类的一些操纵运算子,比如setfill,setw,setbase,setprecision等等。它是I/O流控制头文件,就像C里面的格式化输出一样。
- setw(int n)
- 是c++中在输出操作中使用的字段宽度设置,设置输出的域宽,n表示字段宽度。只对紧接着的输出有效,紧接着的输出结束后又变回默认的域宽。
- 当后面紧跟着的输出字段长度小于n的时候,在该字段前面用空格补齐;当输出字段长度大于n时,全部整体输出。
- t:水平制表(跳到下一个Tab位置)
- r:回车,将当前位置移到本行开头
- n:换行
- 头文件为#include <iomanip>
-
- 函数重载
- C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。
- 注意事项
- 重载函数的形参必须不同:形参类型不同或形参个数不同
- 编译器不以形参名来区分
- 不以返回值来区分(函数的类型不同,一个int,一个void,返回值不一样,void为空
-
-
- 不要将不同功能的函数声明为重载函数,以免出现调用结果的误解、混淆。
-
-
- 例子
-
-
- 参数类型不同
-
- 系统函数
- sin,cos什么的自己调用吧
- 库中提供了几百个函数可供使用
- 使用数学函数时,要使用cmath
- 例题
- 栈
- 函数形参与局部变量很相似,都不能像全局变量那样用固定地址加以定位,而需要存储在一种特殊的结构中,这就是栈
- 一般意义上的栈,是一种数据结构,它是一种能够容纳很多数据的结构,但数据进入和退出这个容器的顺序,要满足一定的要求
- 数据只能从栈的一端存入(压入栈),只能从栈的同一端输出(弹出栈),这一端叫做栈顶,另一端叫做栈底
- 栈中数据的添加和删除操作具有“先进后出”的特性
- 运行栈
- 嵌套函数中越早开始的调用,返回的越晚
函数调用中的形参和局部变量,当调用开始时生效,当函数返回后即实效 - 故嵌套函数中,形参和局部变量生效的时间越早,实效的时间越晚
- 所以函数的形参和局部变量可以用栈来存储——运行栈
- 实际上是一段区域的内存空间,与存储全局变量的空间无异,只是寻址的方式不同。
- 运行栈中的数据分为一个一个栈帧,每个栈帧对应一次函数调用,栈帧中包括这次函数调用中的形参值、一些控制信息、局部变量和一些临时数据(中间值、返回值)
- 一个函数在执行过程中能够直接随机访问它所对应的栈帧中的数据,即处在运行栈最顶端的栈帧的数据
- 执行中的函数的栈帧,总处在运行栈的最顶端
- 当一个函数调用其他函数时,要为它所调用的函数设置实参,具体方式是在调用前把实参值压入栈中,运行栈中的这一部分空间是主调函数与被调函数都可以直接访问的,参数的形实结合就是通过访问这一部分公共空间完成的
- 虽然一个函数在被调用时的形参和局部变量地址是不确定的,但是它们的地址相对于栈顶的地址却是确定的,这样就可以通过栈顶的地址,定位形参和局部变量
- 嵌套函数中越早开始的调用,返回的越晚