c++primer 第2章 练习题答案 (尚未完善 陆续补充中 基本上已经完成)

short int 2个字节

int 2/4字节

long 4/8字节

long long 8字节

其实这个吧 意义不是太大 基本上现在大多数都32/64位机器 所以int基本上最小就都4个字节了  而且还和操作系统受限有关系 winodws linux 32位 64位 所以啊 就忽略吧  无符号就是都是正数 最高位在二进制里1不代表负 而是代表正的 该是几是几  

上面是我的白话 下面是GitHub上 大神给的答案 

C++ guarantees short and int is at least 16 bits, long at least 32 bits, long long at least 64 bits.

The signed can represent positive numbers, negative numbers and zero, while unsigned can only represent numbers no less than zero.

The C and C++ standards do not specify the representation of float, double and long double. It is possible that all three implemented as IEEE double-precision. Nevertheless, for most architectures (gcc, MSVC; x86, x64, ARM) float is indeed a IEEE single-precision floating point number (binary32), and double is a IEEE double-precision floating point number (binary64).

Usage:

Use int for integer arithmetic. short is usually too small and, in practice,long often has the same size as int. If your data values are larger than the minimum guaranteed size of an int, then use long long. (In a word: short < int < long < long long)

Use an unsigned type when you know that the values cannot be negative. (In a word: no negative, unsigned.)

Use double for floating-point computations; float usually does not have enough precision, and the cost of double-precision calculations versus single-precision is negligible. In fact, on some machines, double-precision operations are faster than single. The precision offered by long double usually is unnecessary and often entails considerable run-time cost. (In a word: float < double < long double)

Reference:

What are the criteria for choosing between short / int / long data types?
Difference between float and double
Advice: Deciding which Type to Use(This book.)

c++保证短,int至少是16位,长至少32位,长至少64位。
符号可以表示正数、负数和零,而无符号只能表示不小于零的数字。
C和c++标准没有指定float、double和long double的表示形式。这三种方法都可以实现为IEEE双精度。然而,对于大多数体系结构(gcc、MSVC;x86、x64、ARM) float确实是IEEE单精度浮点数(binary32), double是IEEE双精度浮点数(binary64)。
用法:
整数运算使用整型数。short通常太小,实际上long的大小与int相同,如果您的数据值大于int的最小保证值,那么使用long long。(一句话:短< int < long < long long)
当您知道值不能为负数时,使用无符号类型。(一句话:没有否定,没有符号。)
浮点运算使用双精度浮点运算;浮点数通常没有足够的精度,双精度计算与单精度计算的成本可以忽略不计。事实上,在某些机器上,双精度操作比单精度操作要快。long double提供的精度通常是不必要的,并且通常需要相当大的运行时成本。(一句话:浮动< double < long double)
参考:
选择短/ int /长数据类型的标准是什么?
浮点数和双精度数的区别
建议:决定使用哪一种(这本书)。

上面那个中文翻译是 有道词典的 感谢有道词典 打个广告。。。

2.2 按照上面说的 单精度和双精度的损耗 可以忽略不计

To calculate a mortgage payment, what types would you use for the rate, principal, and payment? Explain why you selected each type.
use double, or also float.
The rate most like that: 4.50 % per year.
The principal most like that: $854.36
The payment most like that: $1,142.36
Reference:
mortgage-calculator
What's in a Mortgage Payment?

要计算抵押贷款付款,您将使用什么类型的利率、本金和付款?解释为什么选择每种类型。
使用double或者float。
最像的是:每年4.50%。
最像这样的本金:854.36美元
最类似的付款方式是:1142.36美元
参考:
抵押计算器
什么是按揭付款?
#include<iostream>

using namespace std;

int main(){


        unsigned u = 10,u2=42;
        cout <<u2-u<<endl;
        cout <<u-u2<<endl;
        int i=10,i2=42;

        cout <<i2-i<<endl;
        cout <<i-i2<<endl;
        cout << i -u <<endl;
        cout << u - i <<endl;

        return 0;

}
~        

Determine the type of each of the following literals. Explain the differences among the literals in each of the four examples:

  • (a) 'a', L'a', "a", L"a"
  • (b) 10, 10u, 10L, 10uL, 012, 0xC*
  • (c) 3.14, 3.14f, 3.14L*
  • (d) 10, 10u, 10., 10e-2

