《C++PrimerPlus》第7章 函数:C++的编程模块

7.1 复习函数的基本知识

函数的定义和使用

#include <iostream>
using namespace std;
int main()
{
	void cheers(int n);
	double cube(double x);
	cheers(5);
	double res;
	res = cube(1.5);
	cout << res << endl;
}
void cheers(int n){
	for (int i = 0; i < n; i++){
		cout << "cheers " << endl;
	}
}
double cube(double x){
	return x*x*x;
}

7.2 函数参数和按值传递

7.3 函数和数组

数组的填充、显示和修改

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

int main()
{
	double properties[Max];
	int size = fill_array(properties, Max); // 填充数组
	show_array(properties, size); // 显示数组内容
	if (size > 0) { // 数组里确实有值
		cout << "Enter revaluation factor: ";
		double factor;
		while (!(cin >> factor)) {
			cin.clear();
			while (cin.get() != '\n') continue;
			cout << "Bad input, process terminate." << endl;
		}
		revalue(factor, properties, size); // 根据参数,修改数组
		show_array(properties, size); // 显示修改后的数组
	}
	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, process terminate." << endl;
			break; // 输入错误字符,终止输入
		}
		else if (temp < 0) break; // 输入值小于0,终止输入
		else arr[i] = temp;
	}
	return i; // 返回当前读了几个数
}

void show_array(const double arr[], int n) { // const:不可以通过指针来修改数组
	for (int i = 0; i < n; i++) {
		cout << "Property #" << i + 1 << ": ";
		cout << arr[i] << endl;
	}
}

void revalue(double r, double arr[], int n) {
	for (int i = 0; i < n; i++) {
		arr[i] *= r;
	}
}

const限定符和指针

#include <iostream>
using namespace std;

int main(){
	int n = 10;
	int *pt = &n; // 新建一个指向n的指针
	cout << "1) n = " << n << endl; // n = 10
	*pt = 20; // 通过指针来修改n的值
	cout << "2) n = " << n << endl; // n = 20
	
	const int *pt1 = &n; // 不能通过指针来修改指向的内容,指针指向可以修改
	// 写成 int const *pt1 是等价的
	*pt1 = 20; // 不合法,会报错
	n = 20; // 但是可以直接修改变量的值
	int m = 20;
	pt1 = &m; // 合法,修改指针指向

	int *const pt2 = &n; // 可以通过指针修改内容,但不能修改指针指向
	*pt2 = 20; // 合法,通过指针修改内容
	pt2 = &m; // 不合法,会报错

	const int *const pt3; // 不能通过指针修改指向内容,也不可以修改指针指向

	return 0;
}

使用数组区间的函数

#include <iostream>
using namespace std;
int sum_arr(const int *begin, const int *end);

int main(){
	int cookies[5] = { 1,2,3,4,5 };
	int sum = sum_arr(cookies, cookies+5); // cookie+5,数组末尾的后一个位置
	cout << "Total is: " << sum << endl;
	return 0;
}

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

7.4 函数和二维数组

7.5 函数和C-风格字符串

将C-风格字符串作为参数的函数

#include <iostream>
using namespace std;
unsigned int c_in_str(const char *str, char ch);

int main(){
	char mmm[15] = "minimum";
	// char *wail = "ululate"; 非法,不可以把一个字符串常量赋值给一个非const指针
	const char *wail = "ululate";
	unsigned int ms = c_in_str(mmm, 'm'); // 返回字符串中有几个m
	unsigned int us = c_in_str(wail, 'u');

	cout << ms << " m characters in " << mmm << endl;
	cout << us << " u characters in " << wail << endl;
	return 0;
}

unsigned int c_in_str(const char *str, char ch) {
	unsigned int count = 0;
	// 遍历str指针里面的内容,直到最后一个字符
	while (*str) {
		if (*str == ch) count++;
		str++;
	}
	return count;
}

返回C风格字符串的函数

#include <iostream>
using namespace std;
char *buildstr(char ch, int n);

