Essential-CPP学习笔记-第二章

Essential C++ 第二章-面向过程的编程风格

第一章的程序全部卸载了main()函数里面,在程序规模比较大的情况下,这是不合实际的,因此需要将”共通“的功能抽取出来,携程独立的函数,以下为优点:

1. 使用一连串函数进行调用操作,取代重复的程序代码,增强程序可读性;

2. 可以在不同程序中调用同一个函数,提高复用性;

3.便于团队合作

Tips: 如果编写的程序和预期运行不一致,可以使用以下方式debug:

1. 使用断点,一步一步检查

2. 使用ofstream语句,将每一步执行结果打印到一个文件内,查看文件发现哪里有问题。


2.1 如何撰写函数: 定义函数有以下步骤(功能函数和main主程序在同一个cpp文件内):

  • 1.指定函数的返回值类型(也就是经过函数计算之后,输出的结果): 如int...若无返回值,需要用void占位;
  • 2.函数的名称,一般需要直观表现出函数功能,如: math_calcu();
  • 3.函数的输入参数列表(输入参数),实际上就是调用函数时,输入的数值 如: math_calcu(int x,int y,string x)
  • 4.函数主体,就是函数功能实现的主体 ,使用{}括起来。
  • 注意! 若函数的返回值设定的不是void,那么在函数必须以return结束,否则会出错
  •             若函数设定的返回值是void,那么函数需要以return; 结尾
// P2.1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

//简单的函数编写:fibo数列(斐波那契数列)

#include <iostream>
using namespace std; //指定运行空间

bool fibon_elem_2(int, int &); //此处为函数声明 (forward declaration)
                              //需包含:函数返回值类型bool,函数名称fibon_elem
                              //输入参数类型 (int, int&)-->整型和指针


int main()
{
    int pos;
    cout << "Please input the position: \n";
    cin >> pos;

    int elem;

    if (fibon_elem_2(pos, elem)) {
        cout << "The element in the position is: " << elem;
    }
    else{

        cout << "The position info was wrong: \n" ;
    }
    return 0;
}


bool fibon_elem_2(int pos, int &elem)
{
    if (pos <= 0 || pos > 1024) {
        elem = 0; return false;
    }
    if (pos == 1 || pos == 2) {
        elem = 1; return true;
    }

    elem = 1;
    int n_2 = 1, n_1 = 1;

    for (int ix = 3; ix <= pos; ++ix) {
        elem = n_2 + n_1;
        n_2 = n_1;
        n_1 = elem;
    }
    return true;

}

 

2.2 调用(invoking)一个函数,以及传址与传值:

  • 以冒泡排序为例,需要使用子函数,进行排序,并将排序后的数值保存在vector里面;
  • 要分清:int x=1024 (定义一个对象); int *p=&x (指针指向一个对象); int &rval=ival (referece 化身),代表一个int对象,的关系。
  • 使用传值前提:如果在调用函数进行运算并且要对全局变量进行修改时,使用传址&,否则使用函数的返回值即可;
  • 区分以下几个的意义:传址传值的区别,以以下程序为例:
void swap_1(int val1,int val2){ //寻值而非寻址
      int temp = 0;              //导致:这个函数仅对函数内部数据进行了更改
      temp = val2;
      val2 = val1;
      val1 = t3mp;
}


void swap_2(int &val1,int &val2){ //寻址
      int temp = 0;               //这个函数计算完成之后!!
                                 //会对传入函数的地址内信息进行修改!!
      temp = val2;
      val2 = val1;
      val1 = t3mp;
}

void bubble_sort(vector<int> &vec) {    //&表示直接操作这个地址内存放的数值

    for (int ix = 0; ix < vec.size(); ++ix) {
        for (int jx = ix + 1; jx < vec.size(); ++jx) {  
            if (vec[ix] > vec[jx]) {
                swap(vec[ix], vec[jx]);
            }
        }
    }
}

int main()
{
    int ia[8] = { 8,34,3,13,1,21,5,2 }; //新建一个有8个数值的数组
                                        //并通过下边的方式对vector进行赋值
    vector<int> vec(ia,ia+8); //

    cout << "The vector before sorting is :\n" << endl;
    display_vector(vec);

    bubble_sort(vec);

    cout << "The vector after sorting is :\n" << endl;

    display_vector(vec);
}

 

2.3 生存空间(scope)及生存范围(extent)

  1. 生存空间scope(全局及局部变量):

                                生存空间分为局部生存空间(局部变量)(local scope)(仅在函数体有效)(需要初始化赋值)

                        与全局生存空间(全局变量)(file scope)(在程序内有效-在函数体外赋值)(未赋值时,自动赋值为0)

     2. 动态内存管理(动态变量):不管时local scope还是file scope,系统都会自动进行内存分配; 但是有一种存储形式不行;

                                  称为动态范围:dynamic extent--有时也被成为堆内存,此种类型内存必须由程序员管理。

         管理方法为: 使用new表达式进行配置,使用delete表达式完成释放;

         注意!!创建好动态范围的变量使用完毕后,必须要及时将其delete,否则会出现memory leak (内存泄漏)

// dynamic extent 动态范围
//语法为: 变量名=new Type (initial_value);
//例如:
        pi= new int (1024);  //创建一个初始值为1024的名为pi的变量

