12: Strings

What We Will Cover


Continuations

Questions from last class?

Homework Questions?

  • Exercise 11 (5/10/07)

12.1: Using C-Strings

Objectives

At the end of the lesson the student will be able to:

  • Initialize C-strings
  • Use C-string library functions
  • Perform I/O on C-strings
  • Convert C-strings to numbers

12.1.1: About C-Strings

  • Previously we discussed arrays, including arrays of type char
  • C++ offers a special kind of char array known as a C-string
    • Included from the C programming language
  • Many library functions use C-strings
    • Thus we still need to use C-strings

How C-Strings Work

  • C-strings are an array of char values
  • Each char is stored in the array with a special null character '\0' ending the string
    • The null character is a control character like '\n'
    • You cannot actually view the character
  • For example, a char-array of size 10 used to store a C-string would look like:

12.1.2: Declaring and Initializing C-Strings

  • You can declare and allocate a C-string like a char array but with one important difference:
  • char arrayName[MaximumCStringSize + 1];
  • The "+ 1" reserves the additional space needed by '\0'
  • You can initialize a C-string using double quotes
  • For example:
  • char s[10] = "Hi Mom!";
    cout << s << endl;
    
  • Note that declaring a C-string as char s[10] creates room for only 9 char's
    • The null character terminator requires one space
  • The size variable is actually optional for a C-string
  • For example:
  • char shortString[] = "abc";
    cout << shortString << endl;
    
  • This will create a C-string of size 4 terminated with a '\0'
  • What is wrong with the following declaration?
  • char shortString2[] = {'a', 'b', 'c'};
    cout << shortString2 << endl;
    

C-String Declarations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main() {
    char s[10] = "Hi Mom!";
    cout << s << endl;

    char shortString[] = "abc";
    cout << shortString << endl;

    char shortString2[] = {'a', 'b', 'c', '\0'};
    cout << shortString2 << endl;

    return 0;
}

12.1.3: Iterating C-Strings

  • You can iterate through a C-string like you can for a char array
  • However, you need an appropriate ending condition
  • You must be careful not to replace the null character ('\0')
  • If the null character is lost, the array cannot act like a C-string
  • What could you change in the following to still process the array correctly in case the null character was missing?

C-String Iterations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int main() {
    char myString[] = "Hello World!";
    cout << myString << endl;

    int index = 0;
    while (myString[index] != '\0') {
        myString[index] = 'X';
        index++;
    }
    cout << myString << endl;

    return 0;
}

12.1.4: Performing I/O on C-Strings

  • C-strings can be output with the insertion << operator
  • For example:
  • char news[] = "C-strings";
    cout << news << " Wow." << endl;
    
  • The extraction operator >> can fill a C-string
  • For example:
  • char a[80], b[80];
    cout << "Enter input: " << endl;
    cin >> a >> b;
    cout << a << b << "End of Output";
    
  • Note that whitespace ends reading of the data
  • To read an entire line you can use function getline() of the object cin
  • Syntax:
  • cin.getline(cString, maxSize + 1);
  • cin.getline() has two arguments
    • The first is a C-string variable to store input data
    • The second specifies the maximum number of char's to read
  • For example:
  • char line[80];
    cout << "Enter a line of input:\n";
    cin.getline(line, 80);
    cout << line << "END OF OUTPUT\n";
    
  • cin.getline() stops reading after the maximum number of char's - 1 is read
    • one character is reserved for the null character
    • cin.getline() stops even if the end of the line has not been reached
  • C-string input and output works the same way with file streams
  • fin >> cString;
    fin.getline(cString, 80);
    
  • Similarly, you can use an output file stream like you use cout
  • fout << cString;