int main(){
	char ch;
	int times;
	cout << "Enter a character: ";
	cin >> ch;
	cout << "Enter an integer: ";
	cin >> times;

	char *ps = buildstr(ch, times);
	cout << ps << endl;
	delete[] ps; // new和delete成对出现
	return 0;
}

char *buildstr(char ch, int n) {
	char *pstr = new char[n + 1]; // n+1长度,因为最后要放空字符'\0'
	pstr[n] = '\0';
	for (int i = 0; i < n; i++) {
		pstr[i] = ch;
	}
	return pstr;
}

7.6 函数和结构

传递和返回结构

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

struct polar { // 极坐标
	double distance;
	double angle;
};
struct rect { // 直角坐标
	double x;
	double y;
};

polar rect_to_polar(rect xypos);
void show_polar(polar ppos);

int main(){
	rect rplace;
	polar pplace;
	cout << "Enter the x and y values: ";
	while (cin >> rplace.x >> rplace.y) { // 当输入有效时
		pplace = rect_to_polar(rplace); // 转换坐标
		show_polar(pplace); // 显示坐标
		cout << "Next two numbers(q to quit): " << endl;
	}
	return 0;
}

polar rect_to_polar(rect xypos) {
	polar answer;
	answer.distance = sqrt(xypos.x * xypos.x + xypos.y * xypos.y);
	answer.angle = atan2(xypos.x, xypos.y); // 函数atan2()可根据x和y计算弧度
	return answer;
}

void show_polar(polar ppos) {
	const double Rad_to_deg = 57.2957795;
	cout << "distance = " << ppos.distance << ", angle = " << ppos.angle * Rad_to_deg;
	cout << " degrees" << endl;
}

传递结构的地址

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

struct polar { // 极坐标
	double distance;
	double angle;
};
struct rect { // 直角坐标
	double x;
	double y;
};

void rect_to_polar(const rect* xypos, polar* pplace);
void show_polar(const polar* ppos);

int main(){
	rect rplace;
	polar pplace;
	cout << "Enter the x and y values: ";
	while (cin >> rplace.x >> rplace.y) { // 当输入有效时
		rect_to_polar(&rplace, &pplace); // 转换坐标(传入两个地址)
		show_polar(&pplace); // 显示坐标(传入两个地址)
		cout << "Next two numbers(q to quit): " << endl;
	}
	return 0;
}
// polar* pplace前面不加const限定符,因为我们需要借助指针修改值
void rect_to_polar(const rect* xypos, polar* pplace) {
	// 注意使用间接成员运算符(->)
	pplace->distance = sqrt(xypos->x * xypos->x + xypos->y * xypos->y);
	pplace->angle = atan2(xypos->x, xypos->y); // 函数atan2()可根据x和y计算弧度
}

void show_polar(const polar* ppos) {
	const double Rad_to_deg = 57.2957795;
	cout << "distance = " << ppos->distance << ", angle = " << ppos->angle * Rad_to_deg;
	cout << " degrees" << endl;
}

7.7 函数和string对象

string对象数组

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

int main(){
	string list[5];
	cout << "Enter 5 favourite food:" << endl;
	for (int i = 0; i < 5; i++) {
		cout << i + 1 << ":";
		getline(cin, list[i]);
	}
	cout << "Your list:" << endl;
	display(list, 5);
	return 0;
}

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

7.8 函数与array对象

使用模板array

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

array<string, 4> Snames = {"Spring","Summer","Fall","Winter"};
void fill(array<double, 4> * pa);

int main(){
	array<double, 4> expenses; // 每个季节的开销
	fill(&expenses); // 操作指针来修改原始数据
	return 0;
}

void fill(array<double, 4> * pa) {
	for (int i = 0; i < 4; i++) {
		cout << "Enter " << Snames[i] << " expenses: ";
		cin >> (*pa)[i]; // pa[i] 是不行的
	}
}

7.9 递归

递归调用和逐级返回

#include <iostream>
using namespace std;
void countdown(int n);

int main(){
	countdown(4);
	return 0;
}

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

包含多个递归调用的函数

#include <iostream>
using namespace std;
const int Len = 66;
const int Divs = 6;
void subdivide(char ar[], int low, int high, int levels);

