码迷,mamicode.com
首页 > 编程语言 > 详细

《C++primer》v5 第6章 函数 读书笔记 习题答案

时间:2014-08-23 20:17:51      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   os   使用   io   文件   

6.1

实参是在函数调用处填写的参数。形参是在函数体使用的参数。

实参是形参的初始值。

具体参见:http://blog.163.com/zhengguo_li/blog/static/703014802013423501214/

6.2

(a)该函数试图返回一个局部变量。当函数调用结束后,s所占内存将会被释放,所以返回s是无效的

(b)该函数缺少返回值

(c)定义了两个同名的形参

(d)后面的语句应该写在{}里

6.3、6.4

using namespace std;
int fact(int val)
{
    int  ret=1;
    while(val)
        ret*=val--;
    return ret;
}
int main()
{
    int n;
    while(cin>>n)
        cout<<fact(n)<<endl;
        return 0;
}

6.5

using namespace std;
void showabs(int val)
{
    if(val>0) cout<<val<<endl;
    else cout<<-val<<endl;
}
int main()
{
    int n;
    while(cin>>n)
        showabs(n);
    return 0;
}

6.6

形参是局部变量。

局部变量是在函数体内部定义的变量和形参。它包括自动对象和静态局部对象。自动对象在函数调用结束,该变量占用内存释放。如果没有初始化,它的值是随机的。

局部静态对象在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止才被销毁,才期间即使对象所在的函数结束执行也不会对它有什么影响。如果没有初始化,它的值是0。

具体参见:http://www.myexception.cn/cpp/1633515.html

using namespace std;
void func(int val)
{
    static int ctr=0;
    int temp=10;
    ctr++;
    cout<<ctr<<endl;
}
int main()
{
    int n;
    while(cin>>n)
        func(n);
    return 0;
}

注意静态局部变量只能在定义它的函数内使用,其他地方不能使用,会编译错误。

6.7

using namespace std;
void func(int val)
{
    static int ctr=0;
    int temp=10;
    ctr++;
    cout<<ctr<<endl;
}
int main()
{
    int n;
    while(cin>>n)
        func(n);
    return 0;
}

 6.8

chapter6.h中:

void func(int);

源文件:

#include<iostream>
#include"chapter6.h"
using namespace std;
int main()
{
    int n;
    while(cin>>n)
        func(n);
    return 0;
}
void func(int val)
{
    static int ctr=0;
    int temp=10;
    ctr++;
    cout<<ctr<<endl;
}

6.9

暂略

6.10

void mySoap(int *x,int *y)
{
    int temp=*x;
    *x=*y;
    *y=temp;
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        mySoap(&a,&b);
        cout<<a<<" "<<b<<endl;
    }
    return 0;
}

6.11

void reset(int &i)
{
    i=0;
}
int main()
{
    int n;
    while(cin>>n)
    {
        reset(n);
        cout<<n<<endl;
    }
    return 0;
}

6.12

void mySoap(int &x,int &y)
{
    int temp=x;
    x=y;
    y=temp;
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        mySoap(a,b);
        cout<<a<<" "<<b<<endl;
    }
    return 0;
}

用引用更好。指针操作繁琐,容易出错。

6.13

后者似乎应该是void f(T&)

前者声明了一个参数为int的函数,后者声明了一个参数为int&的函数。

6.14

 略

6.15

s是引用是为了避免拷贝,但是它是引用意味着可以修改它,所以加上const来防止修改

occurs是要作为一个返回值的,即在函数体内要修改它最后返回给主函数,所以是引用。

c其实无所谓,这里并不修改c。

如果s是普通引用可以误改了它。occurs是常量引用将不能该值,无法实现该函数功能。

6.16

如果s是常量引用,将无法使用该函数。

6.17

