Learning pathOriginal reference
Lesson 5 of 12

Strings and small helper teams

Read strings without copying, return transformed values safely, and compose helpers with clear tests.

Three string interfaces, three intentions

std::string text receives an independent string value. std::string& text permits changing the caller. const std::string& text reads the caller’s text without making a full parameter copy. Unlike the built-in a[] syntax, a string is an object that knows its own length.

A reversedCopy(std::string text) helper may intentionally edit its copy and return it by value. The returned string remains valid. Returning a reference to a local string would instead leave a reference to an object whose lifetime has ended.

A predicate can serve a larger helper

A predicate answers a yes-or-no question. isLowerVowel(char) can be reused inside countVowels(const std::string&). Keep the small rule separate from counting, and let main decide how to print the result.

These exercises use ASCII, with case and spacing defined by each contract. Counting lowercase vowels does not count uppercase vowels. A palindrome test that counts spaces and punctuation must compare those characters too; it is not a general Unicode text-processing algorithm.

C++23
// Complete C++23 program. Input: one ASCII line, possibly empty.
#include <iostream>
#include <string>
bool isLowerVowel(char c) {
    return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
int countVowels(const std::string& text) {
    int count = 0; // Contract: text length <= 100000.
    for (char c : text) {
        if (isLowerVowel(c)) ++count;
    }
    return count;
}
int main() {
    std::string text;
    std::getline(std::cin, text);
    std::cout << countVowels(text) << '\n';
}

Compare from both ends

For a palindrome, compare the outer characters and move inward. Return false at the first mismatch; return true after all required pairs match. With a signed right index initialized from the bounded length minus one, the empty case starts at −1 and makes no accesses.

This takes O(L) worst-case time and O(1) helper auxiliary space. Building a reversed copy is also linear time but uses O(L) extra storage. Test empty text, one character, odd and even lengths, case differences, and a mismatch at each end.

Optional challenge: preserve order, not adjacency

A subsequence may skip characters without reordering those kept. To check whether small appears as a subsequence of large, scan large once and advance a position in small only on a match. Check that position is still within small before indexing it.

For small = ace and large = abcde, the answer is true even though ace is not a contiguous substring. The empty string is a subsequence of every string. Two read-only references avoid copies; the scan needs O(|large| + 1) time and O(1) auxiliary space.

Value or reference?

The helper executes x += 10. Compare the caller’s value before and after the call.

Caller before5
Inside helper15
Caller after5

The parameter is a copy. Changing it leaves the caller’s variable untouched.

Guided simulation · Change the inputs to test your understanding.

Pause & predict

Which parameter best fits a helper that only compares characters in an existing string?

Choose an answer
Try it yourself

Turn the idea into code

Write a reusable palindrome helper for an ASCII line of length at most 100000. Count spaces and punctuation, preserve case, and treat the empty line as a palindrome. Do not build a reversed copy.

Give me a hint

Compare the leftmost and rightmost remaining characters. A single mismatch is enough to reject.

Show the explained solution

After every successful comparison, the already-checked outside characters match. When the indices meet or cross, no unchecked pair remains. Each step removes two candidates, giving O(L) time and O(1) auxiliary space.

C++23
// Complete C++23 program. Input: one ASCII line, length <= 100000.
#include <iostream>
#include <string>
bool isPalindrome(const std::string& text) {
    int left = 0;
    int right = static_cast<int>(text.size()) - 1;
    while (left < right) {
        if (text[left] != text[right]) return false;
        ++left;
        --right;
    }
    return true;
}
int main() {
    std::string text;
    std::getline(std::cin, text);
    std::cout << (isPalindrome(text) ? "YES\n" : "NO\n");
}

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.