Home | Gaming | Programming | Play Online | Contact | Keyword Query
Games++ Games & Game Programming

GAMES++
Games++ Home
Games++ Gaming
Games++ Programming
Beta Testing Games
Free Online Games
Hints & Cheats

BROWSER UTILITIES
E-mail This Page
Add to Favorites

SITE SEARCH

Web Games++

AFFILIATES
Cheat Codes
Trickster Wiki
Game Ratings
Gameboy Cheats
PlayStation Cheats
BlackBerry Games
Photoshop Tutorials
Illustrator Tutorials
ImageReady Tutorials

ADVERTISEMENT

ADVERTISEMENT

Ch 7: Grouping Data - C++ by Metrowerks

Introduction to C++ by Metrowerks

Enumerations, typedef, and More Operators

We will now take a look at a complex data type: the enumeration. Following will be a discussion of the typedef command, which allows the programmer to give the standard data types names of their choosing. Finally, we will discuss bitwide operators, the ? operator, and the , operator. These advanced operators contribute to making C++ the powerful yet flexible programming language it is.

Enumerations

An enumeration is a list of named integer constants. These constants can then be used wherever an integer can be used. The keyword enum is used to define an enumeration. Following is an example of an enumeration, fnv, and two variables defined by fnv: fruit and vegetable:

enum fnv {apple, banana, carrot, eggplant, fig} fruit, vegetable;

As in an array, the elements of an enumeration are assigned values starting with 0 and incrementing by a value of one. Given the above declaration, the following code would output "2":

vegetable = carrot;
cout << vegetable;

It is not possible to directly output the string symbol in an enumeration (such as "carrot" in the above example) -- only the integer associated with the variable. In order to output the strings, an array of strings matching the names of each integer in the enumeration must be declared so the enumeration value can serve as the index number for its corresponding string in the array.

It is possible to specify a value to an element in an enumeration. Look at the following:

enum fnv {apple, banana, carrot=5, eggplant, fig} fruit, vegetable;

The above sets the values as follows:

apple = 0
banana = 1
carrot = 5 
eggplant = 6 
fig = 7

typedef

New data type names can be defined with the typedef keyword. Using typedef does not create a new data type; it simply specifies a new name for an existing data type.

typedef float interest_rate;

The above allows the programmer to use interest_rate as an alternative to float:

interest_rate savings, cd;

Two float variables were declared: savings and cd, using the alternative name interest_rate.

It is very common in C++ programming with the more advanced types and longer names to use a typedef to improve readability.

The ternary conditional Operator

The ? operator can replace an if-else statement. For example, the following:

if (z>0) a=5;
else a=10;

can be replaced with:

a = z > 0 ? 5 : 10;

Think of it this way: "Set a equal to . . . Wait, is z > 0? If so, a = 5; if not, a = 10."

The , Operator

In a list of expressions that are separated by a comma, the expression farthest to the right is the value that will be assigned to the variable. For example, look at the following code:

b = 2;
a = (b+=5, b*b)

In this code excerpt, a is set to 49. Why? First, 5 is added to b, then b is multiplied by itself, and a is set to the rightmost value.

Multiple Assignments, sizeof, Dynamic Allocation, and Operator Precedence

We will now take a look at operator shorthand and multiple assignments. Then we will explore a compile-time operator: sizeof. Then, we will examine the new and delete operators, which are the key to dynamic memory allocation. Finally, we will review the operator precedence within C++.

Operator Shorthand and Multiple Assignments

Binary Operator Shorthand

In other code you see, you may encounter an expression that looks like the following:

b += 5;

This is programmer shorthand for:

b = b + 5;

Any binary operator can also be used in this shorthand:

b += 5;
a -= 50;
c *= d;
d = (e != 0) ? (d/=e) : (d+=e);

Multiple Assignments

Multiple assignments of the same value can be made to different variables by using a single assignment statement:

a = b = multiplier = val = 10;

This statement assigns the variables a, b, multiplier, and val all the value of 10.

The sizeof Operator

In different operating environments, variable types have different byte sizes. To determine the size of a variable type or of a specific variable, the sizeof operator can be used. When determining the size of a type, simply enclose the type name in parentheses after the operator. If you're looking for the size of a variable, no parentheses are needed.

int a;
cout << sizeof a << '\n';
cout << sizeof (int);

The output will be the same for both of these (4 in a 32-bit environment). The sizeof operator can be used on any data type. Consider the following:

float arrf [5];
cout << sizeof (float) << '\n';
cout << sizeof arrf;

Again, assuming a 32-bit environment, this should output 4 and 20. The size of a float is 4 and the size of the array is 4 * 5 or 20.

Dynamic Allocation

There is a section of the computer's memory that lies between the program itself and the data stack. This area is called the heap. Some data structures -- such as linked lists, sparse arrays, and binary trees, which you may study if you go beyond this introductory course -- use the heap to store data. In this section, you will simply be presented with the how-to of dynamic memory allocation. It will not be necessary to use this type of allocation in any programs you will work with in this course. However, should you choose to study C++ in greater depth, you will need to know the material presented here.