12.1.5: Using C-String Library Functions

  • Note that the following statement produces a compiler error:
  • char aString[11];
    aString = "Hello";
    
  • The assignment operator does not work with C-strings
  • Instead, programmers use library function strcpy() to assign characters
    • Defined in the cstring library
    • Included automatically by our compiler
  • For example:
  • char aString[11];
    strcpy (aString, "Hi Mom!");
    cout << aString << endl;
    
  • Function strcpy() automatically appends the '\0' character to the C-string
  • Note that strcpy() does not know the length of the first char array
  • Thus, strcpy() can write characters beyond the declared size of the array
  • Many versions of C++ have a safer version of strcpy() named strncpy()
  • strncpy() uses a third argument for the maximum number of char's to copy
  • For example:
  • char anotherString[10];
    strncpy(anotherString, aString, 9);
    cout << anotherString << endl;
    
  • Copies up to 9 characters into another_string, leaving one space for '\0'
    • However, it does not put the '\0' in the array if it stops copying before the end of the string
  • The == operator does not work as you might expect with C-strings
    • You only compare the base address of the two arrays
  • Instead, programmers use strcmp() to compare the content of C-strings
  • For example:
  • #include <cstring>
    
    if (strcmp(cString1, cString2)) {
        cout << "Strings are not the same.";
    } else {
        cout << "String are the same.";
    }
    
  • strcmp() compares the char codes in the two C-strings one char at a time
  • As soon as the characters do not match:
    • Returns a negative value if the code in the first parameter is less
    • Returns a positive value if the code in the second parameter is less
  • If the two C-strings are the same, strcmp() returns 0
  • strlen() is another cstring library function that returns the number of characters in a string
  • int x = strlen(aString);
  • strcat() concatenates two C-strings
    • The second argument is added to the end of the first
    • The result is placed in the first argument
  • For example:
  • char stringVar[20] = "The rain";
    strcat(stringVar, "in Spain");
    
  • Now stringVar contains "The rainin Spain"
  • strncat() is a safer version of strcat()
    • A third parameter limits the number of characters to concatenate
  • For example:
  • char stringVar[20] = "The rain";
    strncat(stringVar, "in Spain", 11);
    

Further Information

12.1.6: C-Strings as Arguments and Parameters

  • C-string variables are arrays
  • C-string arguments and parameters are used just like arrays
  • Like other arrays, be careful with the array size
  • If a function changes the value of a C-string parameter
    • Best to include a parameter for the declared size of the C-string
  • If a function does not change the value of a C-string parameter
    • You can use the null character to detect the end of the string
    • No size argument is needed

12.1.7: Converting C-Strings to Numbers

  • "1234" is a string of characters
  • 1234 is a number
  • Sometimes you need to convert C-strings to numbers
  • For instance, you may need to read string data because:
    • Reading money may involve a dollar sign
    • Reading percentages may involve a percent sign
  • To read numbers as characters:
    1. Read input as characters into a C-string
    2. Remove unwanted characters
    3. Use a conversion function to convert the C-string to a numeric value
  • The conversion functions are found in the library cstdlib
  • To use the functions use the include directive
  • #include <cstdlib>
  • The most used functions: atoi(), atol() and atof()
  • Function atoi() converts a C-string to an int value
  • int x = atoi("1234");  // returns 1234
    int x = atoi("#1234"); // returns 0 because # is not a digit
    
  • Function atol() converts a C-string to a long value
  • long y = atol("1234"); // returns 1234 as a long
  • Function atof() converts a C-string to a double value
  • double z = atof("9.99");  // returns 9.99
    double w = atof("$9.99"); // returns 0.0 because $
                              // is not a digit
    

