02_C++笔记_函数

#include <iostream>
using namespace std;

void func_demo();//函数的原型

/**
 * 函数:要提高编程效率,可以深入学习STL和BOOST C++提供的功能
 * 函数使用三步骤:
 * 1. 函数的原型
 * 2. 函数的定义
 * 3. 函数的调用
 */
int main() {

    //函数的调用
    func_demo();
    return 0;
}

//函数的定义
void func_demo(){
    cout << "function demo" << endl;
}

复习数组和指针的关系:

#include <iostream>
#include <fstream>

using namespace std;


int main(){

    int arr[4] = {1,2,3,4};

    cout << arr << endl;
    cout << arr+1 << endl;
    cout << "---------------"<< endl;
    cout << &arr[0] << endl;
    cout << &arr[0]+1<< endl;
    cout << "---------------"<< endl;
    cout << &arr << endl;
    cout << &arr+1 << endl;
    cout << &arr+2 << endl;

    cout << sizeof(arr) << endl;

    cout << "---------------"<< endl;
    cout << arr[1] << endl;
    cout << *(arr+1) << endl;

    cout << "---------------"<< endl;
    cout << &arr[1] << endl;//0x61ff04
    cout << arr+1 << endl;//0x61ff04
    return 0;
}

结果如下:

0x61ff00
0x61ff04
---------------
0x61ff00
0x61ff04
---------------
0x61ff00
0x61ff10
0x61ff20
16
---------------
2
2
---------------
0x61ff04
0x61ff04

数组和指针作为参数传递:

#include <iostream>

using namespace std;

const int ArSize = 4;
int sum_arr(int arr[], int ArSize);
int sum_arr(double arr[], int ArSize);
int sum_arr02(int * arr, int ArSize);

int main(){

    cout << sizeof (double *) << endl;

    int arr[ArSize] = {1,2,3,4};

    /**
     * 这里是将arr的地址传递给了sum_arr函数
     * 并不是将arr的内容 {1,2,3,4} 赋值给了 sum_arr函数的第一个参数
     * 这并不违反C++值传递的方法,这里也是值传递,只是传递的是一个地址,而不是数组的内容。
     * 
     * 而赋值给ArSize是值拷贝
     * */
    cout << arr << endl;
    cout << sizeof arr << endl;

    int sum1 = sum_arr(arr, ArSize);
    cout << sum1 << endl;

    int sum2 = sum_arr02(arr, ArSize);
    cout << sum2 << endl;

    double arr2[ArSize] = {};
    sum_arr(arr2,ArSize);
    return 0;
}

int sum_arr(double arr[], int ArSize){
     cout << sizeof arr << endl;//4
     return 0;
}

int sum_arr(int arr[], int ArSize){

    //'sizeof' on array function parameter 'arr' will return size of 'int*'
    cout << sizeof arr << endl;//4

    cout << arr << "函数中的值" << endl;
    int sum = 0;
    for (int i = 0; i < ArSize; i++)
    {
        sum += arr[i];
    }
    
    return sum;
}

int sum_arr02(int * arr, int ArSize){

    int sum = 0;
    for (int i = 0; i < ArSize; i++)
    {
        sum += arr[i];
    }
    
    return sum;
}

进一步改进:

#include <iostream>

using namespace std;

const int ArSize = 4;
//参数定义数组的开始地址和结束地址
int sum_arr(const int *begin, const int *end);

int main()
{
    int arr[ArSize] = {1, 2, 3, 4};

    int sum = sum_arr(arr, arr + ArSize);
    cout << sum;//10
    return 0;
}

int sum_arr(const int *begin, const int *end)
{

    const int *pt;
    int sum = 0;
    for (pt = begin; pt != end; pt++)
    {
        sum += *pt;
    }
    return sum;
}

const和指针,

