7.1 复习函数的基本知识
函数的定义和使用
#include
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
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
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
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
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
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
#include
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
#include
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
#include
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
#include
#include
using namespace std;
array Snames = {"Spring","Summer","Fall","Winter"};
void fill(array * pa);
int main(){
array expenses; // 每个季节的开销
fill(&expenses); // 操作指针来修改原始数据
return 0;
}
void fill(array * pa) {
for (int i = 0; i < 4; i++) {
cout << "Enter " << Snames[i] << " expenses: ";
cin >> (*pa)[i]; // pa[i] 是不行的
}
}
7.9 递归
递归调用和逐级返回
#include
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
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
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
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;
}