⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 习题5.18 .txt

📁 c++ primer 答案(第4版) 自己整理的 只有1-5章
💻 TXT
字号:
习题5.18 

编写程序定义一个vector对象,其每个元素都是指向string类型的指针,读取该vector对象,输出每个string的内容及其相应的长度。

【解答】

//定义一个vector对象,其每个元素都是指向string类型的指针,

//读取该vector对象,输出每个string的内容及其相应的长度

#include <iostream>

#include <string>

#include <vector>

using namespace std;

int main()

{

    vector<string*> spvec;

    //读取vector对象

    string str;

    cout << "Enter some strings(Ctrl+Z to end)" << endl;

    while (cin >> str) {

        string *pstr = new string; //指向string对象的指针

        *pstr = str;

        spvec.push_back(pstr);

    }

    //输出每个string的内容及其相应的长度

    vector<string*>::iterator iter = spvec.begin();

    while (iter != spvec.end()) {

        cout << **iter << (**iter).size() << endl;

        iter++;

    }

    //释放各个动态分配的string对象

    iter = spvec.begin();

    while (iter != spvec.end()) {

        delete *iter;

        iter++;

    }

    return 0;

}

习题5.19 

假设iter为vector<string>::iterator类型的变量,指出下面哪些表达式是合法的,并解释这些合法表达式的行为。

(a) *iter++;             (b) (*iter)++;

(c) *iter.empty();   (d) iter->empty();

(e) ++*iter;         (f) iter++->empty();

【解答】

(a)、(d)、(f)合法。

这些表达式的执行结果如下:

(a)返回iter所指向的string对象,并使iter加1。

(d)调用iter所指向的string对象的成员函数empty。

(f)调用iter所指向的string对象的成员函数empty,并使iter加1。

习题5.20 

编写程序提示用户输入两个数,然后报告哪个数比较小。

【解答】

可编写程序如下:

//提示用户输入两个数,然后报告哪个数比较小

#include <iostream>

using namespace std;

int main()

{

    int val1, val2;

    //提示用户输入两个数并接受输入

    cout << "Enter two integers:" << endl;

    cin >> val1 >> val2;

    //报告哪个数比较小

    cout << "The smaller one is" 

         << (val1 < val2 ? val1 : val2) << endl;

    return 0;

}

习题5.21 

编写程序处理vector<int>对象的元素:将每个奇数值元素用该值的两倍替换。

【解答】

//处理vector<int>对象的元素:

//将每个奇数值元素用该值的两倍替换

#include <iostream>

#include <vector>

using namespace std;

int main()

{

    vector<int> ivec(20,1);//ivec包含20个值为1的元素

    //将每个奇数值元素用该值的两倍替换

    for (vector<int>::iterator iter = ivec.begin();

         iter != ivec.end(); ++iter)

        *iter = (*iter % 2 == 0 ? *iter : *iter * 2);

    return 0;

}

习题5.22 

编写程序输出每种内置类型的长度。

【解答】

//输出每种内置类型的长度

#include <iostream>

using namespace std;

int main()

{

    cout << "type\t\t\t" << "size" << endl

         << "bool\t\t\t" << sizeof(bool) << endl

         << "char\t\t\t" << sizeof(char) << endl

         << "signed char\t\t" << sizeof(signed char) << endl

         << "unsigned char\t\t" << sizeof(unsigned char) << endl

         << "wchar_t\t\t\t" << sizeof(wchar_t) << endl

         << "short\t\t\t" << sizeof(short) << endl

         << "signed short\t\t" << sizeof(signed short) << endl

         << "unsigned short\t\t" << sizeof(unsigned short) << endl

         << "int\t\t\t" << sizeof(int) << endl

         << "signed int\t\t" << sizeof(signed int) << endl

         << "unsigend int\t\t" << sizeof(unsigned int) << endl

         << "long\t\t\t" << sizeof(long) << endl

         << "sigend long\t\t" << sizeof(signed long) << endl

         << "unsigned long\t\t" << sizeof(unsigned long) << endl

         << "float\t\t\t" << sizeof(float) << endl

         << "double\t\t\t" << sizeof(double) << endl

         << "long double\t\t" << sizeof(long double) << endl;

    return 0;

}