//1. const修饰一个常量对象,防止使用该指针来修改所指向的值
const int age = 34;
//age = 23;//assignment of read-only variable 'age'
//int * p = &age;//invalid conversion from 'const int*' to 'int*' [-fpermissive]
const int * p = &age;//valid
//2. const修改一个指针对象,防止改变指针指向的位置
int main(){

    int age1 = 34;
    //*p 为const,不能被修改
    //p 不是const,可以被修改
    // 也就是说不能通过 *p 来修改变量age1的值
    //但是可以通过age1变量来修改
    const int * p = &age1;

    //*p += 1;//assignment of read-only location '* p'
    cout << p << endl;//0x63ff08
    cout << *p << endl;//34

    age1 = 23;//重新赋值
    cout << *p << endl;//23
    p = p+1;
    cout << p;//0x63ff0c

    return 0;
}

指针指向指针:

int main(){

    //指针指向指针
    int age = 34;
    int * pd = &age;
    int **pt = &pd;

    cout << &age << endl;//0x63ff08
    cout << pd << endl;//0x63ff08
    cout << * pd << endl;//34
    // ** pt = pd;
    //*pt  = pd;
    // pd = &age
    // => *pt = &age;

    cout << &pd << endl;//0x63ff04
    cout << pt << endl;//0x63ff04 pt指向的是pd的地址
    cout << * pt << endl;//0x63ff08 *pt 保存的是pd指针的内容
    cout << ** pt << endl;//34
    return 0;
}

int main() {

    int sloth = 3;

    const int * ps = &sloth;
    cout << ps << endl;//0x63ff04
    //* ps = 23;//assignment of read-only location '* ps'
    cout << ps+1 << endl;//0x63ff08

    int * const finger = &sloth;
    cout << finger << endl;//0x63ff04
    * finger = 24;
    cout << * finger << endl;//24
    cout << finger+1 << endl;//0x63ff08

    double a = 34.5;
    const double * const pa = &a;
    return 0;
}
//不能将const修饰的nums赋值给非const修饰的形参
const int nums[3] = { 1, 2, 3 };

函数和C-风格字符串

#include <iostream>

unsigned int c_in_str(const char * str, char ch);
char * build_str(char c, int n);

using namespace std;

int main() {

    char mmm[15]="helloworld";
    unsigned int count = c_in_str(mmm,'o');
    cout << count << endl;
    char * pstr = build_str('M', 5);
    cout << &pstr[0] << endl;//MMMMM
    cout << &pstr[1] << endl;//MMMM
    cout << pstr[0] << endl;//M
    cout << pstr[1] << endl;//M
    cout << * pstr << endl;//M
    cout << pstr << endl;//MMMMM
    cout << (int * )pstr << endl;//0x681be8
    cout << &pstr << endl;//0x63fef8
    cout << (int * )(pstr+1) << endl;//0x681be9

    cout << ((int *)pstr+1) << endl;//0x681bec
    delete [] pstr;//释放内存,不等于变量销毁。
    return 0;
}

/**
 * 1. 函数和C-风格字符串
 *  C-风格字符串:一系列字符组成,以空值字符结尾
 *  将字符串作为参数时,意味着传递的是地址,
 *  可以使用const来禁止怼字符串参数进行修改
 * 2. 字符串三种表示:
 *  2.1 char数组(C-风格字符串和char数组重要区别:字符串有内置结束字符)
 *  2.2 用引号括起来的字符串常量
 *  2.3 被设置为字符串的地址的char指针
 *
 */

//处理字符串中字符的标准方式
unsigned int c_in_str(const char * str, char ch){

    cout << *str << endl;

    unsigned int count = 0;
    while(*str){ //quit 当是结束字符'\0'时,该表达式为false
        if(*str == ch){
            count++;
        }
        str++;//指针向下移动一位
    }

    return count;
}

