c++primer第七章函数学习笔记

函数的基本知识

定义函数

无返回值

void functionName(parameterList)

{

    statement(s);

    return; // optional

}

有返回值

    typeName funtionName(parameterList)

    {

        statements;

        return value;

    }

#include <iostream>
using namespace std;
void simple();
int main()
{

    //     // c++ 的编程模块
    cout << "main() will call the simple () function: \n";
    simple(); // function
    return 0;
}
void simple()
{
    cout << "I'm but a simple function";
}

函数原型和函数调用

#include <iostream>
using namespace std;
void cheers(int);
double cube(double x);
int main()
{
    cheers(5);
    cout << "Give me a number: ";
    double side;
    cin >> side;
    double volume = cube(side);
    cout
        << "A " << side << "-foot cube has a volume of ";
    cout << volume << " cubic feet. \n";
    cheers(cube(2)); // 存在自动类型转换
    return 0;
}
void cheers(int n)
{
    using namespace std;
    for (int i = 0; i < n; i++)
        cout << "Cheers!";
    cout << endl;
}

double cube(double x)
{
    return x * x * x;
}

函数原型是一句语句,以分号结束。例如

函数原型的功能:

函数参数和按值传递

用于传递值的变量为形参(parameter),传递给函数的值为实参(argument)

多个参数用逗号隔开

#include <iostream>
using namespace std;
void n_chars(char, int);
int main()
{
    int times;
    char ch;

    cout << "Enter a character: ";
    cin >> ch;
    while (ch != 'q')
    {
        cout << "Enter an integer: ";
        cin >> times;
        cout << ch;
        n_chars(ch, times);
        cout << "\nEnter another character or press the q-key to quit: ";
        cin >> ch;
    }
    cout << "The value of time is " << times << ". \n";
    cout << "Bye\n";
    return 0;
}
void n_chars(char c, int n)
{
    while (n-- > 0)
        cout << c;
}

另外一个接受两个参数的的函数(抽奖概率)

#include <iostream>

long double probability(unsigned numbers, unsigned picks);
using namespace std;
int main()
{
    double total, choices;
    cout << "Enter the total number of choices on the game card and\n"
            "the number of picks allowed:\n";
    while ((cin >> total >> choices) && choices <= total)
    {
        cout << "You have one chance in ";
        cout << probability(total, choices);
        cout << " of winning.\n";
        cout << "Next two numbers (q to quit): ";
    }
    cout << "Bye\n";
    return 0;
}
long double probability(unsigned numbers, unsigned picks)
{
    long double result = 1.0;
    long double n;
    unsigned p;

    for (n = numbers, p = picks; p > 0; n--, p--)
        result = result * n / p;
    return result;
}

函数和数组

int sum_arr(int arr[], int n)

// // list 7.5
#include <iostream>
const int ArSize = 8;
int sum_arr(int arr[], int n);
// int sum_arr(const int *begin, const int *end);
using namespace std;
int main()
{
    int cookies[ArSize] = {1, 2, 4, 8, 16, 32, 64, 128};
    // C++ 将数组名解释为其第一个元素的地址 cookies = &cookies[0]
    //  对数组名使用sizeof()将得到整个数组的长度(以字节为单位)
    //  int arr[] 在函数头与 int *arr 等价
    cout << cookies << " = array address, ";
    // int sum;
    int sum = sum_arr(cookies, ArSize); // 指针减法是整数值
    cout << "Total cookies eaten: " << sum << endl;
    return 0;
}
int sum_arr(int arr[], int n)
{
    int total = 0;
    cout << arr << " = arr, ";
    cout << sizeof arr << "= sizeof arr\n"; // wrong
    for (int i = 0; i < n; i++)
        total += arr[i];
    return total;
}

函数通过指针来处理数据

其中输入arr[] 是一个指针

将数组作为参数

C++ 将数组名解释为其第一个元素的地址

函数将数组的地址赋给指针变量