12.1.8: Summary

  • C++ offers a special kind of char array known as a C-string
    • Has the same shortcoming as arrays
    • You need to know about C-Strings because you often have to work with them
  • Each char is stored in the array with a special null character '\0' ending the string
  • Syntax:
  • char ArrayName[MaximumCStringSize + 1];
  • C-strings can be output with the insertion << operator
  • The extraction operator >> can fill a C-string
  • To read an entire line you can use function cin.getline()
  • Syntax:
  • cin.getline(cString, maxSize + 1);
  • You can iterate a C-string like an array
  • int index = 0;
    while (ourString[index] != '\0' && index < SIZE) {
        ourString[index] = 'X';
        index++;
    }
    
  • To assign C-strings, use the cstring library function strcpy()
    • A safer version of strcpy() is named strncpy()
  • Programmers use strcmp() to compare the contents of C-strings
  • strlen() returns the number of characters in a string
  • strcat() concatenates two C-strings
  • strncat() is a safer version of strcat()
  • C-string variables are arrays
  • C-string arguments and parameters are used just like arrays
  • To convert C-strings to numbers, use a conversion function
    • Function atoi() to converts a C-string to an int value
    • Function atol() to converts a C-string to a long value
    • Function atof() to converts a C-string to a double value

Check Yourself

  1. What is a C-string?
  2. What is the ending character for a C-string?
  3. What code do you write for user I/O using C-string variables?
  4. What code do you write to copy a C-string variable?
  5. What code do you write to compare two C-strings?
  6. What functions can you use to convert a C-string to an int? double?

Exercise 12.1

Specifications

  1. Save the following code as readcstr.cpp
  2. Write a program that reads a line of text as a C-string and prints the line vertically (one character at a time) down the page
  3. As a comment in your code, answer the following question:
  4. Q1: How large should you make the C-string? Why?

  5. Your source code is the solution to this exercise.
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main() {
    // Enter code here

    return 0;
}

12.2: String Class

Objectives

At the end of the lesson the student will be able to:

  • Use string constructors and member functions

12.2.1: Using Strings: A Review

  • The string class allows a programmer to use strings as a basic data type
  • Defined in the string library and standard namespace
  • #include <string>
    using namespace std;
    
  • Included automatically with our version of g++
  • Strings are stored in a character sequence starting at 0 (zero)
  • String variables and expressions are treated much like simple types
  • You can assign C-strings to string objects using the assignment operator
  • string s1 = "Hello Mom!";
  • Also, you can assign string objects to a string object
  • string s1, s2, s3;
    s1 = "Hello ";  // assignment
    s2 = "Mom!";
    s3 = s1 + s2;   // concatenation
    cout << s3 << endl;
    
  • Will the following code compile and run? Why or why not?
  • string s = "abc" + "def";
    cout << s << endl;
    
  • Will this code compile and run? Why or why not?
  • string s = "abc";
    s = s + "def" + "ghi";
    cout << s << endl;
    
  • Recall that you can easily convert a string to a C-string using c_str():
  • string str = "Hi Mom!";
    char cstr[80];
    strcpy(cstr, str.c_str());
    cout << cstr << endl;
    
  • Comparison operators work with string objects
  • == returns true if two string objects contain the same characters in the same order
  • For example:
  • string s1, s2;
    s1 = "Hello World!";
    s2 = "Hello World!";
    cout << (s1 == s2);
    
  • <, >, <=, >=, != can be used to compare string objects as well

12.2.2: Constructors of Class string

  • Since string is a class type, it has constructors
  • The default string constructor initializes the string to the empty string
  • string phrase; // empty string
  • Another string constructor takes a C-string argument
  • string noun("ants");
    cout << noun << endl;
    

12.2.3: Indexing a String

  • You can access any individual character of a string object using [ ]
  • For example:
  • string line;
    cout << "Enter your name: ";
    getline(cin, line);
    cout << "The first letter is:  " << line[0] << endl;
    
  • What happens if we try to display line[100]?
    • Buffer overflow is a major source of errors and security flaws
  • Member function at accesses an individual character as well
  • cout << "The first letter is:  "
         << line.at(0) << endl;
    
  • However, at checks for valid index values
  • When an invalid index is found, the program provides an error message and aborts
  • For example:
  • cout << "The first letter is:  "
         << line.at(100) << endl;
    
    
  • Produces a message like:
  • 5 [sig] fiddle 2272 open_stackdumpfile: Dumping stack trace to fiddle.exe. stackdump

  • Which is better: An error message or a security flaw?

Further Information