//返回C-风格的字符串
//函数无妨返回一个字符串,但是可以返回一个字符串的地址
char * build_str(char c, int n){
    char * pstr = new char[n+1];
    cout << "build_str:"<< &pstr << endl;
    pstr[n] = '\0';

    while(n-- > 0){
        pstr[n] = c;
    }
    return pstr;
}

函数和结构:

#include <iostream>
using namespace std;

struct travel_time {
    int hours;
    int mins;
};

const int Mins_per_hr = 60;
travel_time sum(travel_time t1, travel_time t2);
void show_time(travel_time t);

struct rect {
    double x;
    double y;
};

struct polar {
    double r;
    double angle;
};

const int Rad_to_deg = 57.3;
polar rect_to_polar(rect r);
void show_polar(polar p);

void rect_to_polar2(rect * r, polar * pda);
void show_polar2(const polar * pda);

int main() {

    //1.1 传递和返回结构
    travel_time t1 = { 1, 23 };
    travel_time t2 = { 2, 53 };
    travel_time t = sum(t1, t2);
    show_time(t); //hours:4,mins:16
    rect rplace = { 100, 100 };
    polar p = rect_to_polar(rplace);
    show_polar(p); //r:141.421 angel:44.7677degrees

    //1.2 传递结构的地址
    polar place;
    rect_to_polar2(&rplace, &place);
    show_polar2(&place); //r:141.421 angel:44.7677degrees
    return 0;
}

/**
 * 1. 函数和结构
 */

//1.1 传递和返回结构
travel_time sum(travel_time t1, travel_time t2) {

    travel_time total;
    total.mins = (t1.mins + t2.mins) % Mins_per_hr;
    total.hours = (t1.hours + t2.hours) + (t1.mins + t2.mins) / Mins_per_hr;

    return total;
}
void show_time(travel_time t) {
    cout << "hours:" << t.hours << ",mins:" << t.mins << endl;
}

#include <cmath>

polar rect_to_polar(rect r) {
    polar answer;
    answer.r = sqrt(r.x * r.x + r.y * r.y);
    answer.angle = atan2(r.y, r.x);
    return answer;
}
void show_polar(polar p) {
    cout << "r:" << p.r << endl;
    cout << "angel:" << p.angle * Rad_to_deg << "degrees" << endl;
}

//1.2 传递结构的地址
void show_polar2(const polar * pda) {
    cout << "r:" << pda->r << endl;
    cout << "angel:" << pda->angle * Rad_to_deg << "degrees" << endl;
}

void rect_to_polar2(rect * r, polar * p) {

    p->r = sqrt(r->x * r->x + r->y * r->y);
    p->angle = atan2(r->y, r->x);
}

函数和string

#include <iostream>
using namespace std;

void test();
void display(const string sa[], int n);

int main() {

    test();
    return 0;
}

void test() {
    const int SIZE = 5;
    string list[SIZE]; //数组,存储了5个字符串对象
    for (int i = 0; i < SIZE; i++) {
        cout << i + 1 << ":";
        getline(cin, list[i]);
    }

    cout << "your list:" << endl;
    display(list, SIZE);
}

//函数和string
void display(const string sa[], int n) {
    for (int i = 0; i < n; i++) {
        cout << i+1 << ":" << sa[i] << endl;
    }
}

函数和array

#include <iostream>
#include <array>
#include <string>

const int Seasons = 4;
const std::array<std::string, Seasons> Snames = { "Spring", "Summer", "fall",
        "winter" };

//修改array
void fill(std::array<double, Seasons> * pa);
//显示array
void show(std::array<double, Seasons> da);

int main() {

    std::array<double, Seasons> expenses;

    fill(&expenses);
    show(expenses);

    return 0;
}

