C++ primer(第五版)第2章习题答案

时间:2022-10-13 00:14:25

第二章 变量和基本类型

2.1

short和int至少16比特,long至少32比特,long long至少64比特。

带符号类型可以表示正数、负数或0,无符号类型仅能表示大于等于0的值。

float有7个有效位,double有16个有效位。


2.2

使用double或者float


2.3

32 4294967264 32 -32 0 0


2.4

C++ primer(第五版)第2章习题答案


2.5

(a)字符字面值 宽字符字面值 字符串字面值 宽字符串字面值

 单引号是字符字面值,双引号是字符串字面值,L是前缀,含义是宽字符。

(b)十进制字面值 无符号十进制字面值 长整型十进制字面值 无符号长整型十进制字面值 八进制字面值 十六进制字面值

没有u后缀含义是带符号的类型,以0开头的整数代表八进制,以0x,0X开头代表十六进制数。

(c)双精度浮点型字面值 单精度浮点型字面值 扩展精度浮点型字面值

注意默认的浮点型字面值是一个double.

(d)十进制字面值 无符号十进制字面值 双精度浮点型字面值 双精度浮点型字面值


2.6

第一行整数是十进制的,第二行是八进制的,八进制中没有数字9,是无效的。


2.7

(a) Fergus?\n  查表ASCII 字符串字面值

(b) 31.4 e为底数是10的指数 扩展精度浮点型字面值

(c) 1024 单精度浮点型字面值常量

(d) 3.14 扩展精度浮点型字面值


2.8

#include <iostream>

int main()
{
    std::cout << "\062\115\012";
    std::cout << "\062\t\115\012";
    return 0;
}


2.9

(a)输入运算符是从左侧运算对象所指定的输入流读取数据,存入右侧运算对象,相当于赋值,然而赋值不是初始化,该值将不被初始化,是未定义的。

int input_value = 0;
std::cin >> input_value;

(b)使用列表初始化int变量时,初始值存在丢失信息的风险

double i = { 3.14 };

(c) wage变量没有被定义,变量定义的形式是在类型说明符后紧跟多个变量名时,以逗号分隔,以分号结束。

double wage;
double salary = wage = 9999.99;

(d)把一个浮点数赋给整数类型时,会进行近似处理,结果值将仅保留浮点数中小数点之前的部分。

double i = 3.14;


2.10

global_str与global_int是函数体之外的变量,前者会默认初始化为空串,后者为0;local_int和local_str在函数体内部将不被初始化,前者的值是未定义的,但后者在std中可以无须显式初始化而定义对象,是一个空串。


2.11

(a)定义 (b)定义 (c)声明


2.12

(a) 非法,double是关键字,不能被用作标识符;

(b)可以;

(c)非法,由数字下划线字母组成,“-”不属于其中;

(d)非法,不能以数字开头;

(e)可以。


2.13

j=100; 局部变量会覆盖全局变量


2.14

100 45 在for语句中定义的i只能在for语句中访问。


2.15

(a) 合法,不过会类型转换。

(b)不合法,引用类型的初始值必须是一个对象。

(c)合法。

(d)不合法,引用必须被初始化。


2.16

都合法,第一个d的值为3.14159,其他的都会发生类型转换。


2.17

10 10 为引用ri赋值,是把值赋给了与引用绑定的i


2.18

int a = 0, b = 1;
int *p1 = &a, *p2 = p1;

// change the value of a pointer.
p1 = &b;
// change the value to which the pointer points
*p2 = b;


2.19

指针是指向另外一种类型的复合类型,引用是一个已经存在的对象的别名。

区别:

(1) 引用是已经存在对象的别名,指针本身就是一个对象。

(2) 初始化变量时,引用和它的初始值绑定在一起,没有方法使得引用重新绑定到另一个对象,因此引用必须初始化,而指针可以被赋值和拷贝。

(3)引用总是得到最初绑定的初始值,而在指针的生命周期中可以指向不同的对象。

(4)引用必须初始化,指针在定义时可以不初始化。(建议初始化所有指针)


2.20

把i的值改为1764(42×42)。


2.21

(a)非法,除了两种例外情况,其他所有指针类型都要和它所指向的对象严格匹配。

(b)非法,指针存放某个对象的地址,要想获得该地址,需要使用取地址符。

(c)合法。


2.22

if (p)     // p是否为空指针

if(*p)    // p所指向对象的值是否为0


2.23

需要更多的消息判断指针是否有效。


2.24

指针类型必须匹配,其中void是一种特殊的指针类型,可用于存放任意对象的地址。


2.25

(a) ip是指向int的指针,i是int,r是i的引用。

(b) i是int, ip是一个空指针。

(c) ip是一个int型指针,ip2是一个int型变量。


2.26

(a)不合法,const对象一旦创建其值就不能改变,所以const对象必须初始化。

(b)合法。

(c)合法,可以在运行时初始化。

(d)不合法,sz不可以改变。


2.27

(a)不合法,引用要绑定在对象上。

(b)合法,将一个常量指针初始化为i2的地址。

(c)合法,i是一个常量,r是一个常量引用。

(d)合法,将一个指向常量的常量指针p3初始化为i2的地址。