nclude <iostream>
const int ArSize = 8;
int sum_arr(int arr[], int n);
// int sum_arr(const int *begin, const int *end);
using namespace std;
int main()
{
    int cookies[ArSize] = {1, 2, 4, 8, 16, 32, 64, 128};
    // C++ 将数组名解释为其第一个元素的地址 cookies = &cookies[0]
    //  对数组名使用sizeof()将得到整个数组的长度(以字节为单位)
    //  int arr[] 在函数头与 int *arr 等价
    cout << cookies << " = array address, ";
    // int sum;
    int sum = sum_arr(cookies, ArSize); // 指针减法是整数值
    cout << "Total cookies eaten: " << sum << endl;
    sum = sum_arr(cookies, 3);
    cout << "First three eaters ate " << sum << " cookies.\n";
    sum = sum_arr(cookies + 4, 4);
    cout << "Last four eaters ate " << sum << " cookies.\n";
    return 0;
}

int sum_arr(int arr[], int n)
{
    int total = 0;
    cout << arr << " = arr, ";
    cout << sizeof arr << "= sizeof arr\n"; // wrong
    for (int i = 0; i < n; i++)
        total += arr[i];
    return total;
}

填充数组

const保护数组

修改数组

结合代码

#include <iostream>
const int Max = 5;
int fill_array(double arr[], int limit);
void show_array(const double arr[], int n);
void revalue(double r, double ar[], int n);
using namespace std;
int main()
{
    double properties[Max];

    int size = fill_array(properties, Max);
    show_array(properties, size);
    cout << "Enter revaluation factor:";
    double factor;
    cin >> factor;
    revalue(factor, properties, size);
    show_array(properties, size);
    cout << "Done.\n";
    return 0;
}
int fill_array(double arr[], int limit)
{
    double temp;
    int i;
    for (i = 0; i < limit; i++)
    {
        cout << "Enter value #" << (i + 1) << ": ";
        cin >> temp;
        if (!cin)
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input: input process terminated.\n";
            break;
        }
        else if (temp < 0)
            break;
        arr[i] = temp;
    }
    return i;
}
// 展示数组
void show_array(const double arr[], int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << "Property #" << (i + 1) << " : $";
        cout << arr[i] << endl;
    }
}
// 修改数组
void revalue(double r, double ar[], int n)
{
    for (int i = 0; i < n; i++)
        ar[i] *= r;
}

使用数组区间的函数

#include <iostream>
const int ArSize = 8;
int sum_arr(const int *begin, const int *end);
using namespace std;
int main()
{
    int cookies[ArSize] = {1, 2, 4, 8, 16, 32, 64, 128};
    // C++ 将数组名解释为其第一个元素的地址 cookies = &cookies[0]
    //  对数组名使用sizeof()将得到整个数组的长度(以字节为单位)
    //  int arr[] 在函数头与 int *arr 等价
    cout << cookies << " = array address, ";
    // int sum;
    int sum = sum_arr(cookies, cookies + ArSize); // 指针减法是整数值
    cout << "Total cookies eaten: " << sum << endl;
    sum = sum_arr(cookies, cookies + 3);
    cout << "First three eaters ate " << sum << " cookies.\n";
    sum = sum_arr(cookies + 4, cookies + 8);
    cout << "Last four eaters ate " << sum << " cookies.\n";
    return 0;
}
int sum_arr(const int *begin, const int *end)
{
    const int *pt;
    int total = 0;
    // cout << arr << " = arr, ";
    // cout << sizeof arr << "= sizeof arr\n"; // wrong
    for (pt = begin; pt != end; pt++)
        total += *pt;
    return total;
}

指针和const

指针指向常数对象,防止指针修改指向的值; 指针本身声明为常亮,防止指针改变指向的位置

int age = 30;

const int *pt = &age;

不能通过pt对age进行修改,但是可以通过age来修改

函数和二维数组

二维数组属于指向指针的指针