//修改array
void fill(std::array<double, Seasons> * pa) {
    using namespace std;
    for (int i = 0; i < Seasons; ++i) {
        cout << "enter " << Snames[i] << " expenses:";
        cin >> (*pa)[i];
    }
}
//显示array
void show(std::array<double, Seasons> da) {
    using namespace std;
    double total = 0.0;
    cout << "\n expenses: " << endl;
    for (int i = 0; i < Seasons; ++i) {
        cout << Snames[i] << ": $" << da[i] << " expenses:";
        total += da[i];
    }
    cout << "total:" << total << endl;
}

//结果如下:
enter Spring expenses:23.4
enter Summer expenses:45.6
enter fall expenses:67.8
enter winter expenses:78.9

 expenses: 
Spring: $23.4 expenses:Summer: $45.6 expenses:fall: $67.8 expenses:winter: $78.9 expenses:total:215.7

函数指针:

#include <iostream>
#include <array>
#include <string>

double a(int lns);
double b(int lns);
void estimate(int lines, double (*pf)(int));
int main() {

    using namespace std;

    int lines = 5;

    estimate(lines, a);//传递函数的地址
    estimate(lines, b);

    return 0;
}

/**
 * 1. 函数指针
 *  1.1  获取函数的地址: 函数名就是函数的地址
 *      process(think);// 将函数think的地址传递给process()
 *      process(think());// 将函数think()的返回值传递给process()
 *
 *  1.2  声明一个函数指针
 *      声明某种类型的指针时,必须指定指针指向的类型。
 *      同样:声明指向函数的指针时,必须指定指针指向的函数类型。
 *
 *      例如:
 *      double pam(int);//函数原型
 *      double (* pf)(int);// pf 指向了一个函数:接收一个int类型参数,并返回一个double类型
 *      这里:pam是函数,(* pf)也是函数,那么 pf 就是函数指针
 *
 *      通常:
 *      声明函数指针,先声明函数原型,然后将(* pf) 替换函数名。这样pf就是这类函数指针
 *
 *      赋值:
 *      double ned(int);
 *      double (* pf)(int);
 *      pf = ned;//赋值
 *
 *  1.3  使用函数指针来调用函数
 *      调用:
 *      形式1:double x = (* pf)(5);--很清晰的看出来在使用函数指针
 *      形式2:double x = pf(5);
 */

double a(int lns) {
    return 0.5 * lns;
}

double b(int lns) {
    return 0.5 * lns + 0.02 * lns * lns;
}

void estimate(int lines, double (*pf)(int)) {
    using namespace std;

    cout << lines << " lines will take " << (*pf)(lines) << " hours" << endl;
}

深入理解函数指针:

#include <iostream>
#include <array>
#include <string>

//f1,f2,f3 实质是一样的
const double * f1(const double arr[], int n);
const double * f2(const double[], int n);
const double * f3(const double *, int n);

//声明一个函数指针,并初始化,指向f1
const double * (*pf)(const double arr[], int n) = f1;
//C++11 可以使用自动类型推断,声明一个函数指针,并初始化,指向f2
auto p2 = f2;

//声明一个包含三个函数指针的数组,注意[3]的位置
//这里不能使用auto.因为自动类型推断只能用于单值初始化,而不能初始化列表
const double * (*pa[3])(const double *, int n) = {f1,f2,f3};
//声明pa之后,可以使用auto再声明一个
auto pb = pa;

//数组名是指向第一个元素的指针,因此pa和pb都是指向函数指针的指针。
//如何使用它们来调用函数呢?
//const double * px = pa[0](av,3); 调用第一个函数
//const double * px = (*pa[1])(av,3); 调用第二个函数

//获取函数返回的double的值
//double x = *pa[0](av,3);
//double y = *(*pb[1])(av,3);


//创建指向整个数组的指针。
//1. 用自动类型推断
auto pc = &pa;
//2. 使用声明的类型
const double * (*(*pd)[3])(const double *, int) = &pa;

int main() {

    using namespace std;
    return 0;
}

转载于:https://www.jianshu.com/p/49db08aebf44

猜你喜欢

转载自blog.csdn.net/weixin_33779515/article/details/91326340