(e)合法,将一个指向常量的指针初始化为i2的地址。

(f)不合法,使用不当,指针是对象而引用不是,允许把指针本身定为常量,不允许把引用r2本身定位常量。

(g)合法,給一个常量i2和常量引用r初始化为i。


2.28

(a)不合法,常量指针cp没有初始化。

(b)不合法, 常量指针p2没有初始化。

(c)不合法,常量ic没有初始化。

(d)不合法,常量指针p3没有初始化。

(e)合法,p是一个指向常量的指针。


2.29

(a)合法,拷贝常量ic的值并不会改变它的值。

(b)不合法,类型不同,无法赋值。p1是普通指针,会改变其所指向的值。

(c)不合法,p1是普通指针,会改变其所指向的值。

(d)不合法,p3是常量指针,一旦初始化完成,它的值就不能改变了。

(e)不合法,p2是常量,不能再被赋值。

(f)不合法, ic是个常量,不能再被赋值。


2.30

v2是顶层,p2是底层,p3靠右是顶层,靠左是底层,r2是底层。


2.31

(1)合法。拷贝顶层v2的值,并不会改变其值,没什么影响。

(2)不合法。p2是底层const,而p1不是。否则可以通过p1来改变它指向对象的值。

(3)合法。允许令一个指向常量的指针指向一个非常量对象。

(4)不合法。p3有一个底层const,而p1没有。

(5)合法。这两个指针都是底层const。


2.32

不合法。P49,不能把int变量直接赋值給指针。

(1)int *p = &null; 指针指向null

(2)const int *p = nullptr;  不允许修改指针指向地址的内容。

(3)constexpr int *p = nullptr; p是一个指向整数的常量指针,其值为空。


2.33

a = 42; //把42赋值给整型数a

b = 42; //把42赋值给整型数b

c = 42; //把42赋值给整型数c

d =42; //错误,d是一个整型指针,更正:*d = 42

e = 42; //错误,e是一个指向整型常量的指针,更正:e = &a;

g = 42; //错误, g是一个整型常量引用,已经与ci绑定,不能修改。


2.34

#include <iostream>

int main()
{
    int i = 0, &r = i;
    auto a = r; // a is an int (r is an alias for i, which has type int)

    const int ci = i, &cr = ci;
    auto b = ci; // b is an int (top-level const in ci is dropped)
    auto c = cr; // c is an int (cr is an alias for ci whose const is top-level)
    auto d = &i; // d is an int* (& ofan int objectis int*)
    auto e = &ci; // e is const int*(& of a const object is low-level const)

    const auto f = ci; // deduced type of ci is int; f has type const int
    auto& g = ci;      // g is a const int& that is bound to ci

    a = 42;
    b = 42;
    c = 42;
    *d = 42;
    e = &a;

    return 0;
}

2.35

i是整数常量,j是整数,k是一个整型常量引用,p是一个指向整型常量的指针,j2是整型常量,k2是整型常量引用。

#include <iostream>
#include <typeinfo>

int main() {
  const int i = 42;
  auto j = i;
  const auto &k = i;
  auto *p = &i;
  const auto j2 = i, &k2 = i;

  std::cout << "i  is " << typeid(i).name() << "\n";
  std::cout << "j  is " << typeid(j).name() << "\n";
  std::cout << "k  is " << typeid(k).name() << "\n";
  std::cout << "p  is " << typeid(p).name() << "\n";
  std::cout << "j2 is " << typeid(j2).name() << "\n";
  std::cout << "k2 is " << typeid(k2).name() << "\n";

  std::cout << std::endl;
  std::cout << std::boolalpha;

  std::cout << "i and j  have same type? "
            << std::is_same<decltype(i), decltype(j)>::value << "\n";
  std::cout << "i and k  have same type? "
            << std::is_same<decltype(i), decltype(k)>::value << "\n";
  std::cout << "i and j2 have same type? "
            << std::is_same<decltype(i), decltype(j2)>::value << "\n";
  std::cout << "j and j2 have same type? "
            << std::is_same<decltype(j), decltype(j2)>::value << "\n";
  std::cout << "k and k2 have same type? "
            << std::is_same<decltype(k), decltype(k2)>::value << "\n";

  return 0;
}

2.36

c是整型,d是一个整型引用,与a绑定。c,d的值都是4。


2.37

a,b,c是整型,d是整型引用,a,c,d都是3,b是4。


2.38

在处理顶层const和引用的方式上有不同,decltype返回变量的类型包括顶层const和引用在内。

int i = 0, &r = i;
// same
auto a = i;
decltype(i) b = i;
// different
auto c = r; //c是一个整数
decltype(r) d = i; //d是一个整型引用


2.39

C++ primer(第五版)第2章习题答案


2.40

struct Sale_data {
    std::string bookNo;
    std::string bookName;
    unsigned units_sold = 0;
    double revenue = 0.0;
    double price = 0.0;
    //...
};

2.41

1.51

#include <iostream>
#include <string>

