A Deeper Look at the std::string Class

Checking if a String is a Palindrome

How can I efficiently check if a std::string is a palindrome?

Abstract art representing computer programming

A palindrome is a word, phrase, number, or other sequence of characters that reads the same forward and backward. Checking if a string is a palindrome is a common programming task. Here's an efficient way to do this in C++ using std::string:

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
#include <vector>

bool is_palindrome(const std::string& str) {
  if (str.empty()) {
    return true;
  }

  auto left = str.begin();
  auto right = str.end() - 1;

  while (left < right) {
    // Skip non-alphanumeric characters
    while (left < right && !std::isalnum(*left))
      ++left;
    while (left < right && !std::isalnum(*right))
      --right;

    if (std::tolower(*left) != std::tolower(*right)) {
      return false;
    }

    ++left;
    --right;
  }

  return true;
}

int main() {
  std::vector<std::string> tests{
    "A man, a plan, a canal: Panama", "race a car",
    "Was it a car or a cat I saw?", "Hello, World!",
    ""  // empty string
  };

  for (const auto& test : tests) {
    std::cout << "\"" << test << "\" is " << (
      is_palindrome(test) ?
      "a palindrome" : "not a palindrome"
    ) << '\n';
  }
}
"A man, a plan, a canal: Panama" is a palindrome
"race a car" is not a palindrome
"Was it a car or a cat I saw?" is a palindrome
"Hello, World!" is not a palindrome
"" is a palindrome

Let's break down the is_palindrome() function:

  1. We use two iterators, left and right, starting from the beginning and end of the string respectively.
  2. We skip non-alphanumeric characters using std::isalnum().
  3. We compare characters case-insensitively using std::tolower().
  4. If we find a mismatch, we return false.
  5. If we make it through the entire string without finding a mismatch, we return true.

This approach is efficient because:

  • It works in-place, without creating any new strings.
  • It stops as soon as it finds a mismatch.
  • It only traverses half the string in the worst case.

For a simpler implementation that considers all characters and is case-sensitive, you could use std::equal():

bool simple_palindrome(const std::string& str) {
  return std::equal(
    str.begin(),
    str.begin() + str.length() / 2,
    str.rbegin()
  );
}

This method is shorter but less flexible, as it doesn't ignore non-alphanumeric characters or handle case-insensitivity.

For very long strings, you might consider using std::string_view (C++17) to avoid copying:

#include <string_view>

bool is_palindrome(std::string_view sv) {
  // Similar implementation as before,
  // but using string_view
}

Remember, the most appropriate method depends on your specific requirements, such as whether you need to ignore punctuation and whitespace, whether the check should be case-sensitive, and what constitutes a valid character in your palindrome definition.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved