Understanding String Handling in C++: From C-Style to Standard Library Strings
C++ provides multiple ways to work with text data, ranging from traditional character arrays to the more modern standard library string class.
C-Style Strings
A C-style string is essentially a character array that terminates with a null character (\0).
Declaration and Initialization
#include <iostream>
int main() {
char greeting[] = "Welcome!";
char buffer[50];
char letters[] = {'W', 'e', 'l', 'c', 'o', 'm', 'e', '\0'};
std::cout << "greeting: " << greeting << std::endl;
std::cout << "letters: " << letters << std::endl;
return 0;
}
Common Operations
The <cstring> header provides functions for copying, concatenating, measuring, and comparing strings.
#include <iostream>
#include <cstring>
int main() {
char source[] = "Hello";
char destination[50];
strcpy(destination, source);
std::cout << "destination: " << destination << std::endl;
strcat(source, " there!");
std::cout << "source: " << source << std::endl;
std::cout << "Size of source: " << strlen(source) << std::endl;
if (strcmp(source, destination) == 0) {
std::cout << "Both strings match" << std::endl;
} else {
std::cout << "Strings differ" << std::endl;
}
return 0;
}
The std::string Class
The standard library's std::string provides a more flexible and safer alternative to C-style strings.
Declaration and Initialization
#include <iostream>
#include <string>
int main() {
std::string message = "Hello there!";
std::string label("Greeting");
std::string copy = message;
std::cout << "message: " << message << std::endl;
std::cout << "label: " << label << std::endl;
std::cout << "copy: " << copy << std::endl;
return 0;
}
Common Operations
#include <iostream>
#include <string>
int main() {
std::string text = "Hello";
std::string clone;
clone = text;
std::cout << "clone: " << clone << std::endl;
text += ", Universe!";
std::cout << "text: " << text << std::endl;
std::cout << "Size of text: " << text.length() << std::endl;
if (text == clone) {
std::cout << "Contents are identical" << std::endl;
} else {
std::cout << "Contents differ" << std::endl;
}
auto position = text.find("Universe");
if (position != std::string::npos) {
std::cout << "'Universe' located at index: " << position << std::endl;
} else {
std::cout << "Substring not found" << std::endl;
}
std::string segment = text.substr(8, 8);
std::cout << "Extracted substring: " << segment << std::endl;
return 0;
}
Interoperability Between C-Style and std::string
Conversion between the two string types is straightforward.
#include <iostream>
#include <string>
#include <cstring>
int main() {
const char* legacy = "old style string";
std::string modern = legacy;
std::cout << "Modern string: " << modern << std::endl;
std::string contemporary = "modern style";
const char* older = contemporary.c_str();
std::cout << "Legacy string: " << older << std::endl;
return 0;
}
String Streams (std::stringstream)
The std::stringstream class enables parsing and formatting between strings and various data types.
#include <iostream>
#include <sstream>
int main() {
std::stringstream formatter;
formatter << "Count: " << 42 << " Value: " << 3.14;
std::string output = formatter.str();
std::cout << "Formatted output: " << output << std::endl;
std::string token;
int count;
double value;
formatter >> token >> token >> count >> value;
std::cout << "Parsed token: " << token << std::endl;
std::cout << "Parsed integer: " << count << std::endl;
std::cout << "Parsed double: " << value << std::endl;
return 0;
}
String Literals
Overview
String literals are fixed values appearing directly in source code, enclosed in double quotes. C++ supports several literal types.
#include <iostream>
#include <locale>
int main() {
const char* plain = "Standard text";
std::cout << plain << std::endl;
const wchar_t* wide = L"Wide character text";
std::wcout.imbue(std::locale(""));
std::wcout << wide << std::endl;
const char* utf8 = u8"UTF-8 encoded text";
std::cout << utf8 << std::endl;
const char16_t* utf16 = u"UTF-16 text";
std::wcout << reinterpret_cast<const wchar_t*>(utf16) << std::endl;
const char32_t* utf32 = U"UTF-32 text";
std::wcout << reinterpret_cast<const wchar_t*>(utf32) << std::endl;
const char* raw = R"(Text with \ "quotes\" inside)";
std::cout << raw << std::endl;
const char* multiline = R"(Line one
Line two
Line three)";
std::cout << multiline << std::endl;
const char* concatenated = "Part one " "Part two";
std::cout << concatenated << std::endl;
return 0;
}
String Literals vs String Objects
These represent distinct concepts with different characteristics:
Type Differences
String literals are compile-time constants with types like const char* or const wchar_t*. String objects (std::string, std::wstring) are runtime entities from the standard library with member functions for manipulation.
Storage Location
Literals reside in read-only memory segments. std::string objects are dynamically allocated and can be modified during execution.
Capabilities
Literals offer basic character sequence representation without built-in operations. String objects provide extensive methods for searching, modifying, and transforming text.
C++14 User-Defined Literal for Strings
C++14 introduced the s suffix for creating std::string objects directly from literals.
#include <iostream>
#include <string>
using namespace std::literals::string_literals;
int main() {
std::string first = "First example"s;
std::string second = "Second example"s;
std::cout << first << std::endl;
std::cout << second << std::endl;
std::string concatenated = first + " " + second;
std::cout << concatenated << std::endl;
return 0;
}
Requirements for using the s suffix:
- Include the
std::literals::string_literalsorstd::string_literalsnamespace - Compile with C++14 or later support
This syntax eliminates the need for explicit constructor calls when working with string objects throughout your code.