11: Strings

What We Will Cover


Continuations

Homework Questions?

Questions from last class?

What is the code to declare and allocate and array or characters named shortString that is initialized to the values 'a', 'b' and 'c'?

What to take next?

  • Schedule of Classes
  • After completing CS-11 you are qualified to take either CS-19 or cs-20J
    • CS-19: C++ programming and software design methodologies
    • CS-20J: Java programming and software design methodologies
  • Each course has a initial review section such that you could learn the syntax with a little effort
  • Other computer-related courses on which you can use your programming skills
    • CIS 130: UNIX/Linux Shell Programming
    • CIS-160GP: Game Programming in Java
    • CIS-165PH: Introduction to Programming Database-Driven Web Sites with PHP

11.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

11.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:

11.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 shortString[] = {'a', 'b', 'c'};
    cout << shortString << endl;
    

11.1.3: 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
  • inStream >> cString;
    inStream.getline(cString, 80);
    
  • Similarly, you can use an output file stream like you use cout
  • outStream << cString;

11.1.4: Iterating C-Strings

  • You can iterate through a C-string like you can for a char array
  • For example:
  • const int SIZE = 10;
    char shortString[SIZE] = "Hi Mom!";
    int index = 0;
    while (shortString[index] != '\0') {
        shortString[index] = 'X';
        index++;
    }
    cout << shortString << endl;
    
  • 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 to still process the array correctly in case the null character was missing?

11.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 often 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 string_var contains "The rainin Spain"
  • strncat() is a safer version of strcat()
    • A third parameter limits the number of characters to concatenate
  • For example:
  • char string_var[20] = "The rain";
    strncat(string_var, "in Spain", 11);
    

Further Information

11.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

11.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() to 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() to converts a C-string to a long value
  • long y = atol("1234"); // returns 1234 as a long
  • Function atof() to 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
    

11.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

Exercise 11.1

Specifications

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

  4. Submit your source code as the answer to this exercise.

11.2: String Class

Objectives

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

  • Use string constructors and member functions

11.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";
    
  • 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 Mom!";
    s2 = s1;
    cout << (s1 == s2);
    
  • <, >, <=, >= can be used to compare string objects as well

11.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;
    

11.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

11.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;
    }
    

11.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";
    }
    

11.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;

11.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;
    

Exercise 11.2

Specifications

  1. Write a program named triplex.cpp that replaces every third letter of a string with an 'X'.
  2. Submit your source code as the answer to this exercise.

11.3: Handling String Input

Objectives

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

  • Use getline() as a substitute for cin

11.3.1: Problems With cin

  • To get input from a user, we have been using cin
  • However, cin has a number of shortcomings
    1. When entering input into a string, a space causes the input to stop reading
    2. If a user enters a character when a number is expected, unpredictable results occur

For Example

#include <iostream>
using namespace std;

const int MAX = 20;

int main() {
    int numItems;
    string items[MAX];
    cout << "Enter the number of items: ";
    cin >> numItems;
    for (int i = 0; i < numItems && i < MAX; i++) {
        cout << "Enter item #" << i << ": ";
        cin >> items[i];
    }
    cout << "You entered:\n";
    for (int i = 0; i < numItems; i++) {
        cout << i << ": " << items[i] << endl;
    }
    return 0;
}

  • If you enter a letter, like 'A', for the number of items you get unpredictable results
  • Also, if you enter items with whitespace between the words, the second word ends up in the wrong variable
  • The reason for this is the way cin operates
  • Recall that cin >> numItems:
    1. Skips whitespace
    2. Reads characters
    3. Stops reading when the first unusable character is found
  • This leaves the variable numItems uninitialized in the first case
  • In the second case, the string input stops whenever whitespace is encountered

11.3.2: Using getline()

  • Our solution to the first problem was to use getline()
  • getline(cin, items[i]);
    
  • This works because getline() reads until it encounters a '\n'
  • It turns out that a solution to the second problem uses getline() as well

Using getline() to Input Numbers

  • To use getline() to read numbers, we use the following algorithm:
    1. Read the input as a string using getline()
    2. Convert the string to a number

11.3.3: Converting to Numbers

  • To convert strings to numbers, we can use functions from cstdlib
  • These functions take a C-string parameter, so you must convert a string to a C-String using the c_str() function
  • For example:
  • double z = 0.0;
    string text = "9.99";
    z = atof(text.c_str());
    cout << (z + 1 ) << endl;
    

Functions to Convert C-Strings to Numbers