12.2.4: Iterating Strings

  • Member function length() returns the number of characters in the string object
  • string s = "abcdef";
    unsigned n = s.length();
    
  • After we know the length, it is easy to iterate through the individual characters of a string
  • string s = "abcdef";
    for (unsigned i = 0; i < s.length(); i++) {
        cout << "Char[" << i << "]: " << s.at(i) << endl;
    }
    

12.2.5: Finding Substrings

  • Sometimes you want to know if a string contains a certain word
  • For this you can use the find() member function
  • Syntax:
  • unsigned int haystack.find(needle)
    
  • Searches for the string or char needle in the string haystack
  • Returns the index of the first occurrence of needle or string::npos if not found
  • For example
  • string str = "Do you want to play again?";
    unsigned n = str.find("you");
    if (n == string::npos) {
        cout << "Could not find \"you\" in the str\n";
    } else {
        cout << "We found \"you\" in the str\n";
    }
    

12.2.6: Erasing and Inserting Substrings

  • Sometimes you want to erase or insert parts of a string
  • To erase parts of a string, you can use the erase() member function
  • Syntax:
  • str.erase(start, length)
    str.erase(start)
    
  • The first line removes all the characters between start and start + length
  • The second line removes all the characters from start through the end of the string
  • To insert characters into a string, use the insert() member function
  • Syntax:
  • str.insert(start, newStr)
    
  • Inserts the string newStr starting at position start
For Example
string str("Game over");
cout << str << endl;
str.erase(4, 5);
cout << str << endl;
str.insert(0, "I'm ");
cout << str << endl;

12.2.7: Summary

  • The string class allows the programmer to use strings like a primitive type
  • Strings are stored in a character sequence starting at 0 (zero)
  • You can construct string objects like other class types
  • string noun("ants");
  • You can also assign C-strings to strings using the assignment operator
  • string s1 = "Hello Mom!";
  • You can concatenate (join) strings with the '+' operator
  • string s3 = s1 + " " + s2;
  • Comparison operators work with strings: ==, !=, <, >, <=, >=
  • You can access individual characters of a string using [] or member function at
  • You should use member function at because it checks for valid index values
  • line.at(0);
  • You can iterate through a string using a loop and the length() member function
  • string s = "abcdef";
    for (unsigned i = 0; i < s.length(); i++) {
        cout << "Char[" << i << "]: " << s.at(i) << endl;
    }
    
  • You can find characters in a string using the find() member function
  • string str = "Do you want to play again?";
    unsigned n = str.find("you");
    
  • You can erase and insert characters in a string as well
  • string str("Game over");
    cout << str << endl;
    str.erase(4, 5);
    cout << str << endl;
    str.insert(0, "I'm ");
    cout << str << endl;
    

Check Yourself

  1. Is a string a primitive type or a class type?
  2. What is the ending character for a C-string?
  3. What code do you write for user I/O using string variables?
  4. What code do you write to copy a string variable?
  5. What code do you write to compare two string variables?
  6. What code do you write to access a single character of a string variable?
  7. What code do you write to determine the length of a string variable?
  8. What function do you use to find a substring in a string variable?
  9. What function do you use to erase characters from a string variable?
  10. What function do you use to insert characters into a string variable?

Exercise 12.2

Specifications

  1. Save the following code as triplex.cpp.
  2. Write code that replaces every third letter of the string line with an 'X'.
  3. Your source code is the solution to this exercise.
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main() {
    string line;
    cout << "Enter a line of text: ";
    getline(cin, line);
    // Enter code here

    return 0;
}

12.3: Pointers

Objectives

At the end of the lesson the student will be able to:

  • Declare pointers and initialize pointer variables
  • Code basic pointer operations
  • Describe dynamic memory management