习题5.23 

预测下列程序的输出,并解释你的理由。然后运行该程序,输出的结果和你预测的一样吗?如果不一样,为什么?

int x[10]; int *p = x;

cout << sizeof(x)/sizeof(*x) << endl;

cout << sizeof(p)/sizeof(*p) << endl;

【解答】

在表达式sizeof(x)中,x是数组名,该表达式的结果为数组x所占据的存储空间的字节数,为10个int型元素所占据的字节数。

表达式sizeof(*x)的结果是指针常量x所指向的对象(数组中第一个int型元素)所占据的存储空间的字节数。

表达式sizeof(p)的结果是指针变量p所占据的存储空间的字节数。

表达式sizeof(*p)的结果是指针变量p所指向的对象(一个int型数据)所占据的存储空间的字节数。

各种数据类型在不同的系统中所占据的字节数不一定相同,因此在不同的系统中运行上述程序段得到的结果不一定相同。在Microsoft Visual C++ .NET 2003系统中,一个int型数据占据4个字节,一个指针型数据也占据4个字节,因此运行上述程序得到的输出结果为:

10

1

习题5.24 

本节的程序与5.5节在vector对象中添加元素的程序类似。两段程序都使用递减的计数器生成元素的值。本程序中,我们使用了前自减操作,而5.5节的程序则使用了后自减操作。解释为什么一段程序中使用前自减操作而在另一段程序中使用后自减操作。

【解答】

5.5节的程序中必须使用后自减操作。如果使用前自减操作,则是用减1后的cnt值创建ivec的新元素,添加到ivec中的元素将不是10~1,而是9~0。

本节的程序中使用后自减操作或前自减操作均可,因为对cnt的自减操作和对cnt值的使用不是出现在同一表达式中,cnt自减操作的前置或后置形式不影响对cnt值的使用。

习题5.25 

根据表5-4的内容,在下列表达式中添加圆括号说明其操作数分组的顺序(即计算顺序):

(a) ! ptr == ptr->next

(b) ch = buf[ bp++ ] != '\n'

【解答】

添加圆括号说明其计算顺序如下:

(a) ((! ptr) == (ptr->next))

(b) (ch = ((buf[ (bp++) ]) != '\n'))

习题5.26 

习题5.25中的表达式的计算次序与你的意图不同,给它们加上圆括号使其以你所希望的操作次序求解。

【解答】

添加圆括号获得与上题不同的操作次序如下:

(a) ! (ptr == ptr->next)

(b) (ch = buf[ bp++ ]) != '\n'

习题5.27 

由于操作符优先级的问题,下列表达式编译失败。请参照表5-4解释原因,应该如何改正?

string s = "word";

// add an 's' to the end, if the word doesn't already end in 's'

string pl = s + s[s.size() - 1] == 's' ? "" : "s" ;

【解答】

由表5-4可知,在语句string pl = s + s[s.size() - 1] == 's' ? "" : "s" ;中,赋值、加法、条件操作符三者的操作次序为:先执行“+”操作,再用表达式s + s[s.size() - 1]的结果参与条件操作,最后将条件操作的结果赋给pl。但表达式s + s[s.size() - 1]的结果是一个string对象,不能与字符's'进行相等比较,所以编译失败。

改正为:string pl = s + (s[s.size() - 1] == 's' ? "" : "s") ;。

习题5.28 

除了逻辑与和逻辑或外,C++没有明确定义二元操作符的求解次序,编译器可自由地提供最佳的实现方式。只能在“实现效率”和程序语言使用中“潜在的缺陷”之间寻求平衡。你认为这可以接受吗?说出你的理由。

【解答】

这可以接受。

因为,操作数的求解次序通常对结果没什么影响。只有当二元操作符的两个操作数涉及同一对象,并改变该对象的值时,操作数的求解次序才会影响计算结果;后一种情况只会在部分(甚至是少数)程序中出现。在实际使用中,这种“潜在的缺陷”可以通过程序员的努力得到弥补,但“实现效率”的提高却能使所有使用该编译器的程序受益,因此利大于弊。

