自学内容网 自学内容网

2024-11-30-C++ 学习:函数课后习题( Primer 第六章 上)山光悦鸟形,潭影空人心。

C++的学习不能断,我感觉冬天了,可以刷一下 C++ primer 这本大厚书。

一、前言

  C++中 函数 的相关习题的学习!

二、习题

练习6.1

问题: 实参和形参的区别?
答案:
(1)形参出现在函数定义的地方,形参列表可以包含0个、1个或多个形参,多个形参之间用逗号分隔开,形参规定了一个函数所接受的数据的类型和数量。
(2)实参出现在函数调用的地方,实参的数量和形参的数量一样多。实参的主要作用是初始化形参,并且这种初始化过程是一一对应的,即第一个实参初始化第一个形参,以此类推。

练习 6.2

问题 请指出下列函数哪个有错误,为什么?应该如何修改这些错误呢?

(a)
int f(){
string s;
// ...
return s;
-)

(b) 
f2(int i) {/* ... */ }

(c) 
int calc(int v1,int v1) /*...*/}

(d) 
double square(double x) return x*x;

答案

(a) 错误
string f(){
string s;
// ...
return s;
-)

(b) 错误 缺少返回类型
void f2(int i) {/* ... */ }

(c) 错误
int calc(int v1,int v2) {/*...*/}

(d) 错误
double square(double x) {return x*x;}

练习 6.8

问题
编写一个名为 Chapter6.h的头文件,令其包含6.1节练习(第184页)中的函数声明。

答案
根据题目要求,Chapter6.h头文件的内容如下:

#ifndef CHAPTER6_H_INCLUDED
#define CHAPTER6_H_INCLUDED

int fact(int );
double myABS(double);
double myABS2(double);

#endif //CHAPTER6_H_INCLUDED

练习 6.10 + 6.12

问题
编写一个函数,使用指针形参交换两个整数的值。在代码中调用该函数并输出交换后的结果,以此验证函数的正确性。

答案

  • 指针方法
#include <iostream>
using namespace std;
//在函数体内部通过解引用操作改变指针所指的内容
void mySWAP(int *p,int *q)
{
int tmp=*p;// tmp是一个整数
*p = *q;
*q= tmp;
}

int main()
{
int a=5,b=10;
int *r=&a, *s= &b;
cout <<“交换前:a ="<< a<< ",b ="<< b<< endl;
mySWAP(r,s);
cout <<"交換后;a="<< a<<",b="<<b<< endl;
return 0;
}
  • 非指针方法
#include <iostream>
using namespace std;

void mySWAP(int &i, int &j)
{
int tmp = i;
i = j;
j = tmp;
}

int main()
{
int a=5,b=10;
cout <<“交換前:a= " << a<< ",b="<< b << endl;
mySWAP(a,b);
cout <<“変换后:a="<<a<<",b="<<b<< endl;
return 0;
}

与使用指针相比,使用引用交换变量的内容从形式上看更简单一些,并既额外声明指针变量,也避免了拷贝指针的值

练习 6.14

问题
举一个形参应该是引用类型的例子,再举一个形参不能是引用类型的例子。

答案
与值传递相比,引用传递的优势主要体现在三个方面:一是可以直接操作引用形参所引的对象;二是使用引用形参可以避免拷贝大的类类型对象或容器类型对象:三是使用引用形参可以帮助我们从函数中返回多个值。
基于对引用传递优势的分析,我们可以举出几个适合使用引用类型形参的例子:第一,当函数的目的是交换两个参数的内容时应该使用引用类型的形参;第二,当参数是string对象时,为了避免拷贝很长的字符串,应该使用引用类型。
在其他情况下可以使用值传递的方式,而无须使用引用传递,例如求整数的绝对值或者阶乘的程序。

练习 6.16

问题
下面的这个函数虽然合法,但是不算特别有用。指出它的局限性设法改善。
bool is_empty(string& s) {return s.empty();}

答案
本题的程序把参数类型设为非常量引用,这样做有几个缺陷:
一是容易给使者一种误导,即程序允许修改变量s的内容;
二是限制了该函数所能接受的实参型,我们无法把const对象、字面值常量或者需要进行类型转换的对象传递给普的引用形参。

根据上述分析,该函数应该修改为:
bool is_empty(const string& s) {return s.empty();}

练习 6.17

问题
编写一个函数,判断 string 对象中是否含有大写字母。编写器个函数,把 string 对象全都改成小写形式。在这两个函数中你使用的形参类同吗?为什么?

答案

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

//判断字符串是否含有大写字母
bool HasUpper(const string& str)
{
for(auto c:str)
if(isupper(c))
return true;
return false;
}

//把字符串中的所有大写字母转成小写
void ChangeToLower(string& str)
{
for(auto &c:str)
c = tolower(c);
}