bool judge(const string &s)
{
    for(auto c:s)
        if(isupper(c))
        return true;
    return false;
}
int main()
{
   string s;
   while(cin>>s)
    cout<<judge(s)<<endl;
    return 0;
}
void solve(string &s)
{
    for(auto &c:s)
        c=tolower(c);
}
int main()
{
    string s;
    while(cin>>s)
    {
        solve(s);
        cout<<s<<endl;
    }
    return 0;
}

前者参数定义为const string&,后者为string&。

6.18

bool compare(Matrix&,Matrix&);
vector<int>::iterator change_val(int, vector<int>::iterator);

前者用来比较两个对象,后者用来改变对象。

6.19

(a)不合法。参数个数不匹配。

(b)合法。

(c)匹配。int隐式转double。

(d)合法。double隐式转int。

6.20

在函数体内不对形参做改变的时候可以用常量引用,推荐用常量引用。

可能会误操作修改了形参导致修改了实参。

6.21

int compare(int a,int *b)
{
    if(a>*b) return a;
    else return *b;
}
int main()
{
    int a,b;
    while(cin>>a>>b)
        cout<<compare(a,&b)<<endl;
    return 0;
}

指针类型是int*

6.22

void mySwap(int **a,int **b)
{
    int *temp=*a;
    *a=*b;
    *b=temp;
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        int *px=&a,*py=&b;
        cout<<&*px<<" "<<&*py<<endl;
        mySwap(&px,&py);
        cout<<&*px<<" "<<&*py<<endl;
    }
    return 0;
}

由于这里交换的是指针,所以应该定义指向指针的指针。

6.23

这个题有多种方式。

下面这种是用传int*指针的。

void myPrint(int *ii,int *jj,int n)
{
    cin>>*ii;
    for(int i=0; i<n; ++i)
        cin>>jj[i];
}
int main()
{
    int n=2;
    int i,j[2];
    myPrint(&i,j,n);
    cout<<i<<endl;
    for(auto c:j)
        cout<<c<<endl;
    return 0;
}

修改单个元素还可以直接传它的引用。

修改数组还可以像标准库那样传一个首尾迭代器,或者传一个指向j数组的引用。

6.24

这个函数是有问题的。

它传入的并不是一个大小为10的int数组,而是一个指向int数组首地址的指针,后面的10是没有意义的。

一个大小为5的int数组同样可以被该函数调用,但是下面的输出就会有错。

void myPrint(const int ia[10])
{
    for(int i=0;i!=10;++i)
        cout<<ia[i]<<endl;
}
int main()
{
    int a[5]={0,1,2,3,4};
    myPrint(a);
    return 0;
}

6.25、6.26

不懂,暂略

6.27

int getSum(initializer_list<int> lst)
{
    int s=0;
    for(auto i:lst)
        s+=i;
    return s;
}
int main()
{
    cout<<getSum({1,2,4})<<endl;
    return 0;
}

initializer_list不支持下标访问,可以通过迭代器访问。它的值是常量,不可被修改。

6.28

常量string引用

6.29

减少无谓的拷贝操作,另外auto将不保留顶层const,用引用可以保证是常量。

6.30

C:\Users\Administrator\Desktop\C++_code\a.cpp|7|error: return-statement with no value, in function returning ‘bool‘ [-fpermissive]|

 如果不写returned语句却不会报错。

6.31

如果引用了一个局部变量,返回后将无效

?第二个不懂

6.32

个人觉得是正确的。将数组每个值置成它的下标值。

6.33

void out(int cur,vector<int> v)
{
    if(cur>=v.size()) return ;
    cout<<v[cur]<<endl;
    out(cur+1,v);
}
int main()
{
    vector<int> vec{123,3,1,0,5};
    out(0,vec);
    return 0;
}

形参处似乎是不能写auto的。也的确,这样就没法匹配函数了。

6.34

如果传入的参数是负数,将导致无限递归

6.35

val--返回的是val,将导致无限递归

6.36

string (&f()) [];

6.37

typedef string  Str[10];
Str& f();

auto f() ->string (&)[10];

6.38