习题5.29 

假设ptr指向类类型对象,该类拥有一个名为ival的int型数据成员,vec是保存int型元素的vector对象,而ival、jval和kval都是int型变量。请解释下列表达式的行为,并指出哪些(如果有的话)可能是不正确的,为什么?如何改正?

(a) ptr->ival != 0           (b) ival != jval < kval

(c) ptr != 0 && *ptr++       (d) ival++ && ival

(e) vec[ival++] <= vec[ival]

【解答】

表达式的行为如下:

(a) 判断ptr所指向的对象的ival成员是否不等于0。

(b) 判断ival是否不等于“jval是否小于kval”的判断结果,即判断ival是否不等于true(1)或false(0)。

(c) 判断ptr是否不等于0。如果ptr不等于0,则求解&&操作的右操作数,即,ptr加1,且判断ptr原来所指向的对象是否为0。

(d) 判断ival及ival+1是否为true(非0值)(注意,如果ival为false,则无需继续判断ival+1)。

(e) 判断vec[ival]是否小于或等于vec[ival+1]。

其中,(d)和(e)可能不正确,因为二元操作符的两个操作数涉及同一对象,并改变该对象的值。

可改正如下:

(d) ival && ival + 1

(e) vec[ival] <= vec[ival + 1]

习题5.30 

下列语句哪些(如果有的话)是非法的或错误的?

(a) vector<string> svec(10);

(b) vector<string> *pvec1 = new vector<string>(10);

(c) vector<string> **pvec2 = new vector<string>[10];

(d) vector<string> *pv1 = &svec;

(e) vector<string> *pv2 = pvec1;

(f) delete svec;

(g) delete pvec1;

(h) delete [] pvec2;

(i) delete pv1;

(j) delete pv2;

【解答】

错误的有(c)和(f)。

(c)的错误在于:pvec2是指向元素类型为string的vector对象的指针的指针(即pvec2的类型为vector<string> **),而new操作返回的是一个指向元素类型为string的vector对象的指针,不能用于初始化pvec2。

(f)的错误在于:svec是一个vector对象,不是指针,不能对它进行delete操作。

习题5.31 

根据5.12.2节的变量定义,解释在计算下列表达式的过程中发生了什么类型转换?

(a) if (fval)

(b) dval = fval + ival;

(c) dval + ival + cval;

记住,你可能需要考虑操作符的结合性,以便在表达式含有多个操作符的情况下确定答案。

【解答】

(a) 将fval的值从float类型转换为bool类型。

(b) 将ival的值从int类型转换为float类型,再将fval + ival的结果值转换为double类型,赋给dval。

(c) 将ival的值从int类型转换为double类型,cval的值首先提升为int类型,然后从int型转换为double型,与dval + ival的结果值相加。

习题5.32 

给定下列定义:

char cval; int ival; unsigned int ui;

float fval; double dval;

指出可能发生的(如果有的话)隐式类型转换:

(a) cval = 'a' + 3;      (b) fval = ui – ival * 1.0;

(c) dval = ui * fval;        (d) cval = ival + fval + dval;

【解答】

(a) 'a'首先提升为int类型,再将'a' + 3的结果值转换为char型,赋给cval。

(b) ival转换为double型与1.0相乘,ui转换为double型再减去ival * 1.0的结果值,减操作的结果转换为float型,赋给fval。

(c) ui转换为float型与fval相乘,结果转换为double型,赋给dval。

(d) ival转换为float型与fval相加,结果转换为double型,再与dval相加,结果转换为char型,赋给cval。

习题5.33 

给定下列定义:

int ival; double dval;

const string *ps; char *pc; void *pv;

用命名的强制类型转换符号重写下列语句:

(a) pv = (void*)ps;      (b) ival = int(*pc);

(c) pv = &dval;          (d) pc = (char*) pv;

【解答】

(a) pv = static_cast<void*> (const_cast<string*> (ps));      

(b) ival = static_cast<int> (*pc);

(c) pv = static_cast<void*> (&dval);         

(d) pc = static_cast<char*> (pv);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -