C++ Strings Interview Questions
C++ Strings and Built-in String Functions
Basic Level (15 Questions)
What are the two types of strings in C++ and what are their differences?
C++ supports two types of strings:
- C-style strings (character arrays): Null-terminated character arrays, inherited from C language.
- String class objects (std::string): C++ Standard Library string class from the <string> header.
| Aspect | C-style Strings | std::string |
|---|---|---|
| Header | <cstring> or none | <string> |
| Memory | Fixed size, manual management | Dynamic, automatic management |
| Null terminator | Required | Not required (handled internally) |
| Assignment | strcpy() function needed | Direct assignment with = operator |
| Concatenation | strcat() function | + operator or append() |
| Length | strlen() function | length() or size() methods |
| Safety | Prone to buffer overflow | Bounds checking available |
How do you declare and initialize strings in C++ using both methods?
C-style string declaration and initialization:
- Character array with null terminator: char str[] = "Hello";
- Explicit character array: char str[6] = {'H','e','l','l','o',' '};
- Pointer to string literal: char *str = "Hello";
- Uninitialized array: char str[20];
- Default constructor: std::string str;
- From C-string: std::string str = "Hello";
- From another string: std::string str2 = str1;
- With repetition: std::string str(5, 'A'); (creates "AAAAA")
- Substring: std::string str = "Hello World".substr(6, 5);
What are the most commonly used C-string functions from <cstring> header?
| Function | Purpose | Description |
|---|---|---|
| strlen() | String length | Returns length of string (excluding null terminator) |
| strcpy() | String copy | Copies source string to destination |
| strncpy() | Bounded copy | Copies up to n characters |
| strcat() | String concatenation | Appends source to destination |
| strncat() | Bounded concatenation | Appends up to n characters |
| strcmp() | String compare | Compares two strings lexicographically |
| strncmp() | Bounded compare | Compares up to n characters |
| strchr() | Character search | Finds first occurrence of character |
| strrchr() | Reverse search | Finds last occurrence of character |
| strstr() | Substring search | Finds first occurrence of substring |
| strtok() | String tokenization | Splits string into tokens |
What are the key member functions of the std::string class?
| Category | Functions | Description |
|---|---|---|
| Capacity | size(), length(), capacity(), empty(), clear(), reserve(), shrink_to_fit() | Query and manage string size and capacity |
| Element Access | operator[], at(), front(), back() | Access individual characters (at() does bounds checking) |
| Modifiers | append(), push_back(), insert(), erase(), replace(), swap(), pop_back() | Modify string content |
| Operations | c_str(), data(), copy(), find(), rfind(), find_first_of(), find_last_of(), substr(), compare() | String operations and searching |
| Numeric Conversions | stoi(), stol(), stoll(), stof(), stod(), to_string() | Convert between strings and numbers (C++11) |
How do string comparison functions work in C++?
C-style string comparison (strcmp):
- Returns 0 if strings are equal
- Returns negative value if first string is less than second
- Returns positive value if first string is greater than second
- Comparison is lexicographical (dictionary order)
- Case-sensitive comparison
- compare() method: Similar return values as strcmp()
- Relational operators: ==, !=, <, <=, >, >= can be used directly
- Case-sensitive by default
- For case-insensitive comparison, need to convert to same case first or use custom comparison
What is the difference between strcpy() and strncpy() functions?
| Aspect | strcpy() | strncpy() |
|---|---|---|
| Safety | Unsafe - no bounds checking | Safer - specifies maximum characters to copy |
| Null terminator | Always copies null terminator | May not add null terminator if source length ≥ n |
| Padding | No padding | Pads destination with nulls if source shorter than n |
| Use case | When source size is known and fits destination | When copying from untrusted sources or fixed buffers |
| Performance | Faster | Slightly slower due to length checking |
How do you convert between C-style strings and std::string?
Converting C-string to std::string:
- Implicit conversion: std::string str = cstr;
- Constructor: std::string str(cstr);
- Assignment: str = cstr;
- With length: std::string str(cstr, length);
- c_str() method: Returns const char* (read-only)
- data() method: Returns char* (C++17 onwards, non-const for non-const strings)
- copy() method: Copies to character array
- c_str() pointer becomes invalid if string is modified
- For modifications, copy to a separate buffer
- Always ensure destination buffer is large enough
What are the string search functions available in C++?
C-style string search functions:
- strchr(): Find first occurrence of character
- strrchr(): Find last occurrence of character
- strstr(): Find substring
- strpbrk(): Find any character from set
- strcspn(): Find length of initial segment not containing characters
- strspn(): Find length of initial segment containing only characters
- find(): Find first occurrence of string/character
- rfind(): Find last occurrence of string/character
- find_first_of(): Find first occurrence of any character in set
- find_last_of(): Find last occurrence of any character in set
- find_first_not_of(): Find first character not in set
- find_last_not_of(): Find last character not in set
- All return string::npos if not found
How does string concatenation work in C++ with both string types?
C-style string concatenation:
- strcat(dest, src): Appends src to dest
- strncat(dest, src, n): Appends up to n characters from src to dest
- Must ensure dest has enough space for both strings plus null terminator
- No automatic memory management
- Returns pointer to dest
- + operator: string3 = string1 + string2;
- += operator: string1 += string2;
- append() method: Various overloads for different data types
- push_back(): Appends single character
- Automatic memory management - string resizes as needed
- Can concatenate strings, C-strings, characters, and ranges
What are the string tokenization methods in C++?
C-style string tokenization:
- strtok(): Modifies original string by replacing delimiters with null characters
- First call: strtok(string, delimiters)
- Subsequent calls: strtok(NULL, delimiters)
- Not thread-safe (uses static buffer)
- strtok_r(): Thread-safe version (POSIX)
- Returns pointer to token or NULL when done
- No built-in tokenizer in std::string
- Common approaches:
- find() and substr() combination
- stringstream with getline() and delimiter
- Regular expressions (C++11)
- Custom tokenization function
What are the numeric conversion functions available for strings in C++?
C++11 introduced numeric conversion functions in std::string:
Features:
| Function | Purpose | Example Conversion |
|---|---|---|
| stoi() | String to int | "123" → 123 |
| stol() | String to long | "123456" → 123456L |
| stoll() | String to long long | "123456789" → 123456789LL |
| stoul() | String to unsigned long | "123" → 123UL |
| stoull() | String to unsigned long long | "123" → 123ULL |
| stof() | String to float | "3.14" → 3.14f |
| stod() | String to double | "3.14159" → 3.14159 |
| stold() | String to long double | "3.14159" → 3.14159L |
| to_string() | Numeric to string | 123 → "123" |
- Automatic detection of base (decimal, octal, hex)
- Leading whitespace is ignored
- Throws std::invalid_argument if no conversion
- Throws std::out_of_range if value out of range
- Optional parameters for size_t* and int base
What is the difference between size() and capacity() in std::string?
| Function | Returns | Description |
|---|---|---|
| size() | size_t | Number of characters currently in the string |
| length() | size_t | Same as size() (for string compatibility) |
| capacity() | size_t | Total characters that can be stored without reallocation |
| max_size() | size_t | Maximum possible string size |
| empty() | bool | True if string has 0 characters |
- capacity() >= size() always
- When size() reaches capacity(), adding more characters triggers reallocation
- reserve() can pre-allocate memory to avoid frequent reallocations
- shrink_to_fit() reduces capacity to fit current size
- Reallocation invalidates iterators, pointers, and references to characters
What are iterator functions available for std::string?
std::string iterator functions:
Usage scenarios:
| Function | Returns | Description |
|---|---|---|
| begin() | iterator | Iterator to first character |
| end() | iterator | Iterator past last character |
| rbegin() | reverse_iterator | Reverse iterator to last character |
| rend() | reverse_iterator | Reverse iterator before first character |
| cbegin() | const_iterator | Const iterator to first character |
| cend() | const_iterator | Const iterator past last character |
| crbegin() | const_reverse_iterator | Const reverse iterator to last character |
| crend() | const_reverse_iterator | Const reverse iterator before first character |
- Range-based for loops (C++11)
- STL algorithms (sort, find, transform, etc.)
- Iterating forward or backward through string
- Const iterators for read-only access
- Reverse iteration for processing from end to beginning
How do you perform case conversion on strings in C++?
Built-in methods:
Common approaches:
- No direct case conversion in std::string or C-string functions
- Use character functions from <cctype> header
| Function | Purpose |
|---|---|
| toupper() | Convert character to uppercase |
| tolower() | Convert character to lowercase |
| isupper() | Check if character is uppercase |
| islower() | Check if character is lowercase |
| isalpha() | Check if character is alphabetic |
- Loop through string and apply toupper()/tolower() to each character
- Use std::transform with toupper/tolower
- For locale-specific conversions, use std::locale
- Third-party libraries like Boost.StringAlgorithms
What is the substr() function in std::string and how is it used?
std::string::substr() function:
- Returns a substring of the original string
- Syntax: substr(pos, count)
- pos: Starting position (default: 0)
- count: Number of characters (default: npos - until end)
- Returns new string containing the substring
- Does not modify original string
- Throws std::out_of_range if pos > size()
- Extracting parts of strings (first N characters, last N characters, middle section)
- String splitting/tokenization
- Removing prefixes or suffixes
- Creating string views without copying (C++17 string_view is better for this)
- Creates a new string (memory allocation)
- For read-only operations, consider std::string_view (C++17)
- For C-strings, use strncpy() with manual null termination
Tricky Level (10 Questions)
What are the safety considerations when working with C-style strings?
Common security issues with C-strings:
- Buffer overflow: Writing beyond allocated memory
- Off-by-one errors: Forgetting null terminator
- Uninitialized buffers: Containing garbage data
- String truncation: Losing data without indication
- Always validate input lengths before copying
- Use bounded functions (strncpy, strncat, snprintf)
- Always null-terminate strings manually when using bounded functions
- Initialize character arrays
- Check return values of string functions
- Use sizeof() for stack-allocated arrays
- Prefer std::string for new code
- strlcpy() and strlcat() (BSD, not standard C/C++)
- snprintf() for formatted output
- Windows: StringCchCopy, StringCchCat
- Compiler security features: /GS flag, stack cookies
How do you read and write strings in C++ with I/O operations?
Reading strings:
- cin >> string: Reads word (stops at whitespace)
- getline(cin, string): Reads entire line (including spaces)
- getline(cin, string, delimiter): Reads until delimiter
- cin.getline(): For C-strings with buffer size limit
- fgets(): File reading for C-strings
- cout << string: Output string
- printf("%s", str.c_str()): Formatted output for std::string
- puts(): Output C-string with newline
- fputs(): File output for C-strings
- ifstream/ofstream with >> and << operators
- getline() with file streams
- fread()/fwrite() for binary data
What are the performance considerations when using std::string?
Performance characteristics of std::string:
- Small String Optimization (SSO): Many implementations store small strings (typically ≤ 15 chars) directly in object, avoiding heap allocation
- Copy-on-write (COW): Some implementations use this optimization (less common now due to thread safety)
- Growth strategy: Typically exponential (double capacity) to amortize reallocation cost
- Use reserve() when final size is known to avoid reallocations
- Avoid repeated concatenation with + in loops (use += or stringstream)
- Prefer passing by const reference for function parameters
- Use move semantics (C++11) for returning strings
- Consider string_view (C++17) for read-only parameters
- Avoid unnecessary copies with substr()
- std::string has overhead: pointer, size, capacity (typically 24-32 bytes)
- Fragmentation from frequent allocations/deallocations
- Custom allocators can improve performance for specific use cases
What is std::string_view (C++17) and when should it be used?
std::string_view features:
Use cases for string_view:
- Lightweight non-owning read-only view of a string
- Header: <string_view>
- Contains pointer to data and size
- No memory allocation (typically 16 bytes)
- Can view any contiguous character sequence
| Aspect | std::string | std::string_view |
|---|---|---|
| Ownership | Owns the data | Non-owning view |
| Memory | Allocates/deallocates | No allocation |
| Modification | Mutable | Read-only |
| Size | Larger (24-32 bytes) | Smaller (16 bytes) |
| Lifetime | Manages lifetime | Depends on source |
- Function parameters for read-only string access
- Avoiding copies when passing substrings
- Parsing and tokenization
- String literals in performance-critical code
- Interface between different string types
- Lifetime: Source data must outlive string_view
- Not null-terminated by requirement (but often is)
- No conversion to C-string automatically
What are the best practices for string handling in modern C++?
Modern C++ string best practices:
- Prefer std::string over C-strings for new code
- Use std::string_view (C++17+) for read-only function parameters
- Pass by const reference when not modifying strings
- Use reserve() when final size is known to avoid reallocations
- Prefer string literals with "s" suffix in C++14: using namespace std::string_literals;
- Use auto with string operations to avoid type issues
- Leverage range-based for loops for iteration
- Use modern conversion functions (stoi, to_string) instead of C functions
- Be cautious with c_str() - pointer invalidated on modification
- Consider emplace_back() instead of push_back() for characters
- Use string streams for complex string building
- Regular expressions (C++11+) for complex pattern matching
- Avoid strlen() in loops - cache the result
- Validate user input before processing
- Use appropriate string functions for the task (find vs find_first_of, etc.)
Why prefer `std::string` over C-strings?
Automatic memory management, bounds-safe interfaces, rich operators, and STL algorithms—fewer buffer overrun bugs.
What does `std::string::npos` represent?
A static constant meaning “no position found,” returned by find when the substring is absent.
Difference between `substr` and `string_view`?
substr allocates a new string; string_view is a non-owning reference to a character range—no allocation.
How does `std::to_string` work?
Overloads convert numeric types to std::string using standard formatting rules (defined in <string>).
What is SSO (small string optimization)?
Many implementations store short strings inside the object without heap allocation, improving cache locality and performance.
Note: These questions cover core interview topics. Pair with the tutorial and MCQ quiz for this section. This page lists 15 basic and 10 tricky questions—use the tutorial and MCQ links above and below.