(a): character literal, wide character literal, string literal, string wide character literal.

(b): decimal, unsigned decimal, long decimal, unsigned long decimal, octal, hexadecimal.

(c): double, float, long double.

(d): decimal, unsigned decimal, double, double.

上面参考一下github大神代码

下面是有道翻译后的结果

(a):字符文字,宽字符文字,字符串文字,字符串宽字符文字。

(b):十进制、无符号十进制、长十进制、无符号长十进制、八进制、十六进制。

(c):双,浮动,长双。

(d):十进制,无符号十进制,双,双。

记住下面这个图就好了

如果有的话,下列定义之间的区别是什么?

int month = 9, day = 7;

int month = 09, day = 07;

第一行的整数是小数。

第二行:

int month = 09无效,因为八进制没有数字9。

2.7

(a): Who goes with Fergus?(new line) "string"

(b): 31.4 "long double"

(c): 1024 "float"

(d): 3.14 "long double"

上面参考其他的答案

练习2.5 指出下述字面值的数据类型并说明每一组内几种字面值的区别:

(a) 'a', L'a', "a", L"a"
(b) 10, 10u, 10L, 10uL, 012, 0xC
(c) 3.14, 3.14f, 3.14L
(d) 10, 10u, 10., 10e-2
解答:
(a)第一个是单char字符,第二个是单wchar_t宽字符,第三个是单个字符串,在内存中存储时,末尾隐含一个'\0'空字符,第四个是单个wchar_t类型的宽字符串,在内存中存储时,末尾也隐含一个'\0'空字符。
(b)第一个是一个int整型,第二个是无符号整型,第三个是long int型,第四个是unsigned long型,第五个是八进制的int型,最后一个是16进制的int型
(c)第一个是double类型,第二个是float类型,第三个是long double类型
(d)第一个是整型,第二个是无符号整型,第三个是double类型,最后一个是double类型的科学记数法表示。
 

练习2.6 下面两组定义是否有区别,如果有,请叙述之:

int month = 9, day = 7;
int month = 09, day = 07;
解答:有区别,第一行是十进制整型,第二行是八进制整型,但是没有09这一表示。

练习2.7 下述字面值表示何种含义?它们各自的数据类型是什么?

(a) "Who goes with F\145rgus?\012"
(b) 3.14e1L
(c) 1024f
(d) 3.14L
解答:
(a)Who goes with Fergus? 换行。\145是字母‘e’,\012是换行符。这三一个字符串类型。
(b)3.14*10^1,long double类型
(c)无意义,错误
(d)3.14 long double类型

#include <iostream>
 
int main()
{
    std::cout << "\062\115\012" ;    // \062是2  \115是M  \012是换行
    std::cout << "\062\011\115\012";  // \011是制表符
    return 0;
}

2.9

(a): error: expected '(' for function-style cast or type construction.

int input_value = 0;
std::cin >> input_value;
(b): error: type 'double' cannot be narrowed to 'int' in initializer list.

double i = { 3.14 };
(c): if declared 'wage' before, it's right. Otherwise, error would be happened: error: use of undeclared identifier 'wage'

double wage;
double salary = wage = 9999.99;
(d): Ok: but value will be truncated.

double i = 3.14;

global_str是全局变量,因此值为空字符串。

global_int是全局变量,因此值为0。

local_int是一个局部变量,它不是未初始化的,因此它有一个未定义的值。

local_str也是一个局部变量,它不是未初始化的,但是它有一个由类定义的值。这是空字符串。

What are the initial values, if any, of each of the following variables?

std::string global_str;
int global_int;
int main()
{
    int local_int;
    std::string local_str;
}
global_str is global variable, so the value is empty string.
global_int is global variable, so the value is zero.
local_int is a local variable which is not uninitialized, so it has a undefined value.
local_str is also a local variable which is not uninitialized, but it has a value that is defined by the class. So it is empty string.

global_str是全局变量,因此值为空字符串。
global_int是全局变量,因此值为0。
local_int是一个局部变量,它不是未初始化的,因此它有一个未定义的值。
local_str也是一个局部变量,它不是未初始化的,但是它有一个由类定义的值。这是空字符串。

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

解答:(a)非法  (b)合法  (c)非法  (d)非法  (e)合法

j=100

2.15

(a):有效。

(b):无效的。初始化器必须是一个对象。