int odd[]={1,3,5,7,9};
int even[]={0,2,4,6,8};
decltype(odd)& arrPtr(int i)
{
    return (i%2)?odd:even;
}

6.39

(a)重复定义。这里会发生二义性调用。

(b)不正确,二义性调用。

(c)正确。函数重载。

6.40

(b)是错误的。一个某个形参有了默认实参,那么位于该形参右边所有的形参都应该有默认实参。

6.41

(a)错误。形参ht缺少实参来初始化。

(b)完全正确。

(c)虽然合法但是与设计初衷不合。这里ht=14,wd=‘*‘,bckgrnd=‘ ‘,显然是将‘*‘赋给了int变量,不是设计的初衷。

6.42

 

string make_plural(int ctr,const string &word,const string &ending="s")
{
    return (ctr>1)?word+ending:word;
}

6.43

(a)常定义在头文件中

6.44

inline bool isShorter(const string &s1,const string &s2)
{
    return s1.size()<s2.size();
}

6.45

规模小、流程直接、频繁调用的、非递归的函数可以用内联函数。

6.46

不能。

C:\Users\Administrator\Desktop\C++_code\a.cpp|9|error: call to non-constexpr function ‘std::basic_string<_CharT, _Traits, _Alloc>::size_type std::basic_string<_CharT, _Traits, _Alloc>::size() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_CharT, _Traits, _Alloc>::size_type = unsigned int]‘|

6.47、6.48

暂略

6.49

函数匹配第一步,选定本次调用对应的重载函数集,集合中的函数称为候选函数。候选函数有两个特征:与被调用函数同名,声明在调用点可见

第二步考察本次调用提供的实参,从候选函数中选出能被这组实参调用的函数,这些新选出的函数也有两个特征。可行函数有两个特征:形参数量与本次调用提供的实参数量相等,每个实参类型与形参类型对应相同或者能够转化成形参类型。

6.50

(a)二义性

(b)void f(int);

(c)void f(int,int);

(d)void f(double,double);

6.51

using namespace std;
void f()
{
    cout<<"无参"<<endl;
}
void f(int a)
{
    cout<<a<<" 有一个int参数!"<<endl;
}
void f(int a,int b)
{
    cout<<a<<" "<<b<<" 有两个int参数!"<<endl;
}
void f(double a,double b)
{
    cout<<a<<" "<<b<<" 有两个double参数!"<<endl;
}
int main()
{
    //f(2.56,42);
    f(42);
    f(42,0);
    f(2.56,3.14);
    return 0;
}

6.52

(a)char转int,3类型提升。

(b)隐式转换

6.53

(a)合法

(b)合法

(c)不合法

顶层const不能区分两个函数,底层const可以区分两个函数

6.54

int func(int,int)
{

}
int main()
{
    vector<int(*)(int,int)> vec{func};
    return 0;
}

6.55

int add(int a,int b)
{
    return a+b;
}
int sub(int a,int b)
{
    return a-b;
}
int multi(int a,int b)
{
    return a*b;
}
int divide(int a,int b)
{
    return a/b;
}
int main()
{
    vector<int(*)(int,int)> vec{add,sub,multi,divide};
    return 0;
}

6.56

int add(int a,int b)
{
    return a+b;
}
int sub(int a,int b)
{
    return a-b;
}
int multi(int a,int b)
{
    return a*b;
}
int divide(int a,int b)
{
    return a/b;
}
int main()
{
    vector<int(*)(int,int)> vec{add,sub,multi,divide};
    cout<<vec[0](1,5)<<endl;
    cout<<vec[1](11,5)<<endl;
    cout<<vec[2](5,5)<<endl;
    cout<<vec[3](20,5)<<endl;
    return 0;
}

输出

6
6
25
4

 

《C++primer》v5 第6章 函数 读书笔记 习题答案

标签:des   style   blog   http   color   os   使用   io   文件   

原文地址:http://www.cnblogs.com/kkkwjx/p/3930664.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!