12.3.1: Pointer Variables

  • Pointer variables (pointers) store memory addresses rather than actual values
  • Pointers "point" to a variable by telling where the variable is located
  • Recall that memory addresses are numbered locations
  • Pointer variables store these memory address
  • You have used pointers already!
    • Call-by-reference parameters
    • Address of actual argument was passed
  • Pointers increase the capabilities of the C++ programs you write
  • Using pointers, you can control low-level memory operations of a computer
  • However, this low level control has a price as well
  • It is possible to create errors that can crash a program or even freeze a computer

Declaring Pointers

  • Pointer variables must be declared as a pointer type
  • For example, to declare a pointer variable named ptr:
  • double *ptr;
  • The asterisk (*) identifies the variable ptr as a pointer
  • You can declare multiple pointers in one statement:
  • int *p1, *p2, v1, v2;
  • p1 and p2 point to variables of type int
  • v1 and v2 are variables of type int

12.3.2: Assigning Values to Pointers

  • You can use the "address of" operator (&) to assign addresses to pointers
  • For example:
  • p1 = &v1;
  • p1 is now a pointer to v1
  • v1 can be called either v1 or "the variable pointed to by p1"

Addresses and Numbers

  • A pointer is a memory address and you can display an address using cout
  • cout << p1 << endl;
  • Memory addresses are shown in a hexadecimal format

Example Assigning Values to Pointers

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main() {
    int *p1, *p2, v1, v2;
    p1 = &v1;
    p2 = &v2;
    cout << p1 << endl;
    cout << p2 << endl;

    return 0;
}

12.3.3: The Dereferencing Operator

  • C++ uses the * operator in yet another way with pointers
  • The phrase "The variable pointed to by p" is translated into C++ as "*p"
    • Here the * is known as the dereferencing operator
    • p is said to be dereferenced
  • When you dereference a pointer, you can use it like an actual variable
  • For instance, you can assign a value to a dereferenced variable like the following example

Example Using Pointer Dereferencing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int main() {
    int *p1, *p2, v1, v2;
    v1 = 1234;
    v2 = 0;
    p1 = &v1; // v1 and *p1 now refer to the same variable
    p2 = &v2;
    *p2 = 42; // dereferenced pointer assigned a value
    cout << "v1=" << v1 << endl;
    cout << "*p1=" << *p1 << endl;
    cout << "v2=" << v2 << endl;
    cout << "*p2=" << *p2 << endl;

    return 0;
}

12.3.4: Using the Assignment Operator

  • You can use the assignment operator (=) to assign the value of one pointer to another
  • For example, if p1 still points to v1:
  • p2 = p1;
  • Now *p2, *p1, and v1 all refer to the same variable
  • Be careful when making assignments to pointer variables:
  • p1= p2;    // changes the location to which p1 "points"
    
    *p1 = *p2; // changes the value at the location to which
               // p1 "points"
    
  • Pointer Assignment: from the textbook p. 504

Example: Pointer Assignment vs. Dereferenced-Pointer Assignment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;

int main() {
    int *p1, *p2, v1, v2;

    cout << "First example:" << endl;
    p1 = &v1;
    p2 = &v2;
    *p1 = 84;
    *p2 = 99;
    p1 = p2;
    cout << p1 << "=" << *p1 << endl;
    cout << p2 << "=" << *p2 << endl;

    cout << "\nSecond example:" << endl;
    p1 = &v1;
    p2 = &v2;
    *p1 = 84;
    *p2 = 99;
    *p1 = *p2;
    cout << p1 << "=" << *p1 << endl;
    cout << p2 << "=" << *p2 << endl;
    return 0;
}

12.3.5: Dynamic Variables

  • Using pointers, variables can be manipulated even without an identifier for them
  • For example, to create a pointer to a new "nameless" variable of type int:
  • int *p1 = new int;
  • The new variable is referred to as *p1
  • You can use *p1 anyplace you can use an integer variable
  • cin >> *p1;
    *p1 = *p1 + 7;
    
  • Variables created using the new operator are called dynamic variables
  • Dynamic variables are created and destroyed while the program is running
  • Dynamically creating and destroying variables is called dynamic memory management

