Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

Exercises

Solutions to selected exercises can be found in the electronic document The Thinking in C++ Annotated Solution Guide, available for a small fee from www.BruceEckel.com.

  1. Create a header file (with an extension of ‘.h’). In this file, declare a group of functions by varying the argument lists and return values from among the following: void, char, int, and float. Now create a .cpp file that includes your header file and creates definitions for all of these functions. Each definition should simply print out the function name, argument list, and return type so you know it’s been called. Create a second .cpp file that includes your header file and defines int main( ), containing calls to all of your functions. Compile and run your program.
  2. Write a program that uses two nested for loops and the modulus operator (%) to detect and print prime numbers (integral numbers that are not evenly divisible by any other numbers except for themselves and 1).
  3. Write a program that uses a while loop to read words from standard input (cin) into a string. This is an “infinite” while loop, which you break out of (and exit the program) using a break statement. For each word that is read, evaluate it by first using a sequence of if statements to “map” an integral value to the word, and then use a switch statement that uses that integral value as its selector (this sequence of events is not meant to be good programming style; it’s just supposed to give you exercise with control flow). Inside each case, print something meaningful. You must decide what the “interesting” words are and what the meaning is. You must also decide what word will signal the end of the program. Test the program by redirecting a file into the program’s standard input (if you want to save typing, this file can be your program’s source file).
  4. Modify Menu.cpp to use switch statements instead of if statements.
  5. Write a program that evaluates the two expressions in the section labeled “precedence.”
  6. Modify YourPets2.cpp so that it uses various different data types (char, int, float, double, and their variants). Run the program and create a map of the resulting memory layout. If you have access to more than one kind of machine, operating system, or compiler, try this experiment with as many variations as you can manage.
  7. Create two functions, one that takes a string* and one that takes a string&. Each of these functions should modify the outside string object in its own unique way. In main( ), create and initialize a string object, print it, then pass it to each of the two functions, printing the results.
  8. Write a program that uses all the trigraphs to see if your compiler supports them.
  9. Compile and run Static.cpp. Remove the static keyword from the code, compile and run it again, and explain what happens.
  10. Try to compile and link FileStatic.cpp with FileStatic2.cpp. What does the resulting error message mean?
  11. Modify Boolean.cpp so that it works with double values instead of ints.
  12. Modify Boolean.cpp and Bitwise.cpp so they use the explicit operators (if your compiler is conformant to the C++ Standard it will support these).
  13. Modify Bitwise.cpp to use the functions from Rotation.cpp. Make sure you display the results in such a way that it’s clear what’s happening during rotations.
  14. Modify Ifthen.cpp to use the ternary if-else operator (?:).
  15. Create a struct that holds two string objects and one int. Use a typedef for the struct name. Create an instance of the struct, initialize all three values in your instance, and print them out. Take the address of your instance and assign it to a pointer to your struct type. Change the three values in your instance and print them out, all using the pointer.
  16. Create a program that uses an enumeration of colors. Create a variable of this enum type and print out all the numbers that correspond with the color names, using a for loop.
  17. Experiment with Union.cpp by removing various union elements to see the effects on the size of the resulting union. Try assigning to one element (thus one type) of the union and printing out a via a different element (thus a different type) to see what happens.
  18. Create a program that defines two int arrays, one right after the other. Index off the end of the first array into the second, and make an assignment. Print out the second array to see the changes cause by this. Now try defining a char variable between the first array definition and the second, and repeat the experiment. You may want to create an array printing function to simplify your coding.
  19. Modify ArrayAddresses.cpp to work with the data types char, long int, float, and double.
  20. Apply the technique in ArrayAddresses.cpp to print out the size of the struct and the addresses of the array elements in StructArray.cpp.
  21. Create an array of string objects and assign a string to each element. Print out the array using a for loop.
  22. Create two new programs starting from ArgsToInts.cpp so they use atol( ) and atof( ), respectively.
  23. Modify PointerIncrement2.cpp so it uses a union instead of a struct.
  24. Modify PointerArithmetic.cpp to work with long and long double.
  25. Define a float variable. Take its address, cast that address to an unsigned char, and assign it to an unsigned char pointer. Using this pointer and [ ], index into the float variable and use the printBinary( ) function defined in this chapter to print out a map of the float (go from 0 to sizeof(float)). Change the value of the float and see if you can figure out what’s going on (the float contains encoded data).
  26. Define an array of int. Take the starting address of that array and use static_cast to convert it into an void*. Write a function that takes a void*, a number (indicating a number of bytes), and a value (indicating the value to which each byte should be set) as arguments. The function should set each byte in the specified range to the specified value. Try out the function on your array of int.
  27. Create a const array of double and a volatile array of double. Index through each array and use const_cast to cast each element to non-const and non-volatile, respectively, and assign a value to each element.
  28. Create a function that takes a pointer to an array of double and a value indicating the size of that array. The function should print each element in the array. Now create an array of double and initialize each element to zero, then use your function to print the array. Next use reinterpret_cast to cast the starting address of your array to an unsigned char*, and set each byte of the array to 1 (hint: you’ll need to use sizeof to calculate the number of bytes in a double). Now use your array-printing function to print the results. Why do you think each element was not set to the value 1.0?
  29. (Challenging) Modify FloatingAsBinary.cpp so that it prints out each part of the double as a separate group of bits. You’ll have to replace the calls to printBinary( ) with your own specialized code (which you can derive from printBinary( )) in order to do this, and you’ll also have to look up and understand the floating-point format along with the byte ordering for your compiler (this is the challenging part).
  30. Create a makefile that not only compiles YourPets1.cpp and YourPets2.cpp (for your particular compiler) but also executes both programs as part of the default target behavior. Make sure you use suffix rules.
  31. Modify StringizingExpressions.cpp so that P(A) is conditionally #ifdefed to allow the debugging code to be automatically stripped out by setting a command-line flag. You will need to consult your compiler’s documentation to see how to define and undefine preprocessor values on the compiler command line.
  32. Define a function that takes a double argument and returns an int. Create and initialize a pointer to this function, and call the function through your pointer.
  33. Declare a pointer to a function taking an int argument and returning a pointer to a function that takes a char argument and returns a float.
  34. Modify FunctionTable.cpp so that each function returns a string (instead of printing out a message) and so that this value is printed inside of main( ).
  35. Create a makefile for one of the previous exercises (of your choice) that allows you to type make for a production build of the program, and make debug for a build of the program including debugging information.



[30] Note that all conventions seem to end after the agreement that some sort of indentation take place. The feud between styles of code formatting is unending. See Appendix A for the description of this book’s coding style.

[31] Thanks to Kris C. Matson for suggesting this exercise topic.

[32] Unless you take the very strict approach that “all argument passing in C/C++ is by value, and the ‘value’ of an array is what is produced by the array identifier: it’s address.” This can be seen as true from the assembly-language standpoint, but I don’t think it helps when trying to work with higher-level concepts. The addition of references in C++ makes the “all passing is by value” argument more confusing, to the point where I feel it’s more helpful to think in terms of “passing by value” vs. “passing addresses.”

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire