Lesson 8 of 12

Join, compare, and find text

Learn content comparison, lexicographical order, substring counts, and the not-found sentinel.

Joining is explicit

For strings, + joins text and += appends to the left-hand string. Spaces are not inserted automatically: first + " " + second explicitly supplies one. Character arithmetic such as 'a' + 'b' does not produce the string "ab".

String equality compares complete content, including case, spaces, order, and length. "Code" differs from "code", and "hi" differs from "hi ". Unlike raw arrays, ordinary string assignment and comparison operate on the whole value.

Compare at the first difference

Lexicographical comparison checks from the left and uses the first different character. If one string ends while all its characters match the other’s beginning, the shorter comes first. For lowercase ASCII words, this follows the familiar alphabet.

"car" comes before "cat"; "app" comes before "apple"; "aa" comes before "z" despite being longer. Numeric-looking text is still text: "10" comes before "2" because '1' precedes '2'.

A substring uses a start and a count

For "banana", substr(1, 3) returns "ana". The second argument counts characters, rather than naming the final index. An inclusive interval [l, r] needs r − l + 1 characters; the half-open interval [l, r) needs r − l.

substr(pos) returns the remaining suffix. A count beyond the remaining length is shortened. pos equal to size() returns an empty string; a position beyond size() is an error. substr does not modify the original string.

A match at zero is still a match

find returns the first starting position or std::string::npos when absent. Use auto to preserve the result’s actual size type, then compare explicitly with npos. if (s.find(pattern)) is wrong: a valid match at zero becomes false.

In banana, find("ana") returns 1 while find("ana", 2) returns 3. One call does not count all matches. Repeated or overlapping matches require a deliberate next search position.

C++23
#include <iostream>
#include <string>

int main() {
    std::string s = "banana";
    std::cout << s.substr(1, 3) << '\n';
    auto position = s.find("ana");
    if (position != std::string::npos) { std::cout << position << '\n'; }
    auto missing = s.find("xyz");
    if (missing == std::string::npos) { std::cout << "NOT FOUND\n"; }
    std::cout << s << '\n';
    return 0;
}
Pause & predict

For s = "training", what does s.substr(2, 4) return?

Choose an answer
Try it yourself

Turn the idea into code

Read two nonempty lowercase ASCII words and print the lexicographically smaller one. If they match, print that word once.

Give me a hint

Compare the strings directly, rather than comparing only their lengths.

Show the explained solution

Use a <= b to choose the first string when it is smaller or equal; otherwise print b. No sorting algorithm is necessary for this two-value decision.

C++23
#include <iostream>
#include <string>

int main() {
    std::string a, b;
    std::cin >> a >> b;
    if (a <= b) { std::cout << a << '\n'; }
    else { std::cout << b << '\n'; }
    return 0;
}

Your notes

Ready for the next idea?

Mark complete when you can explain it yourself.

From a problem to a programIdentify the input, output, and constraints, then translate a small plan into C++.Variables, types, and remembered valuesChoose a representation, initialize it, and understand what assignment really changes.Arithmetic without surprisesPredict division and remainder, widen before multiplication, and format decimal answers.Conditions and logical decisionsBuild exclusive categories, combine comparisons, and protect operations with short-circuit logic.Optional: other ways to chooseRecognize switch for exact choices and the conditional operator for choosing a value.For loops: make repetition preciseTrace initialization, condition, body, and update—and avoid an extra iteration.While, do-while, and stopping rulesChoose a loop from its stopping condition and read the exact input format.Break, continue, and early answersDistinguish leaving a loop from skipping one iteration, without losing required input.Five patterns worth understandingUse sums, counts, best-so-far candidates, products, and flags to process a stream.Nested loops: rows and columnsTranslate a shape into two loop roles and count the total work.Take a number apart, one digit at a timeUse remainder and division to process decimal digits, including zero.Multiple cases and a debugging mindsetCombine the patterns, isolate each case, and test the boundaries that can break your idea.Arrays: give every value a placeUnderstand indices, initialization, capacity, active length, and the first safe array loop.Scan, count, search, and compareDistinguish values from positions and preserve the exact tie rule a problem asks for.Change a sequence without losing itUpdate, copy, compare, reverse, and inspect neighbours using the correct bounds.Matrices: think in two coordinatesTraverse tables, total rows and columns, inspect diagonals, and protect grid neighbours.Characters become stringsSeparate characters from numbers, then safely inspect and edit managed text.Read the text the problem actually givesChoose words or full lines, preserve empty cases, and reset only the state that needs it.Scan text: count, filter, transformBuild a result from matching characters without losing leading zeros or skipping shifted text.Join, compare, and find textLearn content comparison, lexicographical order, substring counts, and the not-found sentinel.