What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
cs:programming:cpp:cpp_primer:answers:chpt_2 [2024/01/14 13:46] – 移除 - 外部编辑 (未知日期) 127.0.0.1cs:programming:cpp:cpp_primer:answers:chpt_2 [2024/01/14 13:46] (当前版本) – ↷ 页面programming:cpp:cpp_primer:answers:chpt_2被移动至cs:programming:cpp:cpp_primer:answers:chpt_2 codinghare
行 1: 行 1:
 +======Chapter.2======
 +第二章的习题答案
 +----
 +====Ex.2.1-2.10====
 +==ex.2.1==
 +>Exercise 2.1: What are the differences between int, long, long long, and short? Between an unsigned and a signed type? Between a float and a double?
  
 +  * Q1: their size is different. int: 16bits; long: 32 bits; long long: 64bits; short: 16bits.
 +  * Q2:singed-type and unsigned-type have different ranges. signed-type usually has its range on both sides of 0; negative range on the left-hand side. unsigned-type starts with 0. More precisely, if a type has $n$ bits, then signed ver has range $[-2^{n-1}+1, 2^{n-1}-1]$, the unsigned ver has range $[0, 2^n-1]$.
 +  * Q3:float / double has different precision(significant digits). float has 6 digits, and double has 10 digits.
 +A few notable things:
 +>//C++ guarantees a char is exactly one byte which is at least 8 bits, short is at least 16 bits, int is at least 16 bits, and long is at least 32 bits. It also guarantees the unsigned version of each of these is the same size as the original, for example, sizeof(unsigned short) == sizeof(short).//
 +
 +>//When writing portable code, you shouldn’t make additional assumptions about these sizes.//
 +Refs:
 +  * [[https://isocpp.org/wiki/faq/newbie#choosing-int-size|What are the criteria for choosing between short / int / long data types?]]
 +  * [[https://stackoverflow.com/questions/2386772/what-is-the-difference-between-float-and-double|What is the difference between float and double?]]
 +==ex.2.2==
 +>Exercise 2.2: To calculate a mortgage payment, what types would you use for the rate, principal, and payment? Explain why you selected each type.
 +rate/principal/payment could be some value that comes with decimals but doesn't require too much precision, such as 2.5%, 525555.90, 1333.25, So the float type would handle them all perfectly.
 +\\ \\ 
 +notes: typical float in memory: sign: 1bit, exponent : 8bits, Mantissa: 23bits. Good enough range for almost all of the data above.\\ \\ 
 +Ref:
 +  * [[https://blog.csdn.net/albertsh/article/details/92385277|float的精度和取值范围]]
 +==ex.2.3==
 +>Exercise 2.3: What output will the following code produce?
 +<code cpp>
 +/*Q1*/
 +unsigned u = 10, u2 = 42;
 +std::cout << u2 - u << std::endl;
 +std::cout << u - u2 << std::endl;
 +/*result*/
 +32
 +4,294,967,264 //2^32 + (10-42)
 +/*Q2*/
 +int i = 10, i2 = 42;
 +std::cout << i2 - i << std::endl;
 +std::cout << i - i2 << std::endl;
 +std::cout << i - u << std::endl;
 +std::cout << u - i << std::endl;
 +/*result*/
 +32
 +-32
 +0
 +0
 +</code>
 +==ex2.4==
 +>Exercise 2.4: Write a program to check whether your predictions were correct. If not, study this section until you understand what the problem is.
 +<code cpp>
 +#include <iostream>
 +int main(int argc, char const *argv[])
 +{
 + unsigned u = 10, u2 = 42;
 + int i = 10, i2 = 42;
 + std::cout << u2 - u << std::endl;
 + std::cout << u - u2 << std::endl;
 + std::cout << i2 - i << std::endl;
 + std::cout << i - i2 << std::endl;
 + std::cout << i - u << std::endl;
 + std::cout << u - i << std::endl;
 + return 0;
 +}
 +</code>
 +the result matches what we got in ex.2.3.
 +==ex2.5==
 +>Exercise 2.5: Determine the type of each of the following literals. Explain the differences among the literals in each of the four examples:
 +<code>
 +(a) 'a', L'a', "a", L"a"
 +'a' : char
 +L'a' : wchar_t 
 +"a" : string 
 +L"a" : wchar_t string 
 +
 +(b) 10, 10u, 10L, 10uL, 012, 0xC
 +10 : decimal
 +10u : unsigned decimal
 +10L : long decimal
 +10ul : unsigned long decimal
 +012 : octal
 +0xC: Hex
 +
 +(c) 3.14, 3.14f, 3.14L
 +3.14 : double
 +3.14f : float
 +3.14L: long double
 +
 +10, 10u, 10., 10e-2
 +10 : decimal
 +10u : unsigned decimal
 +10. : double
 +10e-2 : double
 +</code>
 +==ex2.6==
 +>Exercise 2.6: What, if any, are the differences between the following definitions:
 +<code cpp>
 +int month = 9, day = 7;
 +int month = 09, day = 07;
 +</code>
 +The definition in first-line defines dates in decimal. The second line is trying to define the date in octal, however, the 09 is not a valid number in octal. The correct way to define Seq.7th in octal is:
 +<code cpp>
 +int month = 011, day = 07;
 +</code>
 +==ex.2.7==
 +>Exercise 2.7: What values do these literals represent? What type does each have?
 +<code>
 +(a) "Who goes with F\145rgus?\012"
 +print result: Who goes with Fergus?J, String 
 +(b) 3.14e1L
 +print result: 3.14, long double
 +(c) 1024f
 +print result: this is not the right way to represent a float literal. f suffix can only apply to float point number, e.g. 1024.0
 +(d) 3.14L
 +print result: 3.14 long double
 +</code>
 +==ex.2.8==
 +>Exercise 2.8: Using escape sequences, write a program to print 2M followed by a newline. Modify the program to print 2, then a tab, then an M, followed by a newline.
 +<code cpp>
 +#include <iostream>
 +int main(int argc, char const *argv[])
 +{
 + std::cout << "2M in escape Seq: " << "2\x4d\n";
 + std::cout << "2M in escape Seq [modver]: " << "2\t\x4d\n";
 + return 0;
 +}
 +</code>
 +==ex.2.9==
 +>Exercise 2.9: Explain the following definitions. For those that are illegal, explain what’s wrong and how to correct it.
 +<code cpp>
 +(a) std::cin >> int input_value; //illegal, value for initialization must be defined
 +fix: int input_value = 0; std::cin >> input_value;
 +(b) int i = { 3.14 }; //illegal, list initialization does not allow narrowing conversation
 +fix: float I = {3.14};
 +(c) double salary = wage = 9999.99; //illegal, wage wasn't defined earlier so that it can't be used as a value for initialization.
 +fix: double salary = 9999.99, wage = 9999.99;
 +(d) int i = 3.14; //legal, but the the value of i will be truncated to 3.
 +fix: float i = 3.14
 +</code>
 +==ex.2.10==
 +>Exercise 2.10: What are the initial values, if any, of each of the following variables?
 +<code cpp>
 +std::string global_str;
 +int global_int;
 +int main()
 +{
 +int local_int;
 +std::string local_str;
 +}
 +</code>
 +<code>
 +global_str: empty string
 +global_int: 0
 +local_int:uninitialized
 +std::string local_str: empty string
 +</code>
 +====Ex.2.11-2.20====
 +==ex.2.11==
 +>Exercise 2.11: Explain whether each of the following is a declaration or a definition.
 +<code cpp>
 +extern int ix = 1024; //definition, value ix has been initialized.
 +int uy; //definition, memory is allocated for the varible
 +extern int iz; //declaration, extern keyword lead the value to be declared but not defined.
 +</code>
 +==ex.2.12==
 +>Exercise 2.12: Which, if any, of the following names are invalid?
 +<code cpp>
 +(a) int double = 3.14; //invalid, double is a reserved keyword
 +(b) int _; //valid
 +(c) int catch-22; //invalid, "-" is not a valid character for naming variable.
 +(d) int 1_or_2 = 1; //invalid, variable name can't start with numbers.
 +(e) double Double = 3.14; //valid
 +</code>
 +==ex.2.13==
 +>Exercise 2.13: What is the value of j in the following program?
 +<code cpp>
 +int i = 42;
 +int main()
 +{
 + int i = 100;
 + int j = i;
 +}
 +</code>
 +''j'' will be ''100'', because it is initialized by the local variable ''i''.
 +==ex.2.14==
 +>Exercise 2.14: Is the following program legal? If so, what values are printed?
 +<code cpp>
 +int i = 100, sum = 0;
 +for (int i = 0; i != 10; ++i)
 + sum += i;
 +std::cout << i << " " << sum << std::endl;
 +</code>
 +it is legal. However, the variable ''i'' in scope of ''for'' statement is different from the global variable ''i'',so the global ''i'' doesn't control the for loop. Also, because global variable ''sum'' was used in for loop, so for loop affects the value of ''sum''.\\ 
 +The final output would be : ''100'', ''45''。 
 +==ex.2.15==
 +>Exercise 2.15: Which of the following definitions, if any, are invalid? Why?
 +<code>
 +(a) int ival = 1.01; //valid, an int deifinition
 +(b) int &rval1 = 1.01; //invalid, reference must bound to an object
 +(c) int &rval2 = ival; //valid
 +(d) int &rval3; //invalid, reference must bound to an initialized object
 +</code>
 +==ex.2.16==
 +>Exercise 2.16: Which, if any, of the following assignments are invalid? If they are valid, explain what they do.
 +<code>
 +int i = 0, &r1 = i; double d = 0, &r2 = d;
 +(a) r2 = 3.14159; //valid
 +(b) r2 = r1; //valid. it is actually assigned i to the d, type conversion happened.
 +(c) i = r2; //valid, double to int
 +(d) r1 = d;//valid, double to int
 +</code>
 +==ex.2.17==
 +>Exercise 2.17: What does the following code print?
 +<code cpp>
 +int i, &ri = i;
 +i = 5; ri = 10;
 +std::cout << i << " " << ri << std::endl;
 +</code>
 +Since ''ri'' is refering to ''i'', assign ''10'' to ''ri'' is equal to assign ''10'' to ''i'', which changes the value of ''i'' from ''5'' to ''10''. Thus the final result is ''10'', ''10''
 +==ex.2.18==
 +>Exercise 2.18: Write code to change the value of a pointer. Write code to change the value to which the pointer points.
 +<code cpp>
 +#include <iostream>
 +int main(int argc, char const *argv[])
 +{
 + int i = 100;
 + int j = 200;
 + //change the value of the pointer
 + int *p1 = &i;
 + p1 = &j;
 + std::cout <<"i: " << i << " j: " << j << " p1 points to: " << *p1 << std::endl;
 + //change the value to which the pointer points
 + //p1 is now pointing the j
 + *p1 = 300;
 + std::cout <<"i: " << i << " j: " << j << " p1 points to: " << *p1 << std::endl;
 + return 0;
 +}
 +</code>
 +==ex.2.19==
 +>Exercise 2.19: Explain the key differences between pointers and references.
 +
 +  * Reference is not an object, but pointer is.
 +  * Once reference bound with an object, it can't refer to another object; pointer can change the object which it points over its lifetime.
 +  * Reference must be initialized, a pointer may not be initialized at the time it is defined.
 +==ex.2.20==
 +>Exercise 2.20: What does the following program do?
 +<code cpp>
 +int i = 42; //initialized a int type variable i
 +int *p1 = &i; //initiazed a pointer that point to the address of variable i
 +*p1 = *p1 * *p1; //pi dereferenced. This line is equal to i = i * i. the 1st、2rd、4th * are dereference operator, the 3rd * is doing multiplication. The result will be 42 * 42 = 1764
 +</code>
 +====Ex.2.21-2.30====
 +==ex.2.21==
 +>Exercise 2.21: Explain each of the following definitions. Indicate whether any are illegal and, if so, why.
 +<code>
 +int i = 0; 
 +(a) double* dp = &i; //illegal, the type of the pointer must be identical to  type of which object it points to.
 +(b) int *ip = i; //illegal, initializer must be an address(an int* value)
 +(c) int *p = &i; //legal
 +</code>
 +==ex.2.22==
 +>Exercise 2.22: Assuming p is a pointer to int, explain the following code:
 +<code>
 +if (p) // if p is a null pointer , the condition is false, otherwise the condition is true.
 +if (*p) // if the object which p points to has value 0, the condition is false, otherwise the condition is true.
 +</code>
 +==ex.2.23==
 +>Exercise 2.23: Given a pointer p, can you determine whether p points to a valid object? If so, how? If not, why not?
 +We can't determine whether a pointer points to a valid object. 
 +>//There is no way to distinguish a valid address from an invalid one formed from the bits that happen to be in the memory in which the pointer was allocated.//
 +
 +==ex.2.24==
 +>Exercise 2.24: Why is the initialization of p legal but that of lp illegal?
 +<code cpp>
 +int i = 42; void *p = &i; long *lp = &i;
 +</code>
 +By definition, a void type pointer can point to any type of variable. The limitation on a void type pointer is we can't use it to edit the content of the object to which the pointer points since editing requires a certain type of object. Thus, p is legal. However, pointer initialization requires the type pointer, and the type of initializer must identical. Initializing a long-type pointer with an int-type object is not allowed.
 +==ex.2.25==
 +>Exercise 2.25: Determine the types and values of each of the following variables.
 +<code cpp>
 +(a) int* ip, i, &r = i; //ip is an pointer. i is an interger variable, r is a reference refer to i.
 +(b) int i, *ip = 0; // i is an int variable. ip is a pointer that can point to an int object, but now it is set to be a null pointer.
 +(c) int* ip, ip2; // ip is an pointer points to the a int variable. ip2 is an int variable.
 +</code>
 +==ex2.26==
 +>Exercise 2.26: Which of the following are legal? For those that are illegal, explain why.
 +<code cpp>
 +(a) const int buf; //illegal, const variable must initialized
 +(b) int cnt = 0; //legal
 +(c) const int sz = cnt; //legal
 +(d) ++cnt; ++sz; // ++sz is illegal, sz is a const int variable that can't be modified
 +</code>
 +==ex.2.27==
 +>Exercise 2.27: Which of the following initializations are legal? Explain why.
 +<code cpp>
 +(a) int i = -1, &r = 0;
 + //illegal, reference r must bind to an initialized object
 +(b) int *const p2 = &i2; 
 +//legal, initializing a const pointer with address of an int object
 +(c) const int i = -1, &r = 0;
 + //legal, reference to const can be initialized with literal
 +(d) const int *const p3 = &i2; 
 +//legal,  initializing a const pointer with address of an int object. future editing of i2 is not allowed through this pointer.
 +(e) const int *p1 = &i2; 
 +//legal, editing of i2 is not allowed through pointer p1
 +(f) const int &const r2; 
 +//illegal. there is no const reference since reference is not an object. besides, reference initialization requires a certain initialized object.
 +(g) const int i2 = i, &r = i; 
 +//legal, i will be converted to aconst int to fit the r.
 +</code>
 +==2.28==
 +>Exercise 2.28: Explain the following definitions. Identify any that are illegal.
 +<code cpp>
 +(a) int i, *const cp; //illegal, const pointer must be initialized. 
 +(b) int *p1, *const p2; //illegal, const pointer must be initialized. 
 +(c) const int ic, &r = ic; //illegal, a non-const reference can't be bound to an const object
 +(d) const int *const p3; //illegal, const pointer must be initialized. 
 +(e) const int *p; //legal pointer to int const
 +</code>
 +==ex.2.29==
 +>Exercise 2.29: Uing the variables in the previous exercise, which of the following assignments are legal? Explain why.
 +<code cpp>
 +(a) i = ic; // legal, const int to int
 +(b) p1 = p3; // illegal //p3 is a pointer not can't be changed and can't help with the modification. p1 can either modify or change the pointing location
 +(c) p1 = &ic; // illegal, ic is const int, p1 is pointer to non-const
 +(d) p3 = &ic; // illegal, p3 can't be changed
 +(e) p2 = p1; // illegal, p2 can't be changed
 +(f) ic = *p3; // illegal, ic can't be changed
 +</code>
 +==ex.2.30==
 +>Exercise 2.30: For each of the following declarations indicate whether the object being declared has top-level or low-level const.
 +<code cpp>
 +const int v2 = 0; int v1 = v2; 
 +int *p1 = &v1, &r1 = v1; 
 +const int *p2 = &v2, *const p3 = &i, &r2 = v2; 
 +//v2 is top-level const
 +//p2 is lower-level const, p3 is top-level + lower-level const, r2 is lower-level const.
 +</code>
 +====Ex.2.31-2.40====
 +==ex2.31==
 +>Exercise 2.31: Given the declarations in the previous exercise determine whether the following assignments are legal. Explain how the top-level or low-level const applies in each case.
 +<code cpp>
 +r1 = v2; //legal, r1 is non-const, v2 is top-level const. copy v2 to r1 will ignore the top-level const
 +p1 = p2; //illegal, p1 is non-const, p2 is low-level const.
 +p2 = p1; //legal, p2 is low-const, p1 is non-const, however, can be convert to low-const
 +p1 = p3; //illegal, p3 has low-level const part that can't be copied to a non-const object
 +p2 = p3; //legal, both p2 and p3 has low-level const parts. top-level part in p3 is ignored during the copy.
 +
 +</code>
 +==ex.2.32==
 +>Exercise 2.32: Is the following code legal or not? If not, how might you make it legal?
 +<code cpp>
 +int null = 0, *p = null;
 +</code>
 +I suppose the coder just wants to get a null pointer. Since a null pointer initialization is only allowed to use literal, giving an int variable that is equal to 0 to initialize the pointer is invalid. Two different ways to fix this:
 +<code cpp>
 +int *p = nullptr;
 +int *p = 0;
 +</code>
 +==ex.2.33==
 +>Exercise 2.33: Using the variable definitions from this section, determine what happens in each of these assignments:
 +<code cpp>
 +a = 42; //ok, a is an int
 +b = 42; //ok, a is an int
 +c = 42; //ok, a is an int
 +d = 42; //error, d is an pointer to int
 +e = 42; //error, e is an pointer to const int
 +g = 42; //error, g is already bound to ci. however, reference like g can be initialized by literal.
 +</code>
 +==ex.2.34==
 +>Write a program containing the variables and assignments from the previous exercise. Print the variables before and after the assignments to check whether your predictions in the previous exercise were correct. If not, study the examples until you can convince yourself you know what led you to the wrong conclusion.
 +<code cpp>
 +#include <iostream>
 +int main(int argc, char const *argv[])
 +{
 + int i = 0, &r = i;
 + const int ci = i, &cr = ci;
 + auto a = r; // a is an int
 + std::cout << a << std::endl;
 + a = 42;
 + std::cout << a << std::endl;
 + auto b = ci; // b is an int, top-level const ignored
 + std::cout << b << std::endl;
 + b = 42;
 + std::cout << b << std::endl;
 + auto c = cr; // c is an int, top-level const ignored
 + std::cout << c << std::endl;
 + c = 42;
 + std::cout << c << std::endl;
 + auto d = &i; // d is int*
 + std::cout << *d << std::endl;
 + *d = 42; //a fix
 + std::cout << *d << std::endl;
 + auto e = &ci; // e is pointer to const int
 + std::cout << *e << std::endl; //ci can't be modified
 + auto &g = ci; // g is an reference to const
 + std::cout << g << std::endl; // ci can't be modified
 + return 0;
 +}
 +</code>
 +==ex.2.35==
 +<code cpp>
 +>Exercise 2.35: Determine the types deduced in each of the following definitions. Once you’ve figured out the types, write a program to see whether you were correct.
 +<code cpp>
 +/*deduction*/
 +const int i = 42;
 +auto j = i; // j is an int
 +const auto &k = i; //k is an reference that refers to const int i
 +auto *p = &i; //p is an pointer points to const int i
 +const auto j2 = i, &k2 = i; //j2 is an const int, k2 is an reference to const
 +</code>
 +<code cpp>
 +#include <iostream>
 +#include <typeinfo>
 +int main(int argc, char const *argv[])
 +{
 + const int i = 42;
 + auto j = i;
 + const auto &k = i;
 + auto *p = &i;
 + const auto j2 = i, &k2 =i;
 + std::cout << "j is: " << typeid(j).name() << std::endl;
 + std::cout << "k is: " << typeid(k).name() << std::endl;
 + std::cout << "p is: " << typeid(p).name() << std::endl;
 + std::cout << "j2 is: " << typeid(j2).name() << std::endl;
 + std::cout << "k2 is: " << typeid(k2).name() << std::endl;
 + return 0;
 +}
 +</code>
 +==ex.2.36==
 +>Exercise 2.36: In the following code, determine the type of each variable and the value each variable has when the code finishes:
 +<code cpp>
 +int a = 3, b = 4;
 +decltype(a) c = a; // c is an int, 3
 +decltype((b)) d = a; //d is an reference to int a, 3
 +++c;
 +++d;
 +</code>
 +''++c'' yields ''c+1 = 4''; ''++d'' yields ''a+1 = 4''
 +==ex.2.37==
 +>Exercise 2.37: Assignment is an example of an expression that yields a reference type. The type is a reference to the type of the left-hand operand. That is, if i is an int, then the type of the expression i = x is int&. Using that knowledge, determine the type and value of each variable in this code:
 +<code cpp>
 +int a = 3, b = 4;
 +decltype(a) c = a; // c is int with value 3.
 +decltype(a = b) d = a; // d is an int& refers to a, with value 3.
 +</code>
 +==ex.2.38==
 +>Exercise 2.38: Describe the differences in type deduction between decltype and auto. Give an example of an expression where auto and decltype will deduce the same type and an example where they will deduce differing types.
 +
 +  - ''auto'' requires initialization, decltype don't(except for the reference)
 +  - ''auto'' will return the type based on evaluation, but decltype will return it based on the declaration. So we saw a lot of types convert happen during the auto type deduction, but the decltype always returns what the expression declared.
 +<code cpp>
 +int i = 0;
 +int &r = i;
 +const int ci = 0;
 +/*same type*/
 +auto a1 = i; //return int
 +decltype(i) a2 = i; //return int
 +/*different types*/
 +auto b1 = ci; //return int
 +decltype(ci) b2 = ci; //return const int
 +/*another differents types*/
 +auto r1 = r; //return int
 +decltype(r) r2 = r; //return int&
 +</code>
 +==ex.2.39==
 +>Exercise 2.39: Compile the following program to see what happens when you forget the semicolon after a class definition. Remember the message for future reference.
 +<code cpp>
 +struct Foo { /* empty */ } // Note: no semicolon
 +int main()
 +{
 +return 0;
 +}
 +</code>
 +output:
 +<code bash>
 +ex_2_39.cc:3:2: error: expected ‘;’ after struct definition
 + }
 +  ^
 +  ;
 +</code>
 +==ex.2.40==
 +>Exercise 2.40: Write your own version of the Sales_data class.
 +<code cpp>
 +struct Sales_data {
 + std::string bookNo = "";
 + unsigned int unitSold = 0;
 + double soldPrice = 0.0;
 + double revenue = 0.0;
 +};
 +</code>
 +====Ex.2.41-2.42====
 +==ex.2.41==
 +>Exercise 2.41: Use your Sales_data class to rewrite the exercises in § 1.5.1 (p. 22), § 1.5.2 (p. 24), and § 1.6 (p. 25). For now, you should define your Sales_data class in the same file as your main function.
 +<code cpp>
 +/*
 + * 1.5.1-ex.1.20
 + * Reading a set of book sales and print 
 + */
 +
 +#include <iostream>
 +#include <string>
 +struct Sales_data {
 + std::string bookNo = "";
 + unsigned int unitSold = 0;
 + double soldPrice = 0.0;
 +};
 +
 +int main(int argc, char const *argv[])
 +{
 + Sales_data book;
 + while(std::cin >> book.bookNo >> book.unitSold >> book.soldPrice) {
 +
 + std::cout << "ISBN: " << book.bookNo   
 +   << " Copies Sold: " << book.unitSold 
 +   << " Revenue: " << book.unitSold * book.soldPrice
 +   << " Unit Prine: " << book.soldPrice
 +   << std::endl;
 + }
 + return 0;
 +}
 +</code>
 +
 +<code cpp>
 +/* 
 + * 1.5.1-ex.1.21
 + * Reading two sales that have same ISBN and produce there sum
 + */
 +
 +#include <iostream>
 +#include <string>
 +struct Sales_data {
 + std::string bookNo = "";
 + unsigned int unitSold = 0;
 + double soldPrice = 0.0;
 + double revenue = 0.0;
 +};
 +int main(int argc, char const *argv[])
 +{
 + Sales_data book1, book2;
 + std::cin >> book1.bookNo >> book1.unitSold >> book1.soldPrice;
 + std::cin >> book2.bookNo >> book2.unitSold >> book2.soldPrice;
 +
 + book1.revenue = book1.unitSold * book1.soldPrice;
 + book2.revenue = book2.unitSold * book2.soldPrice;
 +
 + if(book1.bookNo == book2.bookNo) {
 + std::cout <<"ISBN: " << book1.bookNo
 +   <<" Total copies sold: " << book1.unitSold + book2.unitSold
 +   <<" Revenue: " << book1.revenue + book2.revenue
 +   <<" Average price: " << (book1.revenue + book2.revenue) / (book1.unitSold + book2.unitSold)
 +   <<std::endl;
 + return 0;
 +
 + } else {
 + std::cerr << "ISBN must be the same! " << std::endl;
 + return -1;
 + }
 + return 0;
 +}
 +</code>
 +<code cpp>
 +/* 
 + * 1.5.1-ex.1.22 to 1.6-ex.1.25
 + * Reading a set of trans, if they refer to the same ISBN,
 + * then give the sum of then and count the total copies sold
 + */
 +
 +#include <iostream>
 +#include <string>
 +struct Sales_data {
 + std::string bookNo = "";
 + unsigned int unitSold = 0;
 + double soldPrice = 0.0;
 + double revenue = 0.0;
 +};
 +
 +int main(int argc, char const *argv[])
 +{
 + Sales_data book;
 +
 + if(std::cin >> book.bookNo >> book.unitSold >> book.soldPrice) {
 +
 + book.revenue = book.unitSold * book.soldPrice;
 + Sales_data curBook;
 +
 + while(std::cin >> curBook.bookNo >> curBook.unitSold >> curBook.soldPrice) {
 + if(curBook.bookNo == book.bookNo) {
 + curBook.revenue = curBook.unitSold * curBook.soldPrice;
 + book.unitSold += curBook.unitSold;
 + book.revenue += curBook.revenue;
 + }
 + else {
 + double aver_price = book.revenue / book.unitSold;
 + std::cout << "ISBN: " << book.bookNo
 +   << " Copies sold: " << book.unitSold
 +   << " Revenue: " << book.revenue
 +   << " Average price: " << aver_price
 +   << std::endl;
 +
 + //reset the book to the current book
 + book.bookNo = curBook.bookNo;
 + book.unitSold = curBook.unitSold;
 + book.soldPrice = curBook.soldPrice;
 + book.revenue = curBook.unitSold * curBook.soldPrice;
 + }
 + }
 + double aver_price = book.revenue / book.unitSold;
 + std::cout << "ISBN: " << book.bookNo
 +   << " Copies sold: " << book.unitSold
 +   << " Revenue: " << book.revenue
 +   << " Average price: " << aver_price
 +   << std::endl;
 + return 0;
 + }
 + else {
 +
 + std::cerr << "No data?" << std::endl;
 + return -1;
 + }
 + return 0;
 +}
 +</code>
 +==ex.2.42==
 +>Exercise 2.42: Write your own version of the Sales_data.h header and use it to rewrite the exercise from § 2.6.2 (p. 76).
 +<code cpp>
 +/* header Sales_data.h */
 +#ifndef SALES_DATA_H
 +#define SALES_DATA_H
 +#include <string>
 +struct Sales_data {
 + std::string bookNo = "";
 + unsigned int unitSold = 0;
 + double soldPrice = 0.0;
 + double revenue = 0.0;
 +};
 +#endif
 +</code>
 +
 +<code cpp>
 +/*
 + * 1.5.1-ex.1.20
 + * Reading a set of book sales and print 
 + */
 +
 +#include <iostream>
 +#include <string>
 +#include "Sales_data.h"
 + main(int argc, char const *argv[])
 +{
 + Sales_data book;
 + while(std::cin >> book.bookNo >> book.unitSold >> book.soldPrice) {
 +
 + std::cout << "ISBN: " << book.bookNo   
 +   << " Copies Sold: " << book.unitSold 
 +   << " Revenue: " << book.unitSold * book.soldPrice
 +   << " Unit Prine: " << book.soldPrice
 +   << std::endl;
 + }
 + return 0;
 +}
 +</code>
 +<code cpp>
 +/* 
 + * 1.5.1-ex.1.21
 + * Reading two sales that have same ISBN and produce there sum
 + */
 +
 +#include <iostream>
 +#include <string>
 +#include "Sales_data.h"
 +int main(int argc, char const *argv[])
 +{
 + Sales_data book1, book2;
 + std::cin >> book1.bookNo >> book1.unitSold >> book1.soldPrice;
 + std::cin >> book2.bookNo >> book2.unitSold >> book2.soldPrice;
 +
 + book1.revenue = book1.unitSold * book1.soldPrice;
 + book2.revenue = book2.unitSold * book2.soldPrice;
 +
 + if(book1.bookNo == book2.bookNo) {
 + std::cout <<"ISBN: " << book1.bookNo
 +   <<" Total copies sold: " << book1.unitSold + book2.unitSold
 +   <<" Revenue: " << book1.revenue + book2.revenue
 +   <<" Average price: " << (book1.revenue + book2.revenue) / (book1.unitSold + book2.unitSold)
 +   <<std::endl;
 + return 0;
 +
 + } else {
 + std::cerr << "ISBN must be the same! " << std::endl;
 + return -1;
 + }
 + return 0;
 +}
 +</code>
 +<code cpp>
 +/* 
 + * 1.5.1-ex.1.22 to 1.6-ex.1.25
 + * Reading a set of trans, if they refer to the same ISBN,
 + * then give the sum of them and count the total copies sold
 + */
 +
 +#include <iostream>
 +#include <string>
 +#include "Sales_data.h"
 +int main(int argc, char const *argv[])
 +{
 + Sales_data book;
 +
 + if(std::cin >> book.bookNo >> book.unitSold >> book.soldPrice) {
 +
 + book.revenue = book.unitSold * book.soldPrice;
 + Sales_data curBook;
 +
 + while(std::cin >> curBook.bookNo >> curBook.unitSold >> curBook.soldPrice) {
 + if(curBook.bookNo == book.bookNo) {
 + curBook.revenue = curBook.unitSold * curBook.soldPrice;
 + book.unitSold += curBook.unitSold;
 + book.revenue += curBook.revenue;
 + }
 + else {
 + double aver_price = book.revenue / book.unitSold;
 + std::cout << "ISBN: " << book.bookNo
 +   << " Copies sold: " << book.unitSold
 +   << " Revenue: " << book.revenue
 +   << " Average price: " << aver_price
 +   << std::endl;
 +
 + //reset the book to the current book
 + book.bookNo = curBook.bookNo;
 + book.unitSold = curBook.unitSold;
 + book.soldPrice = curBook.soldPrice;
 + book.revenue = curBook.unitSold * curBook.soldPrice;
 + }
 + }
 + double aver_price = book.revenue / book.unitSold;
 + std::cout << "ISBN: " << book.bookNo
 +   << " Copies sold: " << book.unitSold
 +   << " Revenue: " << book.revenue
 +   << " Average price: " << aver_price
 +   << std::endl;
 + return 0;
 + }
 + else {
 +
 + std::cerr << "No data?" << std::endl;
 + return -1;
 + }
 + return 0;
 +}
 +</code>