C++ Strings
Working with Strings in C++
Section titled “Working with Strings in C++”C++ offers two primary ways to work with sequences of characters (strings):
std::string: The standard C++ string class (<string>header). This is the preferred, modern, safer, and more convenient way to handle strings in C++.- C-style character strings: Null-terminated character arrays inherited from the C language (
char*orchar[]). While necessary for interacting with C APIs or older code, direct manipulation is error-prone and generally discouraged in modern C++.
The std::string Class (Recommended)
Section titled “The std::string Class (Recommended)”The std::string class, defined in the <string> header, provides a robust and feature-rich way to manage strings. It handles memory management automatically, preventing many common errors associated with C-style strings.
Key Features and Operations:
Section titled “Key Features and Operations:”- Initialization: Can be initialized from string literals, other
std::stringobjects, or parts of strings. - Assignment: Use the
=operator. - Concatenation: Use the
+or+=operators. - Comparison: Use standard comparison operators (
==,!=,<,>,<=,>=). - Length/Size: Use
.length()or.size()methods (they are equivalent). - Accessing Characters: Use
[]operator (no bounds checking) or.at()method (throwsstd::out_of_rangeif index is invalid). - Appending: Use
.append()or+=. - Finding Substrings: Use
.find(),.rfind(),.find_first_of(),.find_last_of(), etc. - Substrings: Use
.substr()to extract a portion of the string. - Modification: Use methods like
.insert(),.erase(),.replace(). - Conversion to C-style: Use
.c_str()to get aconst char*pointer (null-terminated) for compatibility with C functions.
Example using std::string:
#include <iostream>#include <string>#include <stdexcept> // For std::out_of_range
int main() { // Initialization std::string greeting = "Hello"; std::string name("World"); // Constructor initialization std::string message; // Empty string
// Concatenation and Assignment message = greeting + ", " + name + "!"; // Use + greeting += ", again!"; // Use +=
std::cout << "Greeting: " << greeting << std::endl; std::cout << "Message: " << message << std::endl;
// Length std::cout << "Message length: " << message.length() << std::endl;
// Accessing Characters std::cout << "First character: " << message[0] << std::endl; // 'H' try { std::cout << "Character at index 6: " << message.at(6) << std::endl; // 'W' // std::cout << message.at(100); // This would throw std::out_of_range } catch (const std::out_of_range& oor) { std::cerr << "Out of Range error: " << oor.what() << std::endl; }
// Finding substrings size_t commaPos = message.find(','); if (commaPos != std::string::npos) { // npos indicates 'not found' std::cout << "Comma found at index: " << commaPos << std::endl; }
// Substring std::string sub = message.substr(7, 5); // Extract 5 chars starting at index 7 std::cout << "Substring (name): " << sub << std::endl; // "World"
// Conversion to C-style string (for C APIs) printf("Message as C-string: %s\n", message.c_str());
return 0;}Expected Output:
Greeting: Hello, again!Message: Hello, World!Message length: 13First character: HCharacter at index 6: WComma found at index: 5Substring (name): WorldMessage as C-string: Hello, World!C-Style Character Strings (Legacy)
Section titled “C-Style Character Strings (Legacy)”C-style strings are essentially arrays of characters terminated by a special null character (\0). They are managed using pointers (char*) and require manual memory management if allocated dynamically.
Declaration and Initialization:
// Initialized from a string literal (size automatically includes null terminator)char greeting[] = "Hello"; // Size is 6 ('H','e','l','l','o','\0')
// Explicitly sized array (must be large enough for string + null terminator)char farewell[10] = "Bye"; // {'B','y','e','\0', ?, ?, ?, ?, ?, ?}
// Pointer initialization (points to the literal in read-only memory - modifying is undefined behavior!)const char* readOnlyStr = "Constant String";Memory Representation of greeting[]:
Index: 0 1 2 3 4 5Value: 'H' 'e' 'l' 'l' 'o' '\0'Common C String Functions (<cstring> header):
Section titled “Common C String Functions (<cstring> header):”The <cstring> header (or <string.h> in C) provides functions for manipulating C-style strings. Warning: Many of these functions are unsafe as they don’t perform bounds checking and can lead to buffer overflows if the destination buffer is too small.
| SN | Function | Purpose & Safety Notes |
|---|---|---|
| 1 | strcpy(dest, src) | Copies string src to dest. Unsafe! Can overflow dest. |
| 2 | strncpy(dest, src, n) | Copies at most n characters. Safer, but might not null-terminate if n is reached. |
| 3 | strcat(dest, src) | Appends string src to dest. Unsafe! Can overflow dest. |
| 4 | strncat(dest, src, n) | Appends at most n characters from src. Safer, always null-terminates. |
| 5 | strlen(str) | Returns the length of str (excluding the null terminator). |
| 6 | strcmp(s1, s2) | Compares s1 and s2. Returns 0 if equal, <0 if s1<s2, >0 if s1>s2. |
| 7 | strncmp(s1, s2, n) | Compares at most n characters. |
| 8 | strchr(str, ch) | Returns a pointer to the first occurrence of character ch in str, or nullptr if not found. |
| 9 | strstr(haystack, needle) | Returns a pointer to the first occurrence of string needle in haystack, or nullptr if not found. |
Example using C-style strings (demonstration purposes):
#include <iostream>#include <cstring> // Use <cstring> in C++
int main() { char str1[20] = "Hello"; // Ensure buffer is large enough! char str2[] = "World"; char str3[20]; int len;
// Copy str1 into str3 (use safer strncpy or strcpy_s if available) // strcpy(str3, str1); // Unsafe version strncpy(str3, str1, sizeof(str3) - 1); // Safer copy str3[sizeof(str3) - 1] = '\0'; // Ensure null termination std::cout << "strncpy(str3, str1, ...): " << str3 << std::endl;
// Concatenate str2 onto str1 (use safer strncat or strcat_s) // strcat(str1, str2); // Unsafe version strncat(str1, " ", sizeof(str1) - strlen(str1) - 1); strncat(str1, str2, sizeof(str1) - strlen(str1) - 1); // Safer concat std::cout << "strncat(str1, ...): " << str1 << std::endl;
// Total length of str1 after concatenation len = strlen(str1); std::cout << "strlen(str1): " << len << std::endl;
// Comparison if (strcmp(str2, "World") == 0) { std::cout << "str2 is equal to \"World\"" << std::endl; }
return 0;}Expected Output:
strncpy(str3, str1, ...): Hellostrncat(str1, ...): Hello Worldstrlen(str1): 11str2 is equal to "World"Conclusion: While understanding C-style strings is important for C++ developers (especially when dealing with C libraries or low-level code), always prefer std::string for general string manipulation in modern C++. It’s safer, easier to use, and less error-prone.
std::string_view (C++17)
Section titled “std::string_view (C++17)”For situations where you need read-only access to string data without incurring the overhead of creating a new std::string (e.g., function parameters), consider using std::string_view (from the <string_view> header). It provides a non-owning view into an existing character sequence (which could be a std::string, a C-style string, or a string literal).