Function Description
atof(str.c_str()) Returns the contents of str as a double.
atoi(str.c_str()) Returns the contents of str as an int.
atol(str.c_str()) Returns the contents of str as a long int.

Examples Converting Strings to Numbers

  • Using function atoi():
  • string s1 = "1234";
    int x;
    x = atoi(s1.c_str());  // returns 1234
    cout << x << endl;
    s1 = "#1234";
    x = atoi(s1.c_str()); // returns 0 because # is not a digit
    cout << x << endl;
    
  • Using function atol():
  • string s2 = "1234";
    long y = atol(s2.c_str()); // returns 1234 as a long
    cout << y << endl;
    
  • Using function atof():
  • string s3 = "9.99";
    double z = 0.0;
    z = atof(s3.c_str());  // returns 9.99
    cout << z << endl;
    s3 = "$9.99";
    z = atof(s3.c_str()); // returns 0 because $ is not a digit
    cout << z << endl;
    

    11.3.4: Checking for Errors

    • Note that some of the example shown above do not return the desire results
    • For example, if the user enters "$9.99", the function atof() returns 0
    • To prevent this problem, we must check for erroneous characters
    • To check, we iterate through every character of the input string and verify they are valid
    • The valid characters for a positive double are: '0' - '9' and '.'
      • Ignoring exponential notation
    • In addition, we must verify that the user entered some number
    • Otherwise, we get an empty string ("")

    Example of Verifying User Input When Using getline()

    #include <iostream>
    using namespace std;
    
    const int MAX = 20;
    
    int main() {
        string input;
        double value = 0;
        bool error = true;
        while (error == true) {
            cout << "Enter a number: ";
            getline(cin, input);
            error = false;
            for (unsigned i = 0; i < input.length(); i++) {
                char ch = input.at(i);
                if (ch != '.' && ch < '0' || ch > '9') {
                    error = true;
                    cout << "You must enter a numeric value\n";
                }
            }
        }
        value = atof(input.c_str());
        cout << "You entered: " << value << endl;
    
        return 0;
    }
    
    
    • Note that the verification loop does not catch all possible errors
    • What other input errors might we want to check for?

    11.3.5: No More cin

    • We can use our getline() + verification code to replace cin
    • To make it easier to reuse the code, we wrap the code in a function

    cin Replacement Function for Entering Positive doubles

    #include <iostream>
    using namespace std;
    
    const int MAX = 20;
    
    double inputDouble(string prompt);
    
    int main() {
        string input;
        double value = inputDouble("Enter a positive number: ");
        cout << "You entered: " << value << endl;
    
        return 0;
    }
    
    double inputDouble(string prompt) {
        string input;
        double value = 0;
        bool error = true;
    
        while (error == true) {
            cout << prompt;
            getline(cin, input);
            error = false;
            for (unsigned i = 0; i < input.length(); i++) {
                char ch = input.at(i);
                if (ch != '.' && ch < '0' || ch > '9') {
                    error = true;
                    cout << "You must enter a numeric value\n";
                    break;
                }
            }
        }
        value = atof(input.c_str());
    
        return value;
    }
    

    11.3.6: Summary

    • cin is useful for getting user input, but has a number of shortcomings
      • For example: entering letters when expecting numbers
    • We can design improved input functions using the getline() function
    • The algorithm we use is:
      1. Get user input using getline()
      2. Check for unwanted characters
        • Loop until the user enters only correct characters
      3. Use a conversion function to convert the string to a numeric value

    Exercise 11.3

    1. Write a program named inputint.cpp that uses getline() to read integer values.
    2. Use the code below to get started.
    3. Submit your source code as the answer to this exercise.
    #include <iostream>
    using namespace std;
    
    const int MAX = 20;
    
    double inputDouble(string prompt);
    
    int main() {
        string input;
        double value = inputDouble("Enter a positive number: ");
        cout << "You entered: " << value << endl;
    
        return 0;
    }
    
    double inputDouble(string prompt) {
        string input;
        double value = 0;
        bool error = true;
    
        while (error == true) {
            cout << prompt;
            getline(cin, input);
            error = false;
            for (unsigned i = 0; i < input.length(); i++) {
                char ch = input.at(i);
                if (ch != '.' && ch < '0' || ch > '9') {
                    error = true;
                    cout << "You must enter a numeric value\n";
                    break;
                }
            }
        }
        value = atof(input.c_str());
    
        return value;
    }
    

    Wrap Up

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

    Last Updated: November 17 2005 @16:59:05