Example Demonstrating Pointers and Dynamic Variables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;

int main() {
    int *p1, *p2;

    p1 = new int;
    *p1 = 42;
    p2 = p1;
    cout << "*p1 == " << *p1 << endl;
    cout << "*p2 == " << *p2 << endl;

    *p2 = 53;
    cout << "*p1 == " << *p1 << endl;
    cout << "*p2 == " << *p2 << endl;

    p1 = new int;
    *p1 = 88;
    cout << "*p1 == " << *p1 << endl;
    cout << "*p2 == " << *p2 << endl;

    cout << "Hope you got the point of this example!\n";
    return 0;
}

12.3.6: Dynamic Class Variables

  • Using operator new with class types calls a constructor as well as allocating memory
  • If Product is a class type, then:
  • // Create a pointer to a variable of type Product
    Product *prodPtr, *milkPtr;
    // Call the no-parameter constructor
    prodPtr = new Product;
    // Call Product(string, double);
    milkPtr = new Product("Milk", 2.99);
    

Calling Functions

  • To call a function of an object pointed to by a pointer, you must first dereference the pointer
  • // Dereferencing object variables
    (*prod).show();
    (*milk).show();
    
  • Note that a dereference operator has a lower precedence than a dot (.) operator
  • Thus you need to enclose the dereference operation in parenthesis
  • Since using parenthesis requires extra typing, C++ has a special pointer operator: ->
  • Using "pointer notation" for the above:
  • // Using pointer notation
    prod->show();
    milk->show();
    

Dynamic Memory Management

  • C++ programs reserve an area of memory called the freestore or heap
  • New dynamic variables use memory in the freestore
  • If all of the freestore is used, calls to new will fail
  • You can delete and recycle memory that is no longer needed
  • The delete operator returns memory to the freestore
  • For example:
  • // Free up memory
    delete prod;
    delete milk;
    
  • Memory used by the variable that ptr pointed to is released to the freestore
  • The value of ptr is now undefined
  • Using delete on a pointer variable destroys the dynamic variable pointed to
  • If another pointer variable was pointing to the dynamic variable, that variable is also undefined
  • Undefined pointer variables are called dangling pointers
  • Dereferencing a dangling pointer (*milk) is usually disastrous
  • To prevent this, you should set the pointer variables to NULL after you delete them
  • // Make sure we cannot use again
    prod = NULL;
    milk = NULL;
    
  • Now trying to use the pointer variables will cause an exception like:
  • 3 [main] ptrclass 2316 handle_exceptions:
        Exception: STATUS_ACCESS_VIOLATION
    2095 [main] ptrclass 2316 open_stackdumpfile:
        Dumping stack trace to ptrclass.exe.stackdump
    
  • Then you will know you have made an error rather than the program working part of the time

Example Creating Dynamic Objects

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include "Product.cpp"
using namespace std;

int main() {
    Product *prod, *milk;

    // Create two Product objects using pointers
    prod = new Product;
    milk = new Product("Milk", 2.99);

    // Dereferencing object variables
    (*prod).show();
    (*milk).show();

    // Using "pointer" notation
    prod->show();
    milk->show();

    // Free up memory
    delete prod;
    delete milk;

    // Make sure we cannot use again
    prod = NULL;
    milk = NULL;
    milk->show();

    return 0;
}

Product Class File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
using namespace std;

class Product {
public:
    // Constructors
    Product();
    Product(string newName);
    Product(string newName, double newPrice);
    // Member functions
    string getName() { return name; }
    double getPrice() { return price; }
    void setName(string newName);
    void setPrice(double newPrice);
    void show();
private:
    // Member variables
    string name;
    double price;
};

// no-parameter constructor
Product::Product() {
    name = "Unknown";
    price = 0.0;
}

Product::Product(string newName) {
    setName(newName);
    price = 0.0;
}

Product::Product(string newName, double newPrice) {
    setName(newName);
    setPrice(newPrice);
}

