Concepts / Searching in Strings

Searching in Strings

A string is an ordered sequence of characters, and each character has a definite position.

  • Programming

Why a String Is More Than One Value

A string is one of the most common kinds of data a program handles. Names, messages, file paths, and user input are all strings. When you write a string literal or read text from a user, you usually think of the text as a single value. That is a useful way to think about it at first, but working with strings effectively requires a more detailed picture of what that value is and how a program can reach into it. This article introduces that picture. It is the starting point for the rest of the chapter, because searching, regular expression notation, and iterators all depend on it.

What do you think happens?

If you treat the word cat as a row of slots, one character per slot, which slot holds the last character t?

  • Slot 1

  • Slot 2

  • Slot 3

  • Slot 0

Reveal answer
Answer:

Slot 2

Positions are numbered from 0, so the three characters of cat sit at positions 0, 1, and 2. The last character t is at position 2, which is the string's length minus 1.

Tracing a String Slot by Slot

The section introduces a simple model. Picture a row of numbered slots with one character in each slot. The slot numbers are the positions. Reading a character means naming its position. Searching, pattern matching, and iteration all reduce to ways of visiting or comparing these slots in some order. Hold this picture in mind as you follow the diagram below, which traces the three characters of cat.

cposition 0aposition 1tposition 2comes beforecomes before
Each character of the string cat occupies one slot, and each slot has a definite position number. Position 0 holds the first character, and the characters follow in order.

Notice what the diagram shows. Each slot holds exactly one character. The slots are arranged in a definite order, so the first character comes before the second and the second before the third. The position number is what lets a program say which character it means. Nothing about this model depends on the particular characters or on how long the string is. It applies to any string, whatever its length.

Order as the Defining Property

Definition

A string is an ordered sequence of characters, and each character has a definite position.

The word ordered is the important part. Order is what makes a string more than a bag of letters. If you had only the letters c, a, and t with no order attached, you could not say which one comes first. Because a string keeps its characters in order, every character has a place that can be referred to, and two strings made of the same letters can still differ when their letters are arranged differently.

Key point

Everything else in this chapter depends on the ordered-sequence model. Searching asks where text occurs within that order, regular expression notation describes patterns over that order, and iterators visit the positions in that order. Understanding the model first makes each of those topics easier to learn.

How Positions Are Numbered

Once a string is seen as a sequence, the next question is how its positions are counted. Many programming languages, including C++, number the characters of a string starting from 0 rather than 1. The first character is at position 0. A string with n characters therefore has positions running from 0 up to n minus 1, which can be written as $0 \leq i \leq n-1$ for any valid position i. The last character is always at length minus 1, not at the length itself.

This convention is worth fixing in your mind early. It affects nearly every operation that touches a string's contents, because every search result, every iteration, and every reference to a character is expressed as one of these numbers. If you count from 1 by habit while the string counts from 0, the numbers you compute will point at the wrong characters.

Locating the Last Character

Worked example

Finding the position of the last character

A string holds the three characters c, a, t, in that order. What is the position of its last character?

  1. 1
    Count the characters

    The string has 3 characters, so its length n is 3.

  2. 2
    Apply the numbering rule

    Positions run from 0 up to n minus 1, which here is 3 minus 1.

  3. 3
    Compute the last position

    The last position is 2, and that slot holds the character t.

  4. 4
    Check the first position

    The first character c sits at position 0, so positions 0, 1, and 2 cover all three characters with no gap.

Result

The last character t is at position 2, which equals the length minus 1.

Searching Visits Positions in Order

The section names searching as the first of three ways to work with string contents. Searching asks where a piece of text occurs. Its answer is a position: when the pattern is found, the search returns the position of the match, and when it is not found, the search returns a not-found result instead. The flowchart below illustrates the general idea of how a search can move through the ordered positions to reach that answer. It is a generic illustration of visiting slots in order, not a description of one particular library's internals.

Start at position 0Compare characterat current positionMatch found?Return positionof the matchReturn not-foundresultMove to next positionPast last position?yesnonoyes
A search starts at the first position, compares the character there, and either returns that position on a match or moves to the next position. If it runs past the last position without a match, it returns a not-found result.

