Welcome to Lesson 14!


Learning Objectives
By the end of today's class, you should know...
  • What is a string index?
  • How to iterate through a string using indexing.
  • How to use getline() to take in string input.
  • What is cin >> ws and when is it needed?

Announcements

  • Quiz 5 today
  • Tomorrow is a holiday - No Lab and No Office Hours!


Review Activity

With a partner, complete the following:
  • What is the advantage of using a do-while loop instead of a while loop?
  • Convert the following while loop into a do-while loop:
int num;
cout << "Enter a positive number: ";
cin >> num;

while (num < 0) {
    cout << "Enter a positive number: ";
    cin >> num;

}
  • What will be the output of the following code:

for (int i = 0; i <= 5; i++){
        if (i % 2 == 0)
            cout << "$";
        else
            cout << "!";
    }

  • Fill in the missing lines of code below to handle the case where a user enters a string instead of the expected numerical input.

double height;

cout << "Please enter your height in inches: ";

cin >> height;

while (???????????????) {

    cin.clear();

    ??????

    cout << "Please enter numbers not words.\n";

    cout << "Please enter your height in inches: ";

    cin >> height;

}


Using Loops with Strings

Review: Strings Versus Characters

  • Remember that a string is a series of characters enclosed in double quotes such as:
    "Hello"  "b"  "3.14159"  "$3.95"  "My address is 378 Eastbrook Dr"
  • We can store text in a variable of type string, like:
    string firstName;             // declaration
    firstName = "Jennifer";       // assignment
    string lastName = "Parrish";  // declaration + assignment
    string fullName = firstName + " " + lastName; // concatenation (+) of 2 stings
    
  • On the other hand, a character is a single letter, number or special symbol
  • We enclose characters in a single quote, rather than a double quote, like:
    'a'   'b'   'Z'   '3'   'q'   '$'   '*'
  • Also, we can store a a single character using a variable of type char, such as:
    char letterA = 'A';
    char letterB = 'B';
    
  • Each character is stored as a number, using its ASCII Table value
  • By declaring a char variable or using single quotes, C++ knows to treat the number as a character
  • Thus, when we print a character, we see a letter rather than a number:
    char letter = 'A';
    cout << letter << 'B' << endl;
    
  • As we can see, a string is made up of characters and characters are numerical codes
  • We can use this information to work with characters and strings

Indexing a String

  • Strings have a built-in indexing system with each stored in a character sequence starting at 0 (zero)

  • We can access any individual character of a string variable using square brackets [ ]
  • The general syntax is:
    stringVariable[index];
  • Where:
    • stringVariable: the name of your string variable
    • index: the number of the character position
  • For example:
    string str = "abcdef";
    char firstLetter = str[0];
    cout << firstLetter << str[1] << endl;
    
  • The above code displays:
    ab
  • Notice that the square bracket notation returns a char data type
  • What will the following print?
#include <iostream>
using namespace std;

int main() {
      string sport = "Basketball";
      cout << "The league: " << sport[1] << sport[7] << endl;

      cout << "Abbreviation for this sport: " << sport[0] << sport[6] << endl;

     return 0;

}



Using a For Loop to Iterate Strings
  • Recall that member function length() returns the number of characters in a string variable:
    string s = "abcdef";
    int n = s.length();
  • After we know the length, it is easy to iterate through the individual characters of a string using a counting loop:
    cout << "Enter a message: ";
    string msg;
    cin >> msg;
    for (int i = 0; i < msg.length(); i++) {
        cout << "Char[" << i << "]: " << msg[i] << endl;
    }
    

Group Activity: Iterating Strings

  • Copy the following program into CodeBlocks, save it as test.cpp, and then compile and run the starter program to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    int main() {
        // Enter your code here
    
        return 0;
    }
    
  • Add the following for-loop code to the main() function.
    string msg = "Hello, world!";
    for (int i = 0; i < msg.length(); i++) {
        cout << i << ": " << msg[i] << endl;
    }
    
  • Compile and run your code. What do you see when you compile?


String Input With Spaces

  • We have been using the >> operator to enter data into a string variable:
    string something;
    cout << "Enter something: ";
    cin >> something;
    cout << "You entered: " << something << "END OF OUTPUT\n";
    
  • However, there are some complications
  • >> skips whitespace and stops on encountering more whitespace
  • Thus, we only get a single word for each input variable
  • If a user types in "Hello Mom!", we would only read "Hello" and not " Mom!"
  • This is because cin >> s1 works as follows:
    1. Skips whitespace
    2. Reads non-whitespace characters into the variable
    3. Stops reading when whitespace is found

Input Using getline()

  • To read an entire line we use function getline()
  • Syntax:
    getline(cin, stringVariable);
    
  • Where:
    • stringVariable: the name of the string variable
  • For example:
    string line;
    cout << "Enter a line of input:\n";
    getline(cin, line);
    cout << line << "END OF OUTPUT\n";
    
  • Note that getline() stops reading when it encounters a '\n'


Activity 14.1: How many words in your sentence? (10 pts)

  • Let's write a program that counts the number of words in a sentence input by the user.
  • Find a partner and open up a new C++ file called numWords.cpp.
  • Copy and paste the following starter code into your file:
#include <iostream>
using namespace std;

int main() {
      //Your statements go here

      return 0;
}
  • Add the appropriate block comments with your name and section information.
  • Next declare a string variable at the top of your program named sentence:
string sentence;
  • Welcome the user to the program with the following message:
Give me a sentence, and I will count the number of words.
  • Prompt the user to input a sentence and store the user input as the sentence variable.
Please enter your sentence:_
  • Don't forget to use getline() here.
  • How can we determine how many words are in a sentence?
  • We need to look at the whitespace.
  • Next, we will use a for loop to scroll through the sentence looking for blank spaces. 
  • Each time we encounter a new blank space, we will add one to our total for the number of words in the sentence.
  • Create a new variable at the top of main to store our counter for the number of words in the sentence. Assign it a value of 1. Why do we want to give it an initial value of 1 not 0?
int numWords = 1;
  • Now, create a for loop to iterate through the sentence. Don't forget to use the length() function here.
for (int i = 0; i < sentence.length(); i++) {
      cout << sentence[i] << endl;
}
  • Now, run your program and verify that you get the following output.



  • However, this is not the purpose of our program.
  • We want to count the number of words.
  • Remove the cout statement from your for loop.
  • Repalce the cout with an if statement to check the value of the the s[i] variable to determine if it is a blank space.

if (sentence[i] == ' ') 

  • When we encounter a blank space, we need to add one to the numWords variable.
  • Your for loop should now look like this:

for (int i = 0; i < sentence.length(); i++) {
    if (sentence[i] == ' ') {
        numWords++; 
    }
}
  • Finally, outside of your for loop, add a statement to print out the number of words.
cout << "There are " << numWords << " words in \"" << sentence << "\"" << endl;

  • Run your program to verify it works correctly. Then, upload to Canvas.
  • Your program should now look like this:


Strings Continued

The Problem with Newlines

  • When you press the Enter key, a newline character ('\n') is inserted as part of the input
  • The newline character can cause problems when you mix cin >> with getline()
  • Recall that cin >> s1:
    1. Skips whitespace
    2. Reads non-whitespace characters into the variable
    3. Stops reading when whitespace is found
  • Since whitespace includes newline characters, using cin >> will leave a newline character in the input stream
  • However, getline() just stops reading when it first finds a newline character
  • This can lead to mysterious results in code like the following:
    cout << "Enter your age: ";
    int age;
    cin >> age;
    cout << "Enter your full name: ";
    string name;
    getline(cin, name);
    cout << "Your age: " << age << endl
         << "Your full name: " << name << endl;
    
  • To correct this problem we use cin >> ws just before getline()
    cin >> ws; // clear whitespace from input stream
    
  • We can see how to use this fix in the following example

Example Using cin >> ws


#include <iostream>
using namespace std;

int main() {
    cout << "Enter your age: ";
    int age;
    cin >> age;
    cout << "Enter your full name: ";
    string name;
    cin >> ws; // clear whitespace from buffer
    getline(cin, name);
    cout << "Your age: " << age << endl
         << "Your full name: " << name << endl;
}

Activity 14.2: Sentence Continued (10 pts)
  • Let's add to our program involving sentences from the last activity. We will also calculate the number of letters in the sentence and take in a user guess for a number of letters.
  • At the end of the program, we will confirm whether their guess was correct or not.
  • Declare a new variable beneath the other two at the top of the program. This variable will be used to store our calculation for the number of letters. 
  • Also, add a variable to store the user input for their guess. 
  • The variable declaration section of your program should now look like this:
string sentence;
int numWords = 1;
int numLetters = 0;
int guess;
  • Now alter your first cout statement to reflect the additional uses of this program. Remove the original message in your cout statement and replace it with the one below:
Think of a sentence in your mind.
Later I will tell you how many words and letters are in your sentence.

  • Now, ask the user to enter a guess for how many letters are in the sentence. We want the user to guess without counting the number of letters.
Enter a guess for the number of letters in your sentence (don't count!): _
  • Store the user guess as the guess variable using cin.
  • Next, prompt the user to enter the sentence. Your prompt should remain the same from the last exercise and, as before, you should use getline() to store the user input as the sentence variable.
Please enter your sentence: _
  • Verify that your code inside main looks like identical to the code below:
  • Now, run your program. You should notice a problem.
  • How can we fix this problem?
  • Add a cin >> ws above your getline(cin, sentence);
cin >> ws;
getline(cin, sentence);
  • Compile and run your code again and verify that it is now working properly.
  • Now let's alter the code inside the for loop to calculate how many letters are in the sentence.
  • Since we don't want to count any blank spaces, we only want to increment the numLetters variable when we are NOT incrementing the numWords variable. 
  • Therefore, we need to add an else statement to our for loop. Make sure your if-else in the for loop looks like this:
if (sentence[i] == ' ') {
    numWords++;
} else {
    numLetters++;
}
  • Now, let's add another cout statement below the for loop to print out the number of letters in the sentence,
cout << "And, " << numLetters << " letters.\n";
  • Did our user guess the number of letters correctly? Now is the time to let him or her know. Add the following if-else block above the return 0; of main.
if (guess == numLetters) {
    cout << "You guessed right!\n";
} else {
    cout << "You guessed wrong!\n";
}
  • Run your program again and you should get the following output. Note: if you don't get the output below, compare your program to the final version at the end of this exercise. When you are finished, upload to Canvas
  • Your final code should look identical to the following:


Wrap Up

  • With your partner, answer the questions from today's learning objectives

Upcoming Assignments


~Have a Great 3-Day Weekend!~