struct Sale_data {
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main()
{
    Sale_data book;
    double price;
    std::cin >> book.bookNo >> book.units_sold >> price;
    book.revenue = book.units_sold * price;
    std::cout << book.bookNo << " " << book.units_sold << " " << book.revenue << " " << price;

    return 0;
}

1.52

#include <iostream>
#include <string>

struct Sale_data {
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main()
{
    Sale_data book1, book2;
    double price1, price2;
    std::cin >> book1.bookNo >> book1.units_sold >> price1;
    std::cin >> book2.bookNo >> book2.units_sold >> price2;
    book1.revenue = book1.units_sold * price1;
    book2.revenue = book2.units_sold * price2;

    if (book1.bookNo == book2.bookNo) {
        unsigned totalCnt = book1.units_sold + book2.units_sold;
        double totalRevenue = book1.revenue + book2.revenue;
        std::cout << book1.bookNo << " " << totalCnt << " " << totalRevenue << " ";
        if (totalCnt != 0)
            std::cout << totalRevenue / totalCnt << std::endl;
        else
            std::cout << "(no sales)" << std::endl;

        return 0;
    }
    else {
        std::cerr << "Data must refer to same ISBN" << std::endl;
        return -1;  // indicate failure
    }
}

1.6

#include <iostream>
#include <string>

struct Sale_data {
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main()
{
    Sale_data total;
    double totalPrice;
    if (std::cin >> total.bookNo >> total.units_sold >> totalPrice) {
        total.revenue = total.units_sold * totalPrice;

        Sale_data trans;
        double transPrice;
        while (std::cin >> trans.bookNo >> trans.units_sold >> transPrice) {
            trans.revenue = trans.units_sold * transPrice;

            if (total.bookNo == trans.bookNo) {
                total.units_sold += trans.units_sold;
                total.revenue += trans.revenue;
            }
            else {
                std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
                if (total.units_sold != 0)
                    std::cout << total.revenue / total.units_sold << std::endl;
                else
                    std::cout << "(no sales)" << std::endl;

                total.bookNo = trans.bookNo;
                total.units_sold = trans.units_sold;
                total.revenue = trans.revenue;
            }
        }

        std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
        if (total.units_sold != 0)
            std::cout << total.revenue / total.units_sold << std::endl;
        else
            std::cout << "(no sales)" << std::endl;

        return 0;
    }
    else {
        std::cerr << "No data?!" << std::endl;
        return -1;  // indicate failure
    }
}

2.42

ex2_42_sales_data.h

#include <iostream>
#include <string>

// own Sales_data
struct Sales_data {
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;

    void CalcRevenue(double price);
    double CalcAveragePrice();
    void SetData(Sales_data data);
    void AddData(Sales_data data);
    void Print();
};

void Sales_data::CalcRevenue(double price)
{
    revenue = units_sold * price;
}

void Sales_data::SetData(Sales_data data)
{
    bookNo = data.bookNo;
    units_sold = data.units_sold;
    revenue = data.revenue;
}

void Sales_data::AddData(Sales_data data)
{
    if (bookNo != data.bookNo) return;
    units_sold += data.units_sold;
    revenue += data.revenue;
}

double Sales_data::CalcAveragePrice()
{
    if (units_sold != 0)
        return revenue / units_sold;
    else
        return 0.0;
}

void Sales_data::Print()
{
    std::cout << bookNo << " " << units_sold << " " << revenue << " ";
    double averagePrice = CalcAveragePrice();
    if (averagePrice != 0.0)
        std::cout << averagePrice << std::endl;
    else
        std::cout << "(no sales)" << std::endl;
}

ex2_42_1.cpp

#include <iostream>

#include "ex2_42_sales_data.h"

int main()
{
    Sales_data book;
    double price;
    std::cin >> book.bookNo >> book.units_sold >> price;
    book.CalcRevenue(price);
    book.Print();

    return 0;
}

ex2_42_2.cpp

#include <iostream>

#include "ex2_42_sales_data.h"

int main()
{
    Sales_data book1, book2;
    double price1, price2;
    std::cin >> book1.bookNo >> book1.units_sold >> price1;
    std::cin >> book2.bookNo >> book2.units_sold >> price2;
    book1.CalcRevenue(price1);
    book2.CalcRevenue(price2);

    if (book1.bookNo == book2.bookNo) {
        book1.AddData(book2);
        book1.Print();

        return 0;
    }
    else {
        std::cerr << "Data must refer to same ISBN" << std::endl;
        return -1; // indicate failure
    }
}

ex2_42_3.cpp

#include <iostream>

#include "ex2_42_sales_data.h"

int main()
{
    Sales_data total;
    double totalPrice;
    if (std::cin >> total.bookNo >> total.units_sold >> totalPrice) {
        total.CalcRevenue(totalPrice);

        Sales_data trans;
        double transPrice;
        while (std::cin >> trans.bookNo >> trans.units_sold >> transPrice) {
            trans.CalcRevenue(transPrice);

            if (total.bookNo == trans.bookNo) {
                total.AddData(trans);
            }
            else {
                total.Print();
                total.SetData(trans);
            }
        }

        total.Print();

        return 0;
    }
    else {
        std::cerr << "No data?!" << std::endl;
        return -1; // indicate failure
    }
}