函数和C-风格字符串

 表示字符串的方式

 1. char数组

 2. 有引号括起来的字符串常量

 3. 被设置为字符串的地址的char指针

include <iostream>
int c_in_str(const char *str, char ch);
using namespace std;
int main()
{
    char mmm[15] = "minimum";
    char *wail = "ululate";

    int ms = c_in_str(mmm, 'm');
    int us = c_in_str(wail, 'u');
    cout << ms << "m characters in " << mmm << endl;
    cout << us << "u characters in " << wail << endl;
}

int c_in_str(const char *str, char ch)
{
    int count = 0;
    while (*str)
    {
        if (*str == ch)
            count++;
        str++;
    }
    return count;
}

返回C-风格字符串的函数

#include <iostream>
char *build(char c, int n);
using namespace std;
int main()
{
    int times;
    char ch;
    cout << "Enter a character: ";
    cin >> ch;
    cout << "Enter an integer: ";
    cin >> times;
    char *ps = build(ch, times);
    cout << ps << endl;

    delete[] ps;
    ps = build('+', 20);
    cout << ps << "-DONE-" << ps << endl;
    delete[] ps;
    return 0;
}
char *build(char c, int n)
{
    char *pstr = new char[n + 1];
    pstr[n] = '\0';
    while (n-- > 0)
        pstr[n] = c;
    return pstr;
}

函数和结构

传递和返回结构

#include <iostream>
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 t1);
using namespace std;
int main()
{
    travel_time day1 = {5, 45};
    travel_time day2 = {4, 55};

    travel_time trip = sum(day1, day2);
    cout << "Two-day total: ";
    show_time(trip);

    travel_time day3 = {4, 32};
    cout << "Three-day total:";
    show_time(sum(trip, day3));

    return 0;
}
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 << t.hours << " hours, ";
    cout << t.mins << "minutes.\n";
}

另一个处理结构的函数范例

#include <iostream>
#include <cmath>
struct rect
{
    double x;
    double y;
};
struct polar
{
    double distance;
    double angle;
};
void show_polar(polar dapos);
polar rect_to_polar(rect xypos);
using namespace std;
int main()
{
    rect rplace;
    polar pplace;

    cout << "Enter the x and the y values: ";
    while (cin >> rplace.x >> rplace.y)
    {
        pplace = rect_to_polar(rplace);
        show_polar(pplace);
        cout << "Next two numbers (q to quit):";
    }
    cout << "Done.\n";
    return 0;
}

void show_polar(polar dapos)
{
    const double Rad_to_deg = 57.29577951;

    cout << "distance = " << dapos.distance;
    cout << ", angle = " << dapos.angle * Rad_to_deg;
    cout << " degrees\n";
}
polar rect_to_polar(rect xypos)
{
    polar answer;

    answer.distance =
        sqrt(xypos.x * xypos.x + xypos.y * xypos.y);
    answer.angle = atan2(xypos.y, xypos.x);
    return answer;
}

传递结构的地址

形参是指针使用间接操作符,结构使用成员操作符

间接成员操作符(->)  直接成员操作符(.)

#include <iostream>
#include <cmath>
struct rect
{
    double x;
    double y;
};
struct polar
{
    double distance;
    double angle;
};
void show_polar(const polar *pda);
void rect_to_polar(const rect *pxy, polar *pda);
using namespace std;

int main()
{
    rect rplace;
    polar pplace;

    cout << "Enter the x and the y values: ";
    while (cin >> rplace.x >> rplace.y)
    {
        rect_to_polar(&rplace, &pplace);
        show_polar(&pplace);
        cout << "Next two numbers (q to quit):";
    }
    cout << "Done.\n";
    return 0;
}
void show_polar(const polar *pda)
{
    const double Rad_to_deg = 57.29577951;

    cout << "distance = " << pda->distance;
    cout << ", angle = " << pda->angle * Rad_to_deg;
    cout << " degrees\n";
}