(c):有效。

(d):无效的。必须初始化引用。

解答:(a)合法,给d赋值3.14159

(b)合法,给d赋值0(隐含类型转换)

(c)合法,给i赋值0

(d)合法,给i赋值0

都是输出 10,10

2.19

解答:指针是一种对象,而引用不是。指针可以为空,允许不初始化,引用不可以。

1.指针和引用的定义和性质区别:

(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来

的变量实质上是同一个东西,只不过是原变量的一个别名而已。如:

int a=1;int *p=&a;

int a=1;int &b=a;

上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。

而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单

元。

(2)引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化。

(3)可以有const指针,但是没有const引用;

(4)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)

(5)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;

(6)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。

(7)”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小;

(8)指针和引用的自增(++)运算意义不一样;

(9)如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏;

就是42* 42 再赋值给i 

int i = 0;
  • (a) double* dp = &i;
  • (b) int *ip = i;
  • (c) int *p = &i;
  • (a): illegal, cannot initialize a variable of type double * with an rvalue of type int *
  • (b): illegal, cannot initialize a variable of type int * with an lvalue of type int
  • (c): legal.

(a):非法的,不能用int *类型的右值初始化类型为double *的变量

(b):非法的,不能用类型int的lvalue初始化类型int *的变量

(c):合法的。

if (p) // whether p is nullptr?
if (*p) // whether the value pointed by p is zero?

第一个,判断这个指针是否为空。第二个,判断这个指针指向的对象的值是否为0

不能知道,因为指针可以任意指向一个地址,即使有时候可能看似正确,但依然不能保证它是无害的,指针的意义就是它的值是内存地址,它将按它指向的类型的信息来解释那片空间。而那片空间是否合法,是由程序员保证,而不是指针本身。

2.24  因为p是万能型指针 void *  lp 是long型 与 i的类型 不符合

------------------------------------------------------------------------------------------------------------------

int *p1,p2; 这种声明其实不好 p1是int 型的指针 而p2 则是int 容易误解

2.25

(a) int* ip, i, &r = i;

(b) int i, *ip = 0;

(c) int *ip, ip2;

解答:

(a)ip:int型指针,值不确定; i:int整型,值不确定;r:int型引用,值不确定

(b)i:int整型,值不确定;ip:int型指针,值为空

(c)ip:int型指针,值不确定;ip2:int整型,值不确定;

(a) const int buf;

(b) int cnt =0;

(c) const int sz = cnt;

(d) ++cnt; ++sz;

解答:(a)不合法,没有初始化

(b)合法

(c)合法

(d)第一个合法,第二个不合法,因为sz是const变量,不能做自增运算

一些思考

#include <iostream>

using namespace std;

int main(){

        int i =42;

        const int &r1 = i;

        const int &r2 = 42;
        const int &r3 = r1*2;
        const int &r6 = r1;//正确
        //int &r4 = r1*2;//错误
        int &r4 = i;
        int &r5 = r4;

        const int &r7 = r5;
        //int &r7 = r1;错误

        r5=99;
        cout<<"i=" << i<<endl;
        cout<<"r5=" <<r5<<endl;
        cout<<"r1=" <<r1<<endl;
        cout<<"r2=" <<r2<<endl;

/*
i=99
r5=99
r1=99
r2=42

*/
        return 0;
}
~       

常引用 可以赋值为 普通引用  相反普通引用不可以 赋值为常引用 

练习2.27 下面哪些初始化是合法的?请说明原因。

(a) int i = -1, &r = 0;

(b) int *const p2 = &i2;

(c) const int i = -1, &r = 0;

(d) const int *const p3 = &i2;

(e) const int *p1 = &i2;

(f) const int &const r2;

(g) const int i2 = i, &r = i;

解答:(a)非法,引用r只能绑定到对象上

(b)合法

(c)合法

(d)合法

(e)合法

(f)非法,没有这种语法。

(g)合法

i, *const cp;//非法,cp必须初始化。

const int ic, &r = ic;//非法,ic必须初始化。

int *p1, *const p2;//非法,p2必须初始化。

const int *const p3;//非法,p3必须初始化。

const int * p;/ /合法。指向const int的指针。

(a) int i, *const cp;

(b) int *p1, *const p2;

(c) const int ic, &r = ic;

(d) const int *const p3;