The Memory Allocation Operators: new and delete

To allocate memory space on the heap for a specific variable, use the new operator. For example, the following declares an integer pointer, *ptr, then allocates memory on the heap for that pointer:

int *ptr;
ptr = new int;

This memory can also be initialized according to the following code example:

ptr = new int (50);

The memory on the heap is finite. With large, complex programs, it is possible to exhaust the resources of the heap. Therefore, when a variable on the heap is no longer needed, the memory should be cleared using the delete operator:

delete ptr;

Initializing Pointers to Zero

If a pointer is deleted before it is allocated, the delete operation will be done on whatever memory address is specified whether it is valid or not. This generally will be an address of a vital area of the program and maybe even the operating system itself in older systems. To prevent this, all pointers should be initialized to zero when they are declared. This ensures that if an errant delete is called, that the program will not crash.

You can do this with a simple declaration, initialization statement

int *prt = 0;

It does not hinder future allocation.

Operator Precedence

Remember back in algebra class when you studied the Order of Operations: PEMDAS? That meant that when you had a mathematical expression, you first performed the operations in parentheses, then you addressed the exponents in the equation, then multiplication and division, and finally addition and subtraction. Well, C++ has its own order of operations; certain operators take precedence over the others. The following table shows the C++ operators (some of which we haven't covered yet) in order of precedence.

Highest

( ) [] -> .
! ~ ++ -- (type) * & sizeof 
*/ %
+ - 
<< >>
< <= > >=
== != 
&
^
|
&&
||
?:
= += -= *= /=

Lowest

,

Table 5-1: C++ operator precedence.

We are almost ready to begin the study of object-oriented programming. We'll do that in the next lesson. We will finish this lesson by examining two more compound data types (like the array). They are structures and unions.

Introduction to Structures

The first compound data type we will look at today is the structure. Like the array, the structure is a collection of variables that are referenced by a single name. Like other data types, a structure must be declared and defined before it can be used. The elements are sometimes referred to as members or fields of the structure. The members of a structure are usually related to each other.

The best way for us to look at a structure is to define one, then look at its component parts. The following is the declaration of a structure that will serve as an address/ telephone book:

struct add_ph {
    char first_name[10];
    char last_name[15];
    char phone[15];
    char address1[20];
    char address2[20];
    char city[15];
    char state[4];
    char zip[11];
} personA, personB, personC;

A structure has now been created and three variables of the type add_ph have been declared: personA, personB, personC. Don't forget, when we make the declaration char first_name[10]; we're saying that this variable will hold 10 separate items. For example, if we're using the name "Patrick," then the first_name array will hold [P, a, t, r, i, c, k, , , , ]. Same thing with char phone[10]. There are 10 digits in a phone number, so you would want to allocate 10 spaces for this array. That's easy enough, right?

Now, let's say we want to fill in the name for personA:

personA.first_name = "Joe";
personA.last_name = "Smith";

Simply use the variable name followed by a dot (.) and then the field name. How do we output the first name of personA?

int a;
for (a=0; personA.first_name[a]; a++)
    cout << personA.first_name[a];

Looks familiar, right? We're just indexing an array and outputting each character in that array. We could also just let the C++ string handlers take over, as seen below.

cout << personA.first_name;

Now for the challenge: the following is a complete address/phone book program. There are only two functions used that we haven't yet discussed: strchr(), which looks for a character in a string; and tolower(), which returns the lowercase of a character. Examine the use of the constant listings, the use of arrays, the switch statement, for loops, do-while loops, etc. Notice that instead of setting up a number of variables, as in the example, an array of structures has been declared! The array, as structured, will hold 20 listings. Notice the frequent use of the variable listings throughout the program; it is set up as a constant. That way, should the programmer wish to expand the program to hold 100, 200, or 500 listings, only one change needs to be made in the code. Be sure you understand all aspects of this program, and please ask questions if there are any parts you can't follow.

/* Address and Phone book program
    using an array of structures */
#include 
#include 
#include 
#include 
using namespace std;
const int listings = 20;
struct add_ph {
    char first_name[10];
    char last_name[15];
    char phone[15];
    char address1[20];
    char address2[20];
    char city[15];
    char use_state[4];
    char zip[11];
} entry[listings];
void change(), newentry(), show();
void initialize(), enter(), input(int);
int menu();
int main()
{
    char option;
    initialize();
    for(;;) {
        option = menu();
        switch(option) {
            case 'c': change();
                break;
            case 'n': newentry();
                break;
            case 's': show();
                break;
            case 'q': return 0;
            }
        }
    }
// Subroutine to initialize the array
void initialize()
{
    int j;
    for(j=0; j
// Subroutine for menu selection
int menu()
{
    char sel;
    cout << '\n';
    do {
        cout << "Choose from the following options:\n";
        cout << "(N)ew entry\n";
        cout << "(C)hange an existing entry\n";
        cout << "(S)how all current entries\n";
        cout << "(Q)uit\n\n";
        cout << "Make your selection: ";
        cin >> sel;
    } while (!strchr("ncsq", tolower(sel))); 
// will repeat until the user inputs any of the letters n, c, s, q
    return tolower(sel);
}
// Inputs information for new entries or updating entries
void input(int j)
{
    // char str[90];
    cout << "First name: ";
    cin >> entry[j].first_name;
    cout << "Last name: ";
    cin >> entry[j].last_name;
    cout << "Phone number: ";
    cin >> entry[j].phone;
    cout << "Address line 1: ";
    cin >> entry[j].address1;
    cout << "Address line 2: ";
    cin >> entry[j].address2;
    cout << "City: ";
    cin >> entry[j].city;
    cout << "2-letter state abbreviation: ";
    cin >> entry[j].use_state;
    cout << "Zip code: ";
    cin >> entry[j].zip;
}
// Subroutine to make new entry
void newentry()
{
    int j;
    for(j=0; j
    if (j==listings) {
        cout << "I'm sorry, the phone book is full.\n";
        return;
    }
    input(j);
}
// Subroutine to change an existing entry
void change()
{
    int j;
    char LN[50];
    cout << "Enter the person's last name: ";
    cin >> LN;
    for(j=0; j
    if(j==listings) {
        cout << "No listing found.\n";
        return;
    }
    cout << "Enter new information.\n";
    input(j);
}
// Subroutine to show the listings
void show()
{
    int j;
    for(j=0; j<< entry[j].first_name << ' ';
            cout << entry[j].last_name << '\n';
            cout << entry[j].phone << '\n';
            cout << entry[j].address1 << '\n';
            cout << entry[j].address2 << '\n';
            cout << entry[j].city << ", ";
            cout << entry[j].use_state << ' ';
            cout << entry[j].zip << "\n\n";
        }
    }
}

Examine this program very closely. Make sure you understand what every line does before you go on. There is a lot of information in this program, as it is the culmination of everything we have studied thus far. When you feel you understand every part of the program, move on.

Working With Structures

We will now discuss some basic operations that can be performed on structures.

Passing Structures to Functions

A structure can be passed to a function as an argument of that function. When this occurs, the entire structure is passed using the call-by-value method of argument passing. Therefore, it is not possible for the function to make changes to the contents of the structure.

Assigning Structures

The contents of one structure can be assigned to another structure. In our sample program, if we wanted to copy a record into another, we could do the following:

entry[2] = entry[1];

The contents of entry[1] will be assigned to entry[2].

Note: In order to assign strings, you use a strcpy function whether in a struct or just simple char arrays.

Pointers to Structures

As you can imagine, passing a whole structure to a function can be a tedious task. The best way is to assign a pointer to a structure, then pass the pointer. To assign the address of entry[1] to a pointer, p, we use the same method of assigning addresses as we have used in the past:

p = &entry[1];

You can then access a member of the structure using the arrow operator:

p->first_name;

If you are not using a pointer to a structure, then you would use the dot operator to access the members of a structure:

struct add_ph p;
p.first_name;

Unions

A union is a memory location shared by two or more different variables. Unions, in effect, provide low-level polymorphism -- they allow a single interface to work with several types of data. The union sets aside enough memory to hold the largest data type in the union's declaration:

union test_union {
    int a;
    char c;
    float f;
} var1, var2;

As you can see, the declaration of a union is similar to that of a structure. The union will be large enough to hold a float variable, even though an int or a char doesn't require as much memory. As with a structure, to access or reference a union element, use the dot operator. To access an element with a pointer, use the arrow operator.

Look at the following program, and then review the output to see how unions operate:

#include 
using namespace std;
int main()
{
    union test_union {
        short int i;
        char ch[2];
    } unvar;
    unvar.ch[0] = 'X';
    unvar.ch[1] = 'Y';
    cout << "Characters: " << unvar.ch[0] << unvar.ch[1] << '\n';
    cout << "Integer: " << unvar.i << '\n';
    return 0;
}

The output from this program will look like this:

Characters: XY
Integer: 22872

Anonymous Unions

The above program can be rewritten using what is called an anonymous union :

#include 
using namespace std;
int main()
{
    union {
        short int i;
        char ch[2];
    };
    ch[0] = 'X';
    ch[1] = 'Y';
    cout << "Characters: " << ch[0] << ch[1] << '\n';
    cout << "Integer: " << i << '\n';
    return 0;
}

As you can see, using an anonymous union allows direct access to the variables within the union without use of the dot or arrow operators.

Using sizeof on Structures and Unions

When trying to determine the size of a structure or union, do not manually add the component parts. Instead, the sizeof operator should be used. In the first union program above, the following can be used:

sizeof unvar;

Next Lesson

Copyright © 1998-2007, Games++ All rights reserved. | Privacy Policy