int main(){
	char ruler[Len];
	for (int i = 0; i < Len; i++) {
		ruler[i] = ' ';
	}
	int min = 0, max = Len - 2;
	ruler[Len - 1] = '\0'; // 字符串必须要有结束的空字符\0
	ruler[min] = ruler[max] = '|';
	cout << ruler << endl;

	for (int i = 1; i < Divs; i++) {
		subdivide(ruler, min, max, i);
		cout << ruler << endl;
	}
	return 0;
}

void subdivide(char ar[], int low, int high, int levels) {
	if (levels == 0)
		return;
	int mid = (low + high)/2;
	ar[mid] = '|';
	subdivide(ar, low, mid, levels-1);
	subdivide(ar, mid, high, levels - 1);
}

7.10 函数指针

函数指针示例

#include <iostream>
using namespace std;
double Rick(int lines);
double Jack(int lines);
void estimate(int lines, double(*pf)(int));

int main(){
	cout << "How many lines of your code?" << endl;
	int code;
	cin >> code;
	cout << "Here is Rick's estimate: " << endl;
	estimate(code, Rick);
	cout << "Here is Jack's estimate: " << endl;
	estimate(code, Jack);
	return 0;
}

double Rick(int lines) {
	return lines * 0.05;
}

double Jack(int lines) {
	return lines * 0.03 + lines * lines * 0.0004;
}

void estimate(int lines, double(*pf)(int)) {
	cout << lines << " lines code will take " << (*pf)(lines) << " sec." << endl;
}

函数指针比较复杂的用法

#include <iostream>
using namespace std;
const double *f1(const double *ar, int n);
const double *f2(const double ar[], int n);
const double *f3(const double ar[], int n);

int main(){
	double av[3] = { 1112.3, 1542.6, 22227.9 };

	//------------Part1---------------------
	// 定义一个函数指针p1指向f1
	const double * (*p1) (const double *, int) = f1;
	// C++11的auto功能,自动推定变量类型
	auto p2 = f2;
	cout << "Address    Value" << endl;
	// (*p1)(av, 3) == f1(av,  3), 注意f1的返回值是个指针(地址)
	cout << (*p1)(av, 3) << "   " << *(*p1)(av, 3) << endl;
	// 函数指针也可以直接当作函数名用, p2(av, 3) == f2(av, 3)
	cout << p2(av, 3)  << "   " << *p2(av, 3) << endl;

	//------------Part2---------------------
	// pa(pb)是一个有3个元素的数组,每个元素都是函数指针
	const double * (*pa[3])(const double *, int) = {f1, f2, f3};
	auto pb = pa;
	cout << "Address    Value" << endl;
	for (int i = 0; i < 3; i++) {
		cout << pa[i](av, 3) << "   " << *pa[i](av, 3) << endl;
		cout << pb[i](av, 3) << "   " << *pa[i](av, 3) << endl;
	}

	//------------Part3---------------------
	// &pa 取出pa数组的地址,赋值给pc(pc是一个指针)
	auto pc = &pa;
	const double *(*(*pd)[3])(const double *, int) = &pa; // auto的展开
	cout << "Address    Value" << endl;
	// (*pc) == pa, (*pc)[0](av,3) == pa[0](av,3)
	cout << (*pc)[0](av, 3) << "   " << *(*pc)[0](av, 3) << endl;
	// (*pc)[1](av,3) == pa[1](av,3) == f2(av,3), 返回一个地址,赋值给pdb
	const double *pdb = (*pd)[1](av, 3);
	cout << pdb << "   " << *pdb << endl;
	// 另一种等价的写法
	cout << (*(*pd)[2])(av, 3) << "   " << *(*(*pd)[2])(av, 3) << endl;
	return 0;
}
// f1:返回数组中第一个数的地址
const double *f1(const double *ar, int n) { // 指针表示法
	return ar;
}
// f2:返回数组中第二个数的地址
const double *f2(const double ar[], int n) { // 数组表示法
	return ar + 1;
}
// f3:返回数组中第三个数的地址
const double *f3(const double ar[], int n) {
	return ar + 2;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值