(e) const int *p;

解答:以下答案经过调试验证,有疑惑的地方,可以自己上机调试

(a)定义一个int整型变量i,一个const int型指针,cp没有初始化,不合法。

(b)定义一个int型指针变量p1,一个const int型指针p2,p2没有初始化,不合法。

(c)定义一个const int整型变量ic,一个const int型引用rc,ic没有初始化,不合法。

(d)定义一个指向常量对象的int常量指针p3,没有初始化,不合法。

(e)定义一个指向int常量的指针变量p,合法。(注意:这里不是const常量,是变量,指向的是const而已,二者不同)

2.29

i= ic;/ /合法。

p1 = p3;/ /非法的。p3是指向const int的指针。

p1 = ic;/ /非法的。ic是一个常量。

p3 = ic;/ /非法的。p3是一个常量指针。

p2 = p1;/ /非法的。p2是常量指针。

ic = * p3;/ /非法的。ic是一个常量。

(a)合法

(b)不合法,p1指向非const,p3指向const

(c)不合法,p1指向非const,ic是const

(d)不合法,p3是const变量,不能赋值

(e)不合法,p2是const变量,不能赋值

(f)不合法,ic是const变量,不能赋值

v2是顶层const, p2是底层const。

p3:最右边的常量是顶级的,最左边的是低级的。

r2是低级常量。

r1 = v2; // legal, top-level const in v2 is ignored.
p1 = p2; // illegal, p2 has a low-level const but p1 doesn't.
p2 = p1; // legal, we can convert int* to const int*.
p1 = p3; // illegal, p3 has a low-level const but p1 doesn't.
p2 = p3; // legal, p2 has the same low-level const qualification as p3.

r1 = v2;//合法,v2中的顶级常量被忽略。
p1=p2;//非法,p2有一个低级常量,而p1没有。
p2 = p1;//合法,我们可以将int*转换为const int*。
p1 = p3;//非法,p3有一个低级常量,而p1没有。
p2 = p3;//合法的,p2与p3具有相同的低级const资格。

p1 = p2不合法,p1 = p3不合法,因为p1指向的是变量,而p2,p3指向的是常量,如果允许把p2,p3赋值到指向变量的p1,那么通过p1就能改变所指的对象,但原p2,p3并不能改变所指的常量对象。(这个解释的似乎不太好 )

参考了别人的代码和答案 我个人觉得 常量 还是按照底层或者顶层啥的 来记住比较好 

不合法,null是个整型,p是个int 指针,二者虽然字面值是一样的,但类型不同,不可混用。

int null = 0, *p = nullptr;

int main()
{
    int i = 0, &r = i;
    auto a = r;
    const int ci = i, &cr = ci;
    auto b = ci;
    auto c = cr;
    auto d = &i;
    auto e = &ci;
    const auto f = ci;
    auto &g = ci;
 
    a = 42;
    b = 42;
    c = 42;
    d = 42;      //error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive]
    e = 42;      //error: invalid conversion from ‘int’ to ‘const int*’ [-fpermissive]
    g = 42;      //error: assignment of read-only reference ‘g’
 
    return 0;
}

验证代码如下

#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;
}

c是int, d是a的引用,它们的值都是4。

auto必须初始化,decltype不用。auto的结果与表达形式无关,decltype结果类型与表达式形式有关

decltype指定的类型与auto指定的类型一样:auto (x)=a; decltype(x)=a;

decltype指定的类型与auto指定的类型不一样:auto (x)=a; decltype((x))=a;

int i = 0, &r = i;
// same
auto a = i;
decltype(i) b = i;
// different
auto c = r;
decltype(r) d = r;

编译不通过 会报错 

结构体里赋值的话 记得编译时 要用c++11  否则报错 

#include <iostream>
using namespace std;

struct Sale_data{


        string bookno;
        std::string bookname;
        double price =0.0;
        int num = 1;


};


int main(){



        return 0;

}
~                                                                               
~              

 g++ 10.cpp --std=c++11;

2.41

#include <iostream>
#include <string>

struct Sale_data{

        std::string bookNo;
        unsigned units_sold = 0;
        double revenue = 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.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
    }
}

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;
}

1.51

#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;
}

1.52

#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
    }
}

1.6

#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
    }
}

猜你喜欢

转载自blog.csdn.net/ljwy1234/article/details/82712527