void Product::setName(string newName) {
    if (newName.length() == 0) {
        name = "Unknown";
    } else {
        name = newName;
    }
}

void Product::setPrice(double newPrice) {
    if (newPrice > 0.0) {
        price = newPrice;
    } else {
        price = 0.0;
    }
}

void Product::show() {
    cout <<  name << " has a price of $"
         << price << endl;
}

12.3.7: Summary

  • Pointer variables (pointers) store memory addresses rather than actual values
  • The memory address is where a variable (or other data) is stored
  • Pointers "point" to a variable by telling where the variable is located
  • Using pointers, you can control low-level memory operations of a computer
  • To declare a pointer, use an asterisk operator
  • double *ptr;
  • You can use the "address of" operator (&) to assign addresses to pointers
  • p1 = &v1;
  • You can also use the asterisk operator to dereference pointers
  • *p1 = 42;
  • You can use the assignment operator = to assign the value of one pointer to another
  • p2 = p1;
  • Which should not be confused with:
  • *p1 = *p3;
  • You can create dynamic variables using the new operator
  • p1 = new int;
  • To destroy dynamic variables, use the delete operator
  • delete p1;
  • Also, you can create dynamic object variables

Check Yourself

  1. What is a pointer?
  2. What is the syntax for declaring a pointer variable?
  3. What does the "address of" operator return?
  4. How do you assign the value of one pointer to another?
  5. In the following code, what operation does the "*" perform?
  6. *p1 = 42;
  7. How do you create a new dynamic variable?
  8. How do you delete a dynamic variable?

Exercise 12.3

In this exercise we explore declaring dynamic variables.

Specifications

  1. Save the following code file as mypointers.cpp.
  2. Write a declaration for a variable called numberPtr that points to integer values.
  3. Assign the value 54 to the numberPtr variable.
  4. Write a declaration for a variable called charPtr that will point to character values.
  5. Assign the value 'a' to the charPtr variable.
  6. Write code to display on the screen both dynamic variables.
  7. Your source code is the solution to this exercise.
1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;

int main() {
    // Declaration for a variable called numberPt

    // Declaration for a variable called charPtr

    return 0;
}

12.4: Dynamic Arrays

Objectives

At the end of the lesson the student will be able to:

  • Describe the similarities between array variables and pointers
  • Use dynamic arrays in programs

12.4.1: Arrays and Pointers

  • Array variables are really pointer variables
  • Recall that array elements are stored sequentially in memory addresses
  • An array variable 'points to' the first indexed variable
  • Thus an array variable is a kind of pointer variable
  • For example:
  • int a[] = { 1, 2, 3, 4, 5 };
    int *p;
    
  • Both a and p are pointer variables
  • You can assign a to p
  • p = a;
    
  • Variable p now points where a points
  • Now you can use array brackets with pointer variable p
  • p[0] = 10;
    
  • Note that variable a cannot be changed because it is a constant variable
  • a = p;  // ILLEGAL!
    

Example Assigning an Array to a Pointer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;


int main() {
    int a[] = { 1, 2, 3, 4, 5 };
    int *p;

    p = a;
    p[0] = 99;

    for (int i = 0; i < SIZE; i++) {
        cout << p[i] << endl;
    }

    return 0;
}

12.4.2: Creating and Deleting Dynamic Arrays

  • Arrays are limited because you must set the size before you run your program
  • You do not always know the size your program will need
  • The best you can do is estimate the maximum size
  • You can use dynamic arrays to get around this limitation

Creating Dynamic Arrays

  • To create a dynamic array, you use the new operator
  • const int SIZE = 5;
    int *p = new int[SIZE];
    
  • Creates a dynamically allocated array of 5 elements with a base type of int

Accessing Array Elements

  • Once a dynamic array is declared, you use it like a non-dynamic array
  • for (int i = 0; i < SIZE; i++) {
        p[i] = i * 2 + 1;
        cout << p[i] << endl;
    }
    

