C++ Lab 2 - Pointers, References, Strings

Download the example programs from this page or copy them from the course home page to your directory for this lab as follows (assuming you are currently in the directory):
    cp ~cpsc/public_html/Spring2010/CPSC270A/lab2/*.cc .

References and Pointers

Recall that in Java when you declare a variable to be some object type then the variable is actually a reference to the object, that is, it contains the address of the object rather than the object itself. So for example, if you have a Node class, then the declaration
    Node myNode;
would declare myNode to be a reference (currently null) to a Node object. The actual object would be created using the new operator. In C++, the above declaration would create the actual Node (no new would be needed).

To declare a reference (pointer) to an object we use *. The following declaration declares myNodePtr as a pointer to a Node:

     Node * myNodePtr;
The actual node would be constructed using the new operator as follows:
     myNodePtr = new Node;

You can also use * and new on primitive data types such as int. The following allocates space in memory for an int and assigns intPtr to point to it.

   int * intPtr = new int;
To access the actual value of the integer you need to use the operator * to dereference the pointer - *intPtr is the value of the integer in the location pointed to by intPtr.

The & operator gives the address of a variable. Some examples using * and &:

    myNodePtr = &myNode;  

    int * numPtr = new int;
    int num = 5;
    cout << &num << " an address!";  //prints the address of num

    *numPtr = 13;   // *numPtr is the contents of the location pointed
                    // to by numPtr - * is "dereferencing" numPtr

The program PointerFun.cc illustrates some of the properties of the & ("address of") operator and the * operator (when used to declare and when used to dereference a pointer variable). Study it then compile and run it.

Dynamic Arrays

To create arrays dynamically at runtime you need to use a pointer and new to allocate the space needed. The following declares a to be a pointer and allocates space in memory for n ints.
      int * a = new int[n];

The program DynamicArray.cc illustrate this. Try it.

Problems with memory when using dynamic allocation: In C++ space allocated remains allocated to your process unless you explicitly free it. There is no automatic garbage collection as there is in Java. The delete command is used to place the memory allocated to a pointer back on free store.

     delete numPtr;   // returns the space for the int pointed to by numPtr

     delete [] a;     // frees the space for the array pointed to by a

The program ArrayMemory.cc illustrates the problem with allocating lots of space without freeing it. Follow the instructions below to run the program, examining memory as it runs. The program pauses for input so you can see how much memory is being used.

Parameter Passing

The default mode of parameter passing in C++, as in Java, is pass by value. Parameters passed this way are not changed by the function (method). But in Java, because the "value" of an object variable is a reference, the reference isn't changed but the object it refers to can be changed. An array in C++ is actually a pointer to the first element in the array. Thus, in the double every other element example you were able to change the actual array.

To pass a parameter by reference in C++ you use the ampersand in the header for the function. So, the following would pass the first two parameters by reference and the third one by value:

     void doStuff (int& a, int& b, int c)
     {
        c = c * 2;
        a = a + c;
        b = b - c;
     }
A call to the function would just use the int variables for the actual parameters - the address of the first two would be passed. For example,
       int m = 150;
       int n = 100;
       int p = 5;
       doStuff(m,n,p);
Note: It is standard practice to just list the type of each parameter in the declaration (when it is separate from the definition) - in this example you would put
      void doStuff (int&, int&, int)

This code is in ReferenceParameters.cc. Run it to make sure you understand what happens and how reference and value parameters differ.

Strings in C++

A string in C++ is an array of characters (type char) that has the null character (escape sequence \0) at the end. The null character is automatically added to the characters in a string when the string is read in or is assigned as a literal. The program StringBasics.cc gives an example. This program uses two functions provided by C++ - the sizeof function can be applied to any variable to find out how much space (number of bytes) the variable occupies. The function strlen is a function in the standard library that gives the number of characters in the string.

The program also uses the function strcpy to copy one string to another. Note that the first argument is the destination, the second is the string to be copied. This function (or a loop where you copy character by character) should be used when you need to copy. You cannot use assignment.

Compile and run the program. Note that for the string literal the number of bytes is one more than the number of characters - that accounts for the null character. For the string you typed in, the number of bytes is the number declared for the array.

Exercise:

  1. See what happens when you try assigning strings. There is already a declaration for string3 in the program. Add an assignment statement to assign string3 to be the same as string1. Try compiling and see what the error message is.

  2. Now change your assignment to assign string3 to be the same as string2. Try compiling. This is a more general error message that applies to any type of array in C++.

  3. Now try assigning string3 to be a literal. What happens?

  4. Use strcpy to assign string3 to be a literal. Does it work?

Reading in Strings

If you didn't already do it run the program above again entering a string with more than one word. Do it again putting several white space characters in front of the sentence. What happened?

You should have noticed that cin skips over whitespace and stops reading at whitespace. So it doesn't work to read a whole line that may contain spaces. To do that you need to use one of the functions get or getline that operate on cin.

The program ReadStrings.cc reads in two lines of text and prints them. Note the alternate syntax for using get and getline.

Exercise:

  1. Study the code then compile and run the program.
  2. Comment out the line that adds the null character. Run the program at least twice:
    1. Enter a shorter string for the second input than the first. What happened?
    2. Enter a longer string for the second but less than the maximum length. What happened?

The point - if you create your own string character by character you must explicitly add the null character to the end.

Char

Variables and literals of type char can be manipulated just as in Java. Casting to an int gives the ASCII code and casting an int to char gives the character. The program Frequency.cc reads in a string character by character and determines the frequency of each letter in the alphabet. Study the code to be sure you understand it. Compile and run.

The string class

To use the C++ library string you need to add the INCLUDE preprocessor directive. The class is in the std namespace as is iostream so you do not need an additional using statement. Some of the functions provided in the library are length, find, substr, replace, and insert. The example program StringClass.cc uses some of these. Run it to see how it works. In particular, figure out the following:
  1. The substr function is not the same as Java's substring method. What does the second argument to substr represent? How does this differ from Java?
  2. What happens if you request a substring starting at an index that is out of bounds?
  3. What happens if you request a substring starting at an index that is in bounds but you request more characters than are in the string from that index to the end?

Homework - Due, Wednesday, February 3

  1. Write a C++ program that implements the string-matching algorithm referred to in problem #3 on page 24. Use a function that is called from main for your algorithm. In particular your program should take in a line of text and another string (which may contain spaces). It should return the index of the first character in the string if the string is found in the text or -1 if the string is not in the text. Note: You only need to find the first instance of the string in the case that it appears more than once.

  2. Write a C++ program that implements an anagram checking algorithm (problem #10 on page 39). You may assume the two strings have no whitespace.