int main()
{
cout <<"请输入一个字符串:"<< endl;
string str;
cin >> str;
if(HasUpper(str))
{
ChangeToLower(str);
cout <<"转换后的字符串是:"<<str << endl;
}
else
{
cout<<"该字符串不含大写字母,无须转换"<<endl;
}
return 0;
}

练习 6.18

问题
为下面的函数编写函数声明,从给定的名字中推测函数具备的功能。
(a)名为 compare 的函数,返回布尔值,两个参数都是 matrix 类的引用。
(b)名为 change_val 的函数,返回 vector<int> 的迭代器,有两个参数:一个是 int,另一个是 vector<int> 的选代器。

答案
(a)的函数声明是:
bool compare( const matrix&,const matrix& )
(b)的函数声明是:
vector<int>::iterator change_val( int,vector<int>::iterator )

练习 6.22

问题
编写一个函数,令其交换两个 int 指针。

答案
【解答】
三个不同版本的函数
(1)第一个函数以值传递的方式使用指针,所有改变都局限于函数内部,当函数执行完毕后既不会改变指针本身的值,也不会改变指针所指的内容。
(2)第二个函数同样以值传递的方式使用指针,但是在函数内部通过解引用的方式直接访问内存并修改了指针所指的内容。
(3) 第三个函数的参数形式是 int*&,其含义是,该参数是一个引用,引用的对象是内存中的一个 int 指针,使用这种方式可以把指针当成对象,交换指针本身的值。需要注意的是,最后一个函数既然交换了指针,当然解引用该指针所得的结果也会相应发生改变。

#include <iostream>
using namespace std;


//(1)该函数既不交换指针,也不交换指针所指的内容
void SwapPointer1(int *p,int *q)
{
int *temp =p;
p = q;
q = temp;
}

//(2)该函数交换指针所指的内容
void SwapPointer2(int *p,int *q)
{
int temp =*p;
*p = *q;
*q = temp;
}

// (3)该函数交换指针本身的值,即交换指针所指的内存地址
void SwapPointer3(int *&p,int *&q)
{
int *temp =p;
p = q;
q= temp;
}

int main()
{
int a=5, b=10;
int *p=&a, *q= &b;
cout <<"交换前:"<< endl;
cout << "p 的值是:"<< p <<",q的值是:"<< q<< endl;
cout <<"p所指的值是:"<< *p <<",q所指的值是:"<< *q<< endl;
SwapPointer1(p,q);cout <<"交换后:"<< endl;
cout << "p的值是:"<<p<< ",q的值是:"<< q<< endl;
cout << "p 所指的值是:"<< *p<<",q所指的值是:"<< *q<<endl;

a=5,b=10;
p= &a,q= &b;
cout<<"交换前:"<<endl;
cout <<"p的值是:"<<p<<",q的值是:"<< q<< endl;
cout << "p 所指的值是:"<< *p<<",q所指的值是:"<<*q<< endl;
SwapPointer2(p,q);
cout<<"交换后:"<< endl;
cout << "p 的值是:"<< p<< ",q的值是:"<< q<< endl;
cout<<"p所指的值是:"<<|*p<<",q所指的值是:"<< *q<< endl;

a=5,b= 10;
p=&a,q=&b;
cout <<"交換前:"<< endl;
cout <<"p的值是:" <<p<<",q的值是:"<< q<< endl;
cout <<"p所指的值是:"<< *p <<",q所指的值是:"<< *q<< endl;
SwapPointer3(p,q);
cout <<"交换后:"<<endl;
cout <<"p的值是:"<< p<<",q的值是:"<<q<< endl;
cout <<"p所指的值是:"<<*p <<",q所指的值是;"<<*q << endl;

return 0;
}

练习 6.23

问题
参考本节介绍的几个print 函数,根据理解编写你自己的版本。依次调用每个函数使其输入下面定义的i和 j:
int i=0,j[2]={0,1};

答案

#include <iostream>
using namespace std:

//参数是常量整型指针
void print1(const int *p)
{
cout<<*p<< endl;
}

//参数有两个,分别是常量整型指针和数组的容量
void print2(const int *p,const int sz)
{
int i = 0;
while(i != sz)
{
cout << *p++ << endl;
++i;
}
}

//参数有两个,分别是数组的首尾边界
void print3(const int *b,const int *e)
{
for(auto q=b;q!=e;++q)
cout <<*q<< endl;
}

int main()
{
int i=0,j[2]={0,1};
print1(&i);
print1(j);
print2(&i,1);
//计算得到数组了的容量
print2(j,sizeof(j)/ sizeof(*j));
auto b=begin(j);
auto e=end(j);
print3(b,e);
return 0;
}

总结

  • 多做题,多思考,多记多背,加油~

在这里插入图片描述

代码是在 visual studio 中编写的,该软件还是比较好用的,我安装的是2022专业版;

共勉!


原文地址:https://blog.csdn.net/weixin_42269028/article/details/144157653

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!