void rect_to_polar(const rect *pxy, polar *pda)
{
    pda->distance = sqrt(pxy->x * pxy->x + pxy->y * pxy->y);
    pda->angle = atan2(pxy->y, pxy->x);
}

函数和string对象

可以用string 类型对象数组代替二维char数组;

#include <iostream>
#include <string>
using namespace std;
const int SIZE = 5;
void display(const string sa[], int n);

int main()
{
    string list[SIZE];
    cout << "Enter your " << SIZE << "favorite astronomical sights: \n";
    for (int i = 0; i < SIZE; i++)
    {
        cout << i + 1 << ": ";
        getline(cin, list[i]);
    }

    cout << "Your list: \n";
    display(list, SIZE);
    return 0;
}
void display(const string sa[], int n)
{
    for (int i = 0; i < n; i++)
        cout << i + 1 << ": " << sa[i] << endl;
}

sa 是一个指向sring对象的指针,sa[i] 是一个string对象。

递归

包含一个递归调用的递归

void recurs(argumentlist)

{

    statements1;

    if (test)

        recurs(arguments)

    statements2

}

#include <iostream>
void countdown(int n);
using namespace std;
int main()
{
    countdown(4);
    return 0;
}

void countdown(int n)
{
    cout << "Counting down ..." << n << "(n at" << &n << ")" << endl;
    if (n > 0)
        countdown(n - 1);
    cout << n << ": Kaboom!\n";
}

改变代码显示n的地址和值

#include <iostream>
void countdown(int n);
using namespace std;
int main()
{
    countdown(4);
    return 0;
}

void countdown(int n)
{
    cout << "Counting down ..." << n << "(n at" << &n << ")" << endl;
    if (n > 0)
        countdown(n - 1);
    cout << n << ": Kaboom!" << "(n at " << &n << ") " << endl;
    ;
}

包含多个递归调用的递归

#include <iostream>
const int Len = 66;
const int Divs = 6;
using namespace std;
void subdivide(char ar[], int low, int high, int level);
int main()
{
    char ruler[Len];
    int i;
    for (i = 1; i < Len - 2; i++)
        ruler[i] = ' ';
    ruler[Len - 1] = '\0';
    int max = Len - 2;
    int min = 0;
    ruler[min] = ruler[max] = '|';
    cout << ruler << endl;
    for (i = 1; i <= Divs; i++)
    {
        subdivide(ruler, min, max, i);
        cout << ruler << endl;
        for (int j = 1; j < Len - 2; j++)
            ruler[j] = ' ';
    }
    return 0;
}
void subdivide(char ar[], int low, int high, int level)
{
    if (level == 0)
        return;
    int mid = (high + low) / 2;
    ar[mid] = '|';
    subdivide(ar, low, mid, level - 1);
    subdivide(ar, mid, high, level - 1);
}

函数指针

要声明指向特定类型的函数的指针,可以首先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针

函数指针的基本知识

函数指针的机制

  • 获取函数的地址
  • 声明一个函数指针
  • 使用函数指针来调用函数

 获取函数地址

获取函数地址只用使用函数名,如果think()是一个函数,则think就是函数的地址

声明函数指针

要声明指向特定类型的函数的指针,可以首先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针,例如

double pam (int);

double (*pf) (int);

pf = pam;

使用函数指针来调用函数

使用(*pf),将它看作函数名

函数指针示例

#include <iostream>
double betsy(int);
double pam(int);

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

int main()
{
    int code;

    cout << "How many lines of code do you need? ";
    cin >> code;
    cout << "Here's Betsy's estimate: \n";
    estimate(code, betsy);
    cout << "Here's Pam's estimate: \n";
    estimate(code, pam);
    return 0;
}

double betsy(int Lns)
{
    return 0.05 * Lns;
}
double pam(int Lns)
{
    return 0.03 * Lns + 0.0004 * Lns * Lns;
}

void estimate(int lines, double (*pf)(int))
{
    cout << lines << "lines will take ";
    cout << (*pf)(lines) << "hour(s)\n";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值