At their root, all applications do the same thing: they process data. Programming, then, is dictating what is done with what data. This perspective is relevant because to learn how to program in C++, you must first understand what the available data types are and how they are represented by variables. In this chapter, the most simple variable and data types are covered. These will be used over subsequent chapters as you begin to understand different ways to process information. In Chapter 6, “Complex Data Types,” and beyond, much more advanced data types and variables are covered.
We start with the basic syntax of variables: how to create them, how to assign them values, and how to print those values. Numeric variables will be used in these examples. Then we discuss two other simple data types: characters and strings. Finally, we delve into constants, a non-variable way to represent information.
The overwhelming majority of data you’ll work with will be in the form of variables. To use a variable, you must first declare it—you state that a variable with a specific name will be of a certain type, like so:
datatype variableName;
Let’s look at both parts of this construct separately. First, a variable’s type is the critical consideration. The type dictates what kinds of values can be stored (numbers, characters, etc.) and how much memory is required. This decision has an effect on the performance of your application and, for numbers, what range of values can be handled. Table 2.1 lists the number types available in C++, and you’ll see other simple types later in the chapter.
Table 2.1. These are the basic numeric data types available in C++, along with approximately how much space each requires and what kinds of values they can contain. The size and range of numbers can differ from one operating system to the next.
Looking at the numeric types in more detail, int
, short for integer, is the most basic and is described as C++’s natural type (i.e., C++ handles int
s most efficiently). Then there are long
and short
integers, which increase and decrease the range of their values (as well as how much memory each requires). The amount of space required for these types depends upon the operating system in use. All you can assume is that a short
will be smaller than or the same size as an int
and a long
will be the same size or larger than an int
.
The integer types can be additionally defined as signed
or unsigned
. The former means that a number can be either positive or negative, whereas the latter asserts that the number is always non-negative (unsigned numbers can be 0 or greater in value). With unsigned numbers, the range of possible positive values doubles (see Table 2.1). C++ assumes that all integers are signed by default. To declare one as unsigned, use this syntax:
unsigned datatype variableName;
The remaining numeric types are real numbers. They always contain a decimal point (whereas integers never do) and are sometimes expressed in E notation: 5.1E4, 2.98e+2, –3.45e9, and so on. The three kinds of real numbers—float
, double
, and long double
—differ as to how many digits after the decimal point they can store (which is also referred to as their precision). The least precise of these is float
; double
is twice as precise; and long double
is the most precise. As with the integer types, the actual ranges and memory requirements of these types may differ from one platform to the next. But unlike the integer types, the real numbers cannot be unsigned.
When declaring a variable, its type is the first consideration and its name (also called its identifier) is the second. Variable names in C++ follow specific rules:
• They can contain only letters, numbers, and the underscore.
• They must begin with either a letter or an underscore.
• They are case sensitive.
• They cannot be the same as an existing C++ keyword (such as int
, return
, main
).
• They cannot contain spaces.
There are two general naming conventions for creating compound variable names. One uses underscores to separate words; for example, first_name
or shipping_cost
. The second uses capitalization for this effect: firstName
or shippingCost
(or FirstName
and ShippingCost
). It doesn’t matter which convention you follow as long as you remain consistent.
When you’re trying to come up with a variable name, there are many best practices to follow. For starters, variable names should be
• Descriptive of what information the variable represents
• Logically named, following consistent practices
• Documented by comments
To begin working with variables, let’s create a simple application that declares a couple of them. This application will be used to calculate the cost of purchasing one or more widgets.
Follow the directions from the preceding chapter as to what tools to use or how to use specific IDEs.
// variables1.cpp - Script 2.1
Remember that thorough and accurate comments are the key to professional, reliable programming. In this book you’ll see more minimal notes like this one, but you should not hesitate to go overboard with your own documentation.
iostream
file.
#include <iostream>
This line adds the functionality of the iostream
header file to this program. It’s necessary in order to use cout
and cin
to interact with the console.
main()
function.
int main() {
This line begins the definition of a function called main, which will automatically be called first when the application is run. It takes no arguments and will return an integer value. The opening curly brace marks the beginning of the function’s body.
unsigned short quantity;
float price;
float taxRate;
This application uses two of the number data types. First, a variable called quantity
is defined as an unsigned short
(integer). This will be a positive whole number. Next, two floats are created—one to store the cost of the widget and another to store the sales tax. Each variable is declared on its own line, terminated by a semicolon. You can add comments to your code to detail the purpose of each variable, in case it’s not otherwise clear.
std::cout << "- Widget Cost Calculator-
";
Prior to showing the results of the calculations, this application should show a simple header message. As a reminder, the newline character (
) at the end of the message will force the next printed message to appear on the subsequent line in the console window. Some programmers may prefer to use endl
for this same effect:
std::cout << "- Widget Cost Calculator-" << std::endl;
Refer back to Chapter 1, “Creating a Basic Program,” if you are confused by the cout
or other syntax.
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
This trick was covered in Chapter 1. It forces the user to press Enter or Return prior to completing the execution of the application.
return
line and close the main()
function.
return 0;
}
The function returns the value 0
, which indicates that the function ran successfully. Then, the curly brace marks the end of the main()
function definition.
Some compilers will issue a warning if your file does not end with a newline, so you may need to press Enter or Return once after the closing curly brace.
variables1.cpp
.Remember that how you compile a C++ application depends on what tools you are using to build it. Again, see Chapter 1 for specific techniques.
• You can, and often will, declare multiple variables of the same type in one line:
float price, taxRate;
unsigned short v1, v2, v3;
• In C++, you can declare your variables anywhere in your code, as long as you do so before referring to them. It’s considered good form to declare a variable immediately before it is used, rather than declaring all variables together in a block. But in small programs like those in this chapter, it will make no real difference.
• Generally speaking, variables whose name begins with an underscore are special variables used by C++ itself. By starting your variable names with underscores, you run the risk of your names conflicting with existing C++ variables, having disastrous effects on your application. So while you can start a variable’s name with an underscore, it’s normally best not to.
• Because int
is the standard numeric type, the following declarations are equivalent:
unsigned int zipCode;unsigned zipCode;
Once you’ve declared a variable, you can assign a value to it. Assigning values to simple variables like numbers is very easy and requires only the assignment operator (=
):
int startYear;
startYear = 2006;
double weight;
weight = 1.0196;
Although you must always declare a variable before assigning a value to it, you can perform both acts in one step:
int startYear = 2006;
double weight = 1.0196;
(When you declare a variable and assign it a value in one step, that’s formally called initializing it.)
Let’s build on the preceding example by assigning values to the declared variables.
variables1.cpp
(Script 2.1) in your text editor or IDE.cout
statements, assign each variable a value (Script 2.2):
quantity = 3;
price = 19.95;
taxRate = 0.05;
Obviously you can insert any value you want here, as long as it matches the variable’s type. This means that integers don’t have decimals or fractions and that floats must use a decimal point. As with all numbers, you must not use quotation marks when assigning these values.
variables2.cpp
.The compilation process will check your syntax, notifying you of any errors.
Since there has been no alteration to the output, the result of running this application will still look like Figure 2.2.
• If multiple variables are to be assigned the same value, you can use this shorthand:
unsigned short v1, v2, v3;
v1 = v2 = v3 = 20;
All three variables now have a value of 20
.
• Another way to declare and initialize a simple variable is to use this syntax:
int startYear(2006);
We don’t use this format in this book, but you may come across it in other resources.
• One of the strengths of C (and therefore C++) is that you must declare every variable before you use it. Because of this rule, compilers will catch errors, such as misspelling a variable’s name.
• When you declare a variable, C++ reserves a block of memory on the computer for it. When you assign a value to that variable, that memory block is then filled with that value. This means that if you refer to a variable prior to assigning it a value, it may already have a meaningless value, namely whatever was already in that memory block. For this reason you’ll want to be certain that variables are properly assigned values in your programs.
One of the huge improvements that C++ has over C is how easily you can print a variable’s value. Instead of using the printf()
function with special formatting parameters, you can just use cout
, as you already have been:
float mileage = 27564.9;
std::cout << "My car currently has ";
std::cout << mileage;
std::cout << " miles on it.";
This can also be shortened to just
float mileage = 27564.9;
std::cout << "My car currently has " << mileage << " miles on it.";
It’s just that simple, regardless of the variable’s type (cout
knows how to handle and display the different kinds of data). Note that you do not put the variable within the double quotation marks, though, as C++ would then treat it as a literal string (for example, print mileage instead of the value of mileage
).
Using this new information, the existing application will be modified so that the variables’ values are printed. In the process, some simple calculations will be made using basic arithmetic. Although we haven’t discussed arithmetic in C++ yet, it’s very intuitive.
variables2.cpp
(Script 2.2) in your text editor or IDE.std::cout << "The cost of purchasing "
<< quantity << " widget(s) at a price of $"
<< price << ", with tax, comes to $";
This statement prints out the values of two variables—quantity
and price
—among some literal text.
std::cout << ( (quantity * price) + ((quantity * price) * taxRate) ) << ".
";
To calculate the total of the order, the quantity is multiplied times the price, using the multiplication operator (*
). Added to this is the amount of tax, determined by multiplying the order total times the tax rate.
print.cpp
.• If you were confused by any of the syntax in this program, break it down into its respective parts. For starters, you could use multiple cout
lines to print the main message. It might also help to break the order calculation into smaller pieces, perhaps using other variables as intermediaries.
• Strange as it may seem, computers generally do a poor job of handling floating-point numbers. For very sensitive calculations, like those involving money, it’s safest to use only integers. In this example, that would mean doing all calculations in cents, and then converting to dollars as the last step.
• Perhaps the best beginning debugging technique you can use as you learn how to program with C++ is to print out the values of variables as your application runs. That will give you a peek into what’s happening behind the scenes.
You may have noticed that the order total in the preceding example (see Figures 2.4 and 2.5) is displayed with several decimal points. By default, C++ will print out floating-point numbers using six digits (for example, two to the left of the decimal and four to the right). But by using cout
, you can adjust this behavior.
One option is to use the precision
function to establish the maximum number of digits to display:
std::cout.precision(4);
std::cout << 2.3459; // 2.346
std::cout.precision(3);
std::cout << 30.7164; // 30.7
Notice that the decimals will be rounded as necessary (so it’s 2.346
, not 2.345
). Unfortunately this technique will not reliably restrict the output to a certain number of digits after the decimal point. To accomplish that, two lines are required before setting the precision:
std::cout.setf(std::ios::fixed);
std::cout.setf(std::ios::showpoint);
std::cout.precision(3);
std::cout << 2.3459; // 2.346
std::cout << 30.7164; // 30.716
The syntax may look like hieroglyphics, but it’s easily translated. The first line states that fixed-point notation should be used (as opposed to the default floating-point). The second line says that the decimal point should always be displayed (for real numbers; integers never contain decimals). Finally, the precision is set as the number of digits to the right of the decimal point.
print.cpp
(Script 2.3) in your text editor or IDE.std::cout.setf(std::ios_base::fixed);
std::cout.setf(std::ios_base::showpoint);
std::cout.precision(2);
Because the order total should always have exactly two decimal places, this code is necessary. It could also be used before printing the other variables’ values.
format.cpp
.• Along with formatting the precision, you can also dictate how many spaces are used to print a variable’s value using
setw().
setw(5);
std::cout << "-" << 1 << "-";
The result will be - 1-
(with four spaces before the 1
). The spaces are known as padding in such cases.
• To change the default padding, use
std::cout.fill():
std::cout.fill('*'),
setw(5);
std::cout << "-" << 1.0 << "-";
The result will be -**1.0-
.
Type conversion is the act of changing a variable’s or literal value’s data type, say from an integer to a floating-point number. There are two kinds of type conversions. The first is implicit conversion, also called coercion, and is performed by the compiler as warranted. Common examples are when you have multiple types in an expression or calculation or when assigning data of one type to a variable of another type:
int var1 = 0;
float var2 = 8.2;
var1 = var2; // var1 equals 8
var2 = var1; // var2 equals 8.00000
The second type of conversion is explicit conversion, also called type casting. There are two different ways to forcibly cast a value:
(type) variableOrValue
type (variableOrValue)
The first format comes from C. The second format was added in C++ and only differs in syntax, not functionality (it’s meant to more clearly indicate what is being cast). As a trivial example, the following code will print just the integer 12
:
float myVar = 12.594;
std::cout << int (myVar);
As you can see from the preceding examples, type conversion inevitably changes the value of the data in the process. Specifically, it changes the returned value, not the original value, so in the preceding example, 12
is printed, but myVar
is still equal to 12.594
.
When going from a smaller data type to a larger one, this is normally not a problem. But converting from an int
to a short
or from a float
to an int
will drop some digits. For example, to take a number like 3.14
and turn it into an integer, the result will be 3
, losing the decimal values.
It should also be made clear that the conversion from a real number to an integer does not involve any rounding, so 3.9
will become just 3
. To mimic rounding, add .5
to the real number prior to the conversion:
float myVar1 = 12.594;
float myVar2 = 12.2;
int rounded = myVar1 + .5; // 13
rounded = myVar2 + .5; // 12
All of this will be demonstrated in this next example.
// cast.cpp - Script 2.5
iostream
file.
#include <iostream>
main()
function.
int main() {
unsigned int miles = 192;
float multiplier = 1.609344;
float kilometers;
This application uses one unsigned integer and two floats. The first two variables are initialized here, and the last will be assigned a value as the result of a calculation (see Step 5). The multiplier represents the conversion rate for calculating between miles and kilometers (1 mile = 1.609344 kilometers).
kilometers = miles * multiplier;
To perform the calculation, simple multiplication is involved. Because one of the values being multiplied is a real number, the resulting calculation will also be a real number, meaning that kilometers must be defined as a float. If it were defined as an integer and type casting was not used, the compiler would issue warnings (Figure 2.8).
std::cout << miles << " miles is approximately "
<< int(kilometers + 0.5) << " kilometers(s).
";
To print the calculated kilometers as an integer (instead of as a float), the value is type cast. By adding 0.5
(or just .5
) to kilometers, the returned integer will be a rounded version of the float.
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
return
line and close the main()
function.
return 0;
}
cast.cpp
.• While it’s good to be familiar with casting, you shouldn’t use it too extensively in your own code. Type conversions circumvent C++’s built-in type checking, thereby potentially introducing errors that otherwise would have been caught or avoided.
• In this example, the casting to an integer could be done within the cout
statement (as in Script 2.5) or when kilometers
is assigned a value:
int kilometers = int((miles * multiplier) + 0.5);
• You can easily see how C++ will convert from an integer to a float (adding a decimal point plus some zeros) or vice versa (dropping the fraction). When it comes to other types of casts, there are very specific rules as to how C++ will handle the data. Search online for details if the need arises (although it probably shouldn’t).
• C++ contains four other casting operators, used for more complex casting (including converting advanced types such as pointers and objects). These are: static_cast
, const_cast
, reinterpret_cast
, and dynamic_cast
. The basic syntax is
operator<type>(variable);
For example, the following code will cast a long integer to a short integer—which may cause some data to be lost—without generating warnings:
int kilometers = static_cast<int> ((miles * multiplier) + 0.5);
All of the examples to this point have used only numeric data types. But you will also need to deal with other kinds of data, including single characters or longer strings. In C++ as in C, the char
type exists as a way to store a single character. You can create a char
like any other variable:
char variableName;
Assigning values to character variables uses the assignment operator and single (straight) quotation marks:
char middleInitial;
middleInitial = 'E';
Notice that a char
variable contains only a single character.
Once you’ve assigned a value to a char
, you can print it like the other variables already discussed:
std::cout << "My middle initial is " << middleInitial << ".
";
Although char
may seem different than the types you’ve seen so far, it’s actually a small integer, one byte in size, whose range of values is -127 to 127 (signed) or 0 to 255 unsigned. C++ uses char
to store characters in a numeric format. Normally the characters represent the ASCII set, although this can differ on some machines and in international environments. In ASCII, the following lines assign the same value to the variable:
char initial = 'J';
char initial = 74;
Along with this default set of letters, numbers, and symbols, there are also characters that represent special things (Table 2.2). Of these, you’ve already seen the newline (
).
Table 2.2. These characters all have special meanings. Each uses the escape character (the backslash).
In this next, somewhat trivial, example, several characters will be printed along with their numeric equivalent.
// char.cpp - Script 2.6
iostream
file and begin defining the main()
function.
#include <iostream>
int main() {
char letter = 'N';
char tab = ' ';
char quote = ''';
It really doesn’t matter what characters you use here. The example defines one capital letter and two special escape sequences for demonstration purposes.
std::cout << "It's a question of character:
";
std::cout << letter << " is equivalent to " << int(letter) << ".
";
std::cout << tab << " is equivalent to " << int(tab) << ".
";
std::cout << quote << " is equivalent to " << int(quote) << ".
";
With each cout
statement, the character variable itself is first printed. This will be the letter N, a tab, and a single quotation mark. For each character, the numeric equivalent is also printed. This is accomplished by casting the character as an integer, so that the numeric value is sent to cout
.
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
return
line and close the main()
function.
return 0;
}
char.cpp
.• Because a char
is an integer, you can perform arithmetic on it:
char temp = 'A';
temp = temp + 1; // temp is now B
• As mentioned before, a char
requires one byte of memory. Because it is therefore smaller than even a short
integer, some programmers will use it for very small numbers.
One of the great improvements of C++ over C involves the string data type. A string is a double-quoted value, containing any combination of characters, numbers, spaces, and symbols. To use strings in C++, you must first include the string
header file, which defines all the necessary functionality.
#include <string>
To declare a variable of a string type requires a slightly different syntax because strings are actually a very different data type:
std::string variableName;
At this point, you can assign a value to the string using the assignment operator and double quotation marks:
variableName = "Hello, World!";
To build up a larger string as a combination of shorter ones, use concatenation, which is like addition for strings. It’s easy to remember, because the concatenation operator (+
) is the same as the mathematical addition operator. You’ll see an example in this next program.
// string.cpp - Script 2.7
iostream
and string
files, and then begin defining the main()
function.
#include <iostream>
#include <string>
int main() {
std::string firstName, lastName, fullName;
As a shortcut, all three variables are defined on the same line, separated by commas.
firstName = "Larry";
lastName = "Ullman";
You can, of course, use your own name here!
fullName = firstName + " " + lastName;
This is an example of concatenation, where the value of the one variable is a combination of the other two variables plus a space in the middle.
std::cout << "Hello, " << fullName << "!
";
Strings are printed like any other variable.
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
return
line and close the main()
function.
return 0;
}
string.cpp
.firstName
and lastName
variables, save the file, and then recompile and rerun the application (Figure 2.12).
• You can find the length of a string (the number of characters in it) using the size()
method.
std::cout << "The string " << stringName << " has " << stringName.size() << " characters in it.";
• In C, strings are created as an array of char
s. They are handled, even assigned values, in much different ways. Because the C++ string type is soooo much better than the old C style, we will use it exclusively in this book.
The final topic introduced in this chapter is the constant. Unlike a variable, whose value can change over the course of an application, a constant’s value never changes once it’s been set. Still, you work with a constant much as you would a variable.
Constants, like variables, are of a certain type, like int
or char
. To declare a constant, start with the keyword const
, followed by the type and name. Unlike when using variables, you must initialize a constant when you declare it.
const int QUANTITY = 7;
const float TAXRATE = 0.0725;
const char RIGHT_ANSWER = 'C';
Although it’s not required, it’s commonplace to name constants using all uppercase letters as you see in these examples. Otherwise, the naming rules for constants are the same as those for variables.
One of the best uses of constants is to have a word (the constant name) represent a magic number. Magic numbers are those that have a meaningful value that may not necessarily be clear. In this next example, the number 1.609344
is important because that’s what you’ll use to convert miles to kilometers. Rather than just hard-coding this number in your program, you can assign it to a constant that has a more meaningful name.
cast.cpp
(Script 2.5) in your text editor or IDE.const float MULTIPLIER = 1.609344;
Since this value is a static number—it should never change—it makes more sense for it to be defined as a constant.
The name is put in all capital letters to indicate its constant nature.
kilometers = miles * MULTIPLIER;
This step is necessary, as the variable multiplier
no longer exists.
miles
.constant.cpp
.• You can also define constants using a preprocessor directive, as you might in C:
#define MULTIPLIER 1.609344
But if you do this, you lose the benefit of error checking during compilation, as the compiler doesn’t validate preprocessor directives.
• In C, you can declare a constant and then assign it a value later in the program. This is not an option in C++. You must establish a constant’s value when you declare it.
• Constants are often used in programs that will frequently refer to the exact same value. Instead of hard-coding that value into the program multiple times, just use the constant. To later change the value, you’ll only need to change the one line where the constant is defined.
• Another advantage of C++ constants is that they abide by the same rules of scope as variables. This will mean more to you after you study Chapter 5, “Defining Your Own Functions.”
• In Chapter 6, you’ll see another situation where constants would be used. They are frequently established to determine the size of an array (a special type of variable).