Read the flowchart as a loop over the same numbered slots from the earlier diagram. Each pass checks one position, and the loop ends in one of two results. A found result is a position number, which you can then use to refer to the matched character. A not-found result is a different kind of answer, so a program must be prepared to handle it rather than assume a position was always returned.

Three Ways of Working with Contents

The section introduces three topics that build on the sequence model. Each one answers a different question about a string, so it helps to keep them apart. The table below compares what each operates on and what it gives back, based on the roles the section assigns to each.

TopicQuestion it answersWhat it works withWhat it gives back
SearchingWhere does a piece of text occur?Positions of the string in orderA position of the match, or a not-found result
Regular expression notationDoes the text follow a pattern?Patterns that text may followA description of the pattern rather than a single location
IteratorsHow can I visit each element in turn?Elements taken one at a time in orderAccess to each element as the traversal moves along

The three ways of working with string contents covered in this section

All three rely on the fact that positions are ordered. That shared dependence is why the chapter presents them in sequence, and why this article covers the ordered model before any of them. The later articles will describe the details of each topic, so here the goal is only to recognise the three roles and the common foundation beneath them.

Tracing an Off-by-One Error

An off-by-one error happens when a position is one too large or one too small. Because the numbering starts at 0, the most common version is treating the length as if it were a valid position. The diagram below compares the intended last character of cat with the position an off-by-one mistake would point to.

tposition 2 (length minus 1)Position 3uses the length as apositionNo characterpast the end of catoff by onelands here
For the string cat, the intended last character t sits at position 2. An off-by-one mistake that uses the length 3 as a position points past the end of the string, where no character exists.

The before side shows the correct reasoning: the last character is at length minus 1, which is position 2. The after side shows the error: position 3 is the length, and it does not name any character in cat. The fix is to subtract 1 from the length whenever you need the last position, and to remember that valid positions stop one short of the length.

Mistakes Beginners Make with Positions

  • Common mistake

    Counting positions from 1 instead of 0

    What it looks like

    Treating the first character of cat as position 1 and the last as position 3

    Why it fails

    Positions are numbered from 0, so the first character is at position 0 and the last is at length minus 1.

    Do this instead

    Label the first character position 0, then count upward, so cat has positions 0, 1, and 2.

  • Common mistake

    Using the length as the last position

    What it looks like

    Assuming the last character of cat is at position 3 because the string has 3 characters

    Why it fails

    A string of length n has no character at position n. Its positions stop at n minus 1.

    Do this instead

    Compute the last position as length minus 1, which gives 2 for cat.

  • Common mistake

    Treating a string as a bag of letters

    What it looks like

    Believing that cat and act hold the same information in the same places

    Why it fails

    A string is an ordered sequence, so the order of its characters is part of its meaning and affects where each character sits.

    Do this instead

    Reason about each character by its position, not merely by which letters appear.

  • Common mistake

    Assuming a search always returns a position, without checking for the not-found result

Checking Your Position Reasoning

EASY

Consider the string IJK TEC, which has 7 characters including the space. Without counting from a list, work out the position of the last character and the position of the first character. Then explain why the last position is not 7.

Hints
  • Positions start at 0, so the first character is always at position 0.
  • The last valid position is the length minus 1.
  • A string of length 7 has positions 0 through 6.
MEDIUM

Describe in one sentence what a search returns when the pattern is found and what it returns when the pattern is not found. Then name one reason a program must handle the not-found case explicitly.

Hints
  • Recall the two outcomes shown in the search flowchart.
  • Think about what a program would do next with a position number versus a not-found result.

Key Takeaways

  • A string is an ordered sequence of characters, and each character has a definite position that a program can refer to.
  • Positions are numbered from 0, so the first character is at position 0 and the last is at length minus 1.
  • Searching, regular expression notation, and iterators are the three ways of working with string contents introduced in this section, and all three depend on the ordered model.
  • Off-by-one errors usually come from treating the length as a valid position, so compute the last position as length minus 1.

Related concepts

More concepts starting with S