Deleting Dynamic Arrays

  • Since a dynamic array is allocated dynamically at run-time, you need to delete it when finished
  • This de-allocates all memory for the dynamic array
  • delete [] p;
  • Use brackets to Brackets indicate you are deallocating an array type
  • Since p still points to the location in memory, you should set p = NULL
  • p = NULL;
    

Example of a Dynamic Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;

const int SIZE = 5;

int main() {
    // Declaring a dynamic array
    int *p = new int[SIZE];

    // Accessing a dynamic array
    for (int i = 0; i < SIZE; i++) {
        p[i] = i * 2 + 1;
        cout << p[i] << endl;
    }

    // Deleting a dynamic array
    delete [] p;
    p = NULL;

    return 0;
}

12.4.3: Using Dynamic Arrays with Functions

  • Recall that array types are NOT allowed as the return-type of function
  • int [] someFunction(); // ILLEGAL!
    
  • However, you can return a pointer from a function
  • Thus, you can return a pointer to an array base type
  • int* someFunction();   // LEGAL!
    

For Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;

int* makeArray(int length, int value);
void showArray(int values[], int length);

int main(void) {
    int arraySize, arrayValue;
    cout << "How large of an array do you want? ";
    cin >> arraySize;
    cout << "What value for each element? ";
    cin >> arrayValue;

    int* p = makeArray(arraySize, arrayValue);
    showArray(p, arraySize);

    delete [] p;
    p = NULL;

    return 0;
}

int* makeArray(int length, int value) {
    int* array = new int[length];
    for (int i = 0; i < length; i++) {
        array[i] = value;
    }
    return array;
}

void showArray(int values[], int length) {
    for (int i = 0; i < length; i++) {
        cout << values[i] << " ";
    }
    cout << endl;
}

12.4.4: Summary

  • A dynamically allocated array has its size determined when the program is running
  • Dynamic arrays are implemented as a dynamic variable of an array type
  • int *p = new int[10];
    
  • Since a dynamic array is allocated dynamically at run-time, you should destroy it at run time as well
  • delete [] p;
    
  • You can return a pointer to an array base type from a function
  • int* someFunction();

Check Yourself

  1. When is the advantage of using a dynamic array?
  2. What is the syntax for declaring a dynamic array?
  3. How do you delete a dynamic array?
  4. What code do you write to return a dynamic array from a function?

Exercise 12.4

In this exercise we explore declaring, allocating and assigning values to dynamic arrays.

Specifications

  1. Save the following code file as mydynarray.cpp.
  2. Compile and run the code to observe how it runs.
  3. Declare a pointer to a dynamic array.
  4. Create a dynamic array using the size entered by the user.
  5. Code a call to the fillup() function with the dynamic array you created.
  6. Code a call to the showArray() function with the dynamic array after the fillup() function.
  7. Delete the dynamic array when done using it.
  8. Your source code is the solution to this exercise.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
using namespace std;

void fillUp(int data[], int size);
void showArray(int values[], int size);

int main() {
    int size = 0;
    // Declare a pointer to a dynamic array

    cout << "How many values: ";
    cin >> size;

    // Create the dynamic array

    // Call fillup() function with the dynamic array

    cout << "You entered " << size << " numbers:\n";

    // Call showArray() function with the dynamic array

    // Delete the dynamic array

    return 0;
}

void fillUp(int data[], int length) {
    cout << "Enter " << length << " numbers:\n";
    for (int i = 0; i < length; i++) {
        cin >> data[i];
    }
}

void showArray(int values[], int size) {
    for (int i = 0; i < size; i++) {
        cout << values[i] << endl;
    }
}

Wrap Up

    Reminders

    Due Next: Exercise 11 (5/10/07)
    Sampler Project (5/24/07)

  • When class is over, please shut down your computer
  • You may complete unfinished exercises at the end of the class or at any time before the next class.

Home | Blackboard | Announcements | Day Schedule | Eve Schedule
Course info | Help | FAQ's | HowTo's | Links

Last Updated: May 10 2007 @16:51:40