Programming Fundamentals Using C++

L21 · Characters and Strings: `char` Processing and the `std::string` Class

Module 11 — Strings and Character Processing · Week 11 · Lecture 21 of 32 · 120 minutes Outcomes: CLO-6 · PF-11.1, PF-11.2 · LEARNING_OUTCOMES.md

Learning objectives

  1. Apply <cctype> character classification and conversion functions (isdigit, isalpha, isspace, isupper, islower, toupper, tolower) inside loops over text (PF-11.1).
  2. Manipulate std::string objects: indexing, length(), +/+=, comparison, substr, find, and choose getline vs >> correctly (PF-11.2).
  3. Explain the array-of-chars view of strings (including the '\0' terminator concept for C-strings) and why std::string is the course default (PF-11.2).

Prerequisites

M9 (array indexing/traversal — strings are traversed arrays); L06 (char/int casts); L04 (why >> stops at whitespace).

Concept sequence

  1. Text as data: from char (L03) to sequences of char
  2. <cctype> toolkit with a classification table demo
  3. std::string: declaration, indexing, length
  4. Building and comparing strings (+, +=, ==, <)
  5. Slicing and searching: substr, find
  6. Reading full lines: getline (and its >> interaction trap)

Teaching topics (detailed)

C++ examples required

FileRole
string_processing.cpp ✅classification table, indexing/length, compare, substr/find with npos check, getline demo
(live) name_formatter.cppinitials extractor: getline full name → toupper initials (builds toward L22)

Common student misconceptions

Conceptual explanation (beginner-first)

Strings are the first objects most students meet, even before Module 16 names the idea: a std::string bundles data (the characters) with operations it knows how to do on itself — tell its length, find a substring, hand back a piece, compare itself to another. The dot syntax s.size() reads as "s, report your size" — that mental model pays off in M16, so plant it now.

Under the comfort, the array knowledge from Module 9 still applies: s[i] is a real char, indices run 0..size()-1, and out-of-range accesses are exactly as dangerous as array overruns. The additional machinery is modest: find (position of a substring or std::string::npos if absent), substr (copy a slice), and comparison operators that order strings by character codes — dictionary order, with the uppercase/lowercase wrinkle that "apple" < "Banana" is false because 'a' (97) sorts after 'B' (66).

Terminology and definitions

TermDefinition
std::stringThe library text type; grows as needed, remembers its length
Member functionOperation called on an object with dot syntax: s.size()
Indexing / lengths[i] is a char; valid 0..s.size()-1
findPosition of first match; std::string::npos when absent
std::string::nposThe largest size_t value — the "not found" sentinel
substr(pos, len)Copy of the slice starting at pos, up to len chars
Lexicographic order< > compare char codes position by position
<cctype>Per-char tests/maps: isalpha, isdigit, toupper, tolower, isspace
getlineReads a full line (spaces included) into a string
Leftover newlinecin >> x leaves \n; the next getline reads it as an empty line

Syntax and C++ examples

std::string name{"Grace Hopper"};

std::cout << name.size() << '\n';        // 12
std::cout << name[0] << '\n';            // 'G' — a plain char
name[0] = 'g';                           // assignment through the index

std::size_t pos = name.find(' ');        // 5
if (pos != std::string::npos)
    std::cout << name.substr(0, pos);    // "grace" after the write above

// lexicographic comparison — code-point order, not dictionary intuition
// "apple" < "Banana" is FALSE: 'a'(97) > 'B'(66)

// classification & mapping
char ch{'q'};
if (std::isalpha(static_cast<unsigned char>(ch)))
    ch = static_cast<char>(std::toupper(static_cast<unsigned char>(ch)));   // 'Q'

// the getline pattern (and the repair after >>)
int age{};
std::cin >> age;
std::cin.ignore(1000, '\n');             // drain the leftover newline
std::string title;
std::getline(std::cin, title);           // now reads the whole line

Line-by-line code explanation

examples/string_processing.cpp:

  1. The classification table prints isalpha/isupper/isdigit/isspace results for a fixed character set — a reference students copy.
  2. The indexing block mutates s[1] and prints — strings are mutable through their indices, like arrays.
  3. The find/substr block guards with != std::string::npos before slicing: slicing with npos-derived garbage is the classic crash.
  4. The comparison block orders three words by < and prints the order; the apple/Banana pair demonstrates code-point order vs dictionary intuition.
  5. The getline demo deliberately follows a cin >> int with cin.ignore — the repair pattern shown, not just told.

Output prediction questions (with answers)

  1. "Compiler".size() — ? — 8.
  2. std::string s{"abc"}; s[1] = 'B'; — ? — aBc.
  3. "data".find('a') — ? — 1 (first match); .find('z') — npos.
  4. "2026-09-18".substr(5, 2) — ? — "09".
  5. "apple" < "Banana" — ? — false: 'a' (97) vs 'B' (66) — first position decides.
  6. After cin >> n with input 7⏎Ada, what does an un-repaired getline return? — "" (it consumes the leftover newline).

Common errors and debugging examples

ErrorSymptomFix
Mixing >> and getlinegetline returns emptycin.ignore(1000, '\n') between them
Indexing s[s.size()]Out of range — UB (empty strings: s[0] too)Valid range 0..size()-1; check emptiness
Slicing after unguarded findsubstr from garbage positionTest pos != std::string::npos first
Assuming case-insensitive <Wrong sort order vs. intuitionKnow that comparison is code-point order
toupper(s[i]) used rawWorks usually; UB for negative charsCast to unsigned char (established pattern)
Building output with + on charss + 'x' fine; "a" + 'x' notConcatenate onto a std::string variable

Classroom demonstrations

  1. The empty getline: run the un-repaired cin >> n; getline(...) with input 7⏎Ada Lovelace — the name vanishes; add ignore, it returns. One demo, one rule, remembered all semester.
  2. npos is huge: print std::string::npos — the class sees the giant number and why -1 comparisons are fragile.
  3. Code-point sort: sort {"apple", "Banana", "cherry"} with < — the order surprises; connect to ASCII codes on the board.

Guided student activities

String safari (20 min): 8 task cards (count digits in a plate number, upper-case a word, extract the domain from an email, compare two names for dictionary order, find the first space, slice a date, classify one char, append a suffix) — pairs solve on paper, then 3 are coded live by volunteer typing.

Practice problems

Summary

std::string bundles characters with operations — dot syntax plants the object mental model early. Indexing is array indexing; find needs its npos guard; comparisons follow code points, not intuition; and getline needs its cin.ignore repair after >>. Next (L22): the algorithms that build text — cleaning, splitting, and formatting.

Exit ticket / formative assessment

  1. Write the not-found check for find.
  2. std::string s{"abc"}; s[1] = 'B'; — final value? What type is s[1]?
  3. Which reads "Data Science 101" fully — cin >> s or getline(cin, s)?

Estimated time allocation (120 min)

SegmentMinutes
Recall (2-D quiz) + text-as-data motivation10
<cctype> toolkit + char arithmetic25
Break10
std::string operations + substr/find + getline trap45
String safari activity20
Exit ticket + L22 preview10
Programming Fundamentals Using C++ · C++17 · 16 weeksBack to top ↑