I l@ve RuBoard Previous Section Next Section

1.2 Defining and Initializing a Data Object

Now that we have the user's attention, let's challenge her to a quiz. We display two numbers representing a numerical sequence and then request our user to identify the next value in the sequence. For example,



The values 2,3 form two consecutive 


    elements of a numerical sequence. 


What is the next value? 

These values are the third and fourth elements of the Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, and so on. A Fibonacci sequence begins with the first two elements set to 1. Each subsequent element is the sum of its two preceding elements. (In Chapter 2 we write a function to calculate the elements.)

If the user enters 5, we congratulate her and ask whether she would like to try another numerical sequence. Any other entered value is incorrect, and we ask the user whether she would like to guess again.

To add interest to the program, we keep a running score based on the number of correct answers divided by the number of guesses.

Our program needs at least five objects: the string class object to hold the name of the user; three integer objects to hold, in turn, the user's guess, the number of guesses, and the number of correct guesses; and a floating point object to hold the user's score.

To define a data object, we must both name it and provide it with a data type. The name can be any combination of letters, numbers, and the underscore. Letters are case-sensitive. Each one of the names user_name, User_name, uSeR_nAmE, and user_Name refers to a distinct object.

A name cannot begin with a number. For example, 1_name is illegal but name_1 is OK. Also, a name must not match a language keyword exactly. For example, delete is a language keyword, and so we can't use it for an entity in our program. (This explains why the operation to remove a character from the string class is erase() and not delete().)

Each object must be of a particular data type. The name of the object allows us to refer to it directly. The data type determines the range of values the object can hold and the amount of memory that must be allocated to hold those values.

We saw the definition of user_name in the preceding section. We reuse the same definition in our new program:



#include <string> 


string user_name; 

A class is a programmer-defined data type. C++ also provides a set of built-in data types: Boolean, integer, floating point, and character. A keyword is associated with each one to allow us to specify the data type. For example, to store the value entered by the user, we define an integer data object:



int usr_val; 

int is a language keyword identifying usr_val as a data object of integer type. Both the number of guesses a user makes and the number of correct guesses are also integer objects. The difference here is that we wish to set both of them to an initial value of 0. We can define each on a separate line:



int num_tries = 0; 


int num_right = 0; 

Or we can define them in a single comma-separated declaration statement:



int num_tries = 0, num_right = 0; 

In general, it is a good idea to initialize data objects even if the value simply indicates that the object has no useful value as yet. I didn't initialize usr_val because its value is set directly from the user's input before the program makes any use of the object.

An alternative initialization syntax, called a constructor syntax, is



int num_tries( 0 ); 

I know. Why are there two initialization syntaxes? And, worse, why am I telling you this now? Well, let's see whether the following explanation satisfies either or both questions.

The use of the assignment operator (=) for initialization is inherited from the C language. It works well with the data objects of the built-in types and for class objects that can be initialized with a single value, such as the string class:



string sequence_name = "Fibonacci"; 

It does not work well with class objects that require multiple initial values, such as the standard library complex number class, which can take two initial values: one for its real component and one for its imaginary component. The alternative constructor initialization syntax was introduced to handle multiple value initialization:



#include <complex> 


complex<double> purei( 0, 7 ); 

The strange bracket notation following complex indicates that the complex class is a template class. We'll see a great deal more of template classes throughout the book. A template class allows us to define a class without having to specify the data type of one or all of its members.

The complex number class, for example, contains two member data objects. One member represents the real component of the number. The second member represents the imaginary component of the number. These members need to be floating point data types, but which ones? C++ generously supports three floating point size types: single precision, represented by the keyword float; double precision, represented by the keyword double; and extended precision, represented by the two keywords long double.

The template class mechanism allows the programmer to defer deciding on the data type to use for a template class. It allows the programmer to insert a placeholder that is later bound to an actual data type. In the preceding example, the user chose to bind the data type of the complex class members to double.

I know, this probably raises scads more questions than it answers. However, it is because of templates that C++ supports two initialization syntaxes for the built-in data types. When the built-in data types and programmer-defined class types had separate initialization syntaxes, it was not possible to write a template that supported both built-in and class data types. Making the syntax uniform simplified template design. Unfortunately, explaining the syntax seems to have become more complicated!

The user's running score must to be a floating point value because it may be some percentage. We'll define it to be of type double:



double usr_score = 0.0; 

We also need to keep track of the user's yes/no responses: Make another try? Try another sequence?

We can store the user's response in a character data object:



char usr_more; 


cout << "Try another sequence? Y/N? "; 


cin >> usr_more; 

The char keyword represents a character type. A character marked by a pair of single quotations represents a character literal: 'a', '7', ';', and so on. Some special built-in character literals are the following (they are sometimes called escape sequences):



'\n'  newline 


'\t'  tab 


'\0'  null 


'\''  single quote 


'\"'  double quote 


'\\'  backslash 

For example, to generate a newline and then tab before printing the user's name, we might write



cout << '\n' << '\t' << user_name; 

Alternatively, we can concatentate single characters into a string:



cout << "\n\t" << user_name; 

Typically, we use these special characters within string literals. For example, to represent a literal file path under Windows, we need to escape the backslash:



"F:\\essential\\programs\\chapter1\\ch1_main.cpp"; 

C++ supports a built-in Boolean data type to represent true/false values. In our program, for example, we can define a Boolean object to control whether to display the next numeric sequence:



bool go_for_it = true; 

A Boolean object is specified with the bool keyword. It can hold one of two literal values, either true or false.

All the data objects defined so far modified during the course of our program. go_for_it, for example, eventually gets set to false. usr_score is potentially updated with each user guess.

Sometimes, however, we need an object to represent a constant value: the maximum number of guesses to allow a user, for example, or the value of pi. The objects holding these values should not be modified during the course of our program. How can we prevent the accidental modification of such objects? We can enlist the aid of the language by declaring these objects as const:



const int max_tries = 3; 


const double pi = 3.14159; 

A const object cannot be modified from its initial value. Any attempt to assign a value to a const object results in a compile-time error. For example:



max_tries = 42; // error: const object 
    I l@ve RuBoard Previous Section Next Section