//释放: 
        delete pi;

    3. 局部静态对象(local static objects)--实际上就是在系统中创建容器,若后边用到已有内容,就不用从头开始生成对象了

  1. Tips1: 为了节省函数间通信问题而将所有对象都定义在file scope里面,过于冒险,会打破函数之间的独立性,使程序难以理解。

                       

 

4. Inline 函数(将大函数拆分成小函数,必要时再组合在一起,提高执行效率): 

  • 目的如下边的例子,我们把fibo原先的函数拆分成了3个不同的子函数,在生成fibon数列时,仍会依次调用这三个函数;
  • ->若执行效能不理想,需要将三个函数重新组合成同一个函数运行时,需将这三个函数声明前加上inline即可
  • ->最终结果: 虽然三个子函数还是独立的,但是可以组合成一个大的函数体运行(与之前大函数体类似),同时提高复用性
  • 重要:一般情况下,适合声明为inline的函数,一般和fibon_elem(),is_size_ok() 一样,体积小但常被调用。

 

以下为局部静态对象和inline函数例子:尤其要注意:

// C2.5Inline.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//局部静态对象及inline函数

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


 bool is_size_ok(int size) {

     if (size <= 0 || size > 1024) {
         cout << "Oops the size is not supported: \n";
         return false;
     }
     else {
         return true;
     }
 }

 const vector<int>* fibon_seq(int size) {  //此处实际上是一个局部静态对象(常量),返回值是一个地址

     const int max_size = 1024;
     static vector<int> elems;            //在函数体内创建一个静态对象vector(非易失对象),之后进行计算
                                          //局部静态对象与非静态区别:静态对象在函数体结束后不会被清除

     if (!is_size_ok(size)) {
         return 0;
     }
     for (int ix = elems.size(); ix < size; ++ix) {
         if (ix == 0 || ix == 1) {
             elems.push_back(1);
         }
         else {
             elems.push_back(elems[ix - 1] + elems[ix - 2]);
         }
     }
     return &elems;                      //返回值为计算结束后的vector对象的地址(!静态容器地址)
 }

 inline bool fibo_elem_checking(int pos, int &elem) {

     const vector<int> *pesq = fibon_seq(pos);  //根据输入要取出元素的位置,创建数列,并返回地址;
     if (!pesq) {
         elem = 0; return false;
     }
     elem = (*pesq)[pos - 1];
     return true;

 }

int main()
{
    int elem = 20;

    if (fibo_elem_checking(7,elem)) {
       
        cout << "Successed in generating:";
        cout <<"the number is:" << elem ;

    }
        return 0;
}

 

5. 重载函数(Overloaded Function) 

  • 函数的重载主要使用以下方法: 同一个函数名称可以对应不同的参数表(parameter list),也就是说通过设定不同数量和类型的参数,一个函数名可以具有多种不同的功能-->通过控制传入参数的类型,程序自动决定采用哪个函数;
  • 注意!!仅能通过输入函数数量,类型来作为采用哪个重载函数的标准,不同的返回值不能作为评判标准。

 

6. 模板函数+函数重载(Template Functions))

  • 主要目的是:当我们输入参数不同,又想使用同一个函数进行处理,此时需要编辑模板函数,然后程序将能够自己判断输入的数值类型,自动生成对应的函数。
    template <typename elemType>
    void display_message(const string& msg, const vector<elemType>& vec) { //根据函数输入的第二个参数,自动匹配elemType数据类型
        cout << msg;
        for (int ix = 0; ix < vec.size(); ++ix) {
    
            elemType t = vec[ix];
            cout << t << " ";
        }
     }

    7. 函数指针(positers to Function)-可为程序带来更大弹性

        8.头文件

  •  由于自定义函数必须经过申明以后才能使用,若一个程序需要运行很多函数时,那就需要非常多的声明;

  • -->此时将全部函数的声明全部存放在一个头文件当中,就比较方便:

  • 重要!!在程序中,调用头文件方法:若.h头文件与.cpp文件在同一目录下,那么使用#include "ssss.h"即可

  • -->若在不同的目录下,需要使用#include <xxx.h>进行查找添加

                  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL是一款常用的开源关系型数据库管理系统,它支持多种操作系统和编程语言。本文将介绍如何安装MySQL Essential 5.1.36版本在Windows平台上使用。 1. 下载安装程序 首先,我们需要下载MySQL Essential 5.1.36-win32.msi安装程序,可以在官网或第三方下载站点下载。下载完成后,双击安装程序,开始安装。 2. 选择安装方式 选择默认安装方式即可,或按照个人需求自定义安装。在“选择配置类型”界面上,建议默认选择“完全安装”方式,并勾选“启动Windows服务”选项(这将使MySQL自动运行)。 3. 配置MySQL服务 在“确认安装”界面完成后,选择“执行”,将安装程序拷贝MySQL文件,并自动为MySQL生成一个服务。服务将在启动Windows服务时自动启动。 4. 安装过程小结 MySQL Essential 5.1.36-win32.msi安装程序非常简单,安装过程只需多次“下一步”,遵循默认设置进行即可。安装完成后,您可以在安装目录下找到MySQL的可执行文件和配置文件。现在您已经成功安装了MySQL Essential 5.1.36,可以开始使用它在自己的应用程序中使用了。 总体来说,MySQL Essential 5.1.36-win32.msi的安装非常简单,即使是对于没有数据库方面经验的用户也非常友好。顺利安装后,您可以在本地创建数据库和数据表时候,用MySQL对其进行管理,进行数据处理,抽取数据并生成报告。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值