String Functions
String Functions in C
Table of Contents
- •Introduction
- •Header File
- •String Length - strlen()
- •String Copy Functions
- •String Concatenation Functions
- •String Comparison Functions
- •String Search Functions
- •String Tokenization - strtok()
- •Memory Functions
- •Other Useful Functions
- •Safe Alternatives
- •Best Practices
- •Summary
Introduction
The C Standard Library provides a rich set of functions for string manipulation through the <string.h> header file. These functions are essential for:
- •Measuring string length
- •Copying strings
- •Concatenating strings
- •Comparing strings
- •Searching within strings
- •Tokenizing strings
- •Memory manipulation
Understanding these functions and their proper usage is crucial for effective C programming.
Header File
All string functions require the <string.h> header:
#include <string.h>
Some character functions are in <ctype.h>:
#include <ctype.h> // For toupper, tolower, isalpha, etc.
String Length - strlen()
Syntax
size_t strlen(const char *str);
Description
Returns the number of characters before the null terminator.
Examples
char str[] = "Hello";
size_t len = strlen(str); // Returns 5
strlen("Hello World") // Returns 11
strlen("") // Returns 0
strlen("Hi\0There") // Returns 2 (stops at first \0)
Important Notes
- •Does NOT count the null terminator
- •Returns
size_t(unsigned integer) - •Undefined behavior if string lacks null terminator
Visual Representation
String: "Hello"
┌───┬───┬───┬───┬───┬───┐
│ H │ e │ l │ l │ o │\0 │
└───┴───┴───┴───┴───┴───┘
1 2 3 4 5 (not counted)
strlen returns: 5
String Copy Functions
strcpy() - Copy String
char *strcpy(char *dest, const char *src);
Copies the source string (including null terminator) to destination.
char dest[20];
strcpy(dest, "Hello"); // dest = "Hello"
Warning: No bounds checking! Buffer overflow risk.
strncpy() - Copy with Limit
char *strncpy(char *dest, const char *src, size_t n);
Copies at most n characters from source to destination.
char dest[10];
strncpy(dest, "Hello World", sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // Ensure null termination!
Important Behaviors:
- •If src < n characters: pads with null characters
- •If src >= n characters: NO null terminator added!
- •Always manually null-terminate when using strncpy
Comparison
| Function | Safe | Null-Terminates | Padding |
|---|---|---|---|
| strcpy | No | Yes | No |
| strncpy | Partial | Not always | Yes |
String Concatenation Functions
strcat() - Concatenate Strings
char *strcat(char *dest, const char *src);
Appends source string to destination string.
char str[20] = "Hello";
strcat(str, " World"); // str = "Hello World"
Warning: No bounds checking!
strncat() - Concatenate with Limit
char *strncat(char *dest, const char *src, size_t n);
Appends at most n characters from source, then adds null terminator.
char str[15] = "Hello";
strncat(str, " World!", 6); // str = "Hello World"
Note: Unlike strncpy, strncat always adds null terminator.
Safe Concatenation Pattern
char buffer[50] = "Hello";
size_t remaining = sizeof(buffer) - strlen(buffer) - 1;
strncat(buffer, " World", remaining);
String Comparison Functions
strcmp() - Compare Strings
int strcmp(const char *s1, const char *s2);
Compares two strings lexicographically.
Return Values:
- •
0: Strings are equal - •
< 0: s1 is less than s2 - •
> 0: s1 is greater than s2
strcmp("abc", "abc") // Returns 0
strcmp("abc", "abd") // Returns < 0
strcmp("abd", "abc") // Returns > 0
strcmp("ab", "abc") // Returns < 0
strncmp() - Compare First n Characters
int strncmp(const char *s1, const char *s2, size_t n);
Compares only the first n characters.
strncmp("Hello World", "Hello There", 5) // Returns 0
strncmp("Hello World", "Hello There", 6) // Returns < 0
strcasecmp() / stricmp() - Case-Insensitive (Non-Standard)
// POSIX (Linux/Mac)
int strcasecmp(const char *s1, const char *s2);
// Windows
int _stricmp(const char *s1, const char *s2);
Note: These are not part of the C standard.
Comparison Table
| Return | Meaning | Example |
|---|---|---|
| 0 | Equal | "abc" == "abc" |
| < 0 | s1 < s2 | "abc" < "abd" |
| > 0 | s1 > s2 | "abd" > "abc" |
String Search Functions
strchr() - Find Character
char *strchr(const char *str, int c);
Returns pointer to first occurrence of character, or NULL if not found.
char *str = "Hello World";
char *ptr = strchr(str, 'o'); // Points to first 'o'
if (ptr) {
printf("Found at position: %ld\n", ptr - str); // 4
}
strrchr() - Find Character (Reverse)
char *strrchr(const char *str, int c);
Returns pointer to LAST occurrence of character.
char *str = "Hello World";
char *ptr = strrchr(str, 'o'); // Points to second 'o'
printf("Position: %ld\n", ptr - str); // 7
strstr() - Find Substring
char *strstr(const char *haystack, const char *needle);
Returns pointer to first occurrence of substring, or NULL.
char *str = "Hello World";
char *ptr = strstr(str, "World"); // Points to "World"
if (ptr) {
printf("Found: %s\n", ptr); // "World"
}
strstr(str, "xyz") // Returns NULL
strpbrk() - Find Any Character from Set
char *strpbrk(const char *str, const char *accept);
Returns pointer to first character in str that matches any character in accept.
char *str = "Hello World";
char *ptr = strpbrk(str, "aeiou"); // Points to 'e'
strspn() - Span of Characters
size_t strspn(const char *str, const char *accept);
Returns length of initial segment containing only characters from accept.
strspn("hello123", "helo") // Returns 5 (hel + lo)
strspn("123abc", "0123456789") // Returns 3
strcspn() - Complementary Span
size_t strcspn(const char *str, const char *reject);
Returns length of initial segment NOT containing any characters from reject.
strcspn("hello123", "0123456789") // Returns 5
strcspn("hello\nworld", "\n") // Returns 5
Common use: Find newline position:
char input[100];
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0'; // Remove newline
String Tokenization - strtok()
Syntax
char *strtok(char *str, const char *delim);
Description
Splits a string into tokens based on delimiters.
Basic Usage
char str[] = "Hello,World,How,Are,You";
char *token = strtok(str, ",");
while (token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ","); // NULL for subsequent calls
}
Output:
Hello
World
How
Are
You
Important Characteristics
- •Modifies original string - Replaces delimiters with '\0'
- •Uses static variable - Not thread-safe
- •First call: Pass the string
- •Subsequent calls: Pass NULL
Visual Representation
Before: "Hello,World,Test"
H e l l o , W o r l d , T e s t \0
After strtok:
H e l l o \0 W o r l d \0 T e s t \0
^ ^ ^
token 1 token 2 token 3
Thread-Safe Alternative: strtok_r()
char *strtok_r(char *str, const char *delim, char **saveptr);
char str[] = "a,b,c";
char *saveptr;
char *token = strtok_r(str, ",", &saveptr);
while (token) {
printf("%s\n", token);
token = strtok_r(NULL, ",", &saveptr);
}
Memory Functions
These work with raw memory, not just strings.
memset() - Fill Memory
void *memset(void *ptr, int value, size_t num);
Fills memory with a byte value.
char str[20];
memset(str, 'A', 10); // Fill first 10 bytes with 'A'
str[10] = '\0';
printf("%s\n", str); // "AAAAAAAAAA"
int arr[5];
memset(arr, 0, sizeof(arr)); // Zero out array
memcpy() - Copy Memory
void *memcpy(void *dest, const void *src, size_t num);
Copies num bytes from source to destination. Does NOT handle overlapping regions.
char src[] = "Hello";
char dest[10];
memcpy(dest, src, 6); // Include null terminator
memmove() - Safe Memory Copy
void *memmove(void *dest, const void *src, size_t num);
Like memcpy, but handles overlapping memory regions correctly.
char str[] = "Hello World";
memmove(str + 6, str, 5); // Overlapping regions OK
// str = "Hello Hello"
memcmp() - Compare Memory
int memcmp(const void *ptr1, const void *ptr2, size_t num);
Compares num bytes of memory.
char a[] = "Hello";
char b[] = "Hello";
if (memcmp(a, b, 5) == 0) {
printf("Equal\n");
}
memchr() - Search Memory for Byte
void *memchr(const void *ptr, int value, size_t num);
Finds first occurrence of byte in memory block.
char str[] = "Hello";
char *ptr = memchr(str, 'l', 5);
if (ptr) {
printf("Found at position: %ld\n", ptr - str); // 2
}
Other Useful Functions
sprintf() - Print to String
int sprintf(char *str, const char *format, ...);
Writes formatted output to a string.
char buffer[100];
int num = 42;
sprintf(buffer, "The answer is %d", num);
// buffer = "The answer is 42"
Warning: No bounds checking!
snprintf() - Safe Print to String
int snprintf(char *str, size_t size, const char *format, ...);
Like sprintf but with size limit.
char buffer[20];
snprintf(buffer, sizeof(buffer), "A very long message that exceeds buffer");
// Truncated to fit, always null-terminated
sscanf() - Read from String
int sscanf(const char *str, const char *format, ...);
Parses a string according to format.
char str[] = "42 3.14 Hello";
int i;
float f;
char word[20];
sscanf(str, "%d %f %s", &i, &f, word);
// i = 42, f = 3.14, word = "Hello"
Safe Alternatives
Why Use Safe Functions?
Standard functions like strcpy, strcat, sprintf have no bounds checking and can cause:
- •Buffer overflows
- •Security vulnerabilities
- •Undefined behavior
Recommended Safe Alternatives
| Unsafe | Safe Alternative |
|---|---|
| strcpy | strncpy + null terminate OR strlcpy (BSD) |
| strcat | strncat OR strlcat (BSD) |
| sprintf | snprintf |
| gets | fgets |
strlcpy and strlcat (BSD/macOS)
size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char *dst, const char *src, size_t size);
Always null-terminates and returns total length needed.
char buffer[10];
size_t len = strlcpy(buffer, "Hello World", sizeof(buffer));
// buffer = "Hello Wor\0" (truncated)
// len = 11 (full length of source)
if (len >= sizeof(buffer)) {
printf("Truncation occurred!\n");
}
Note: Not available on all systems (not in glibc).
Example: Safe String Building
char result[100] = "";
// Safe concatenation pattern
void safe_concat(char *dest, size_t dest_size, const char *src) {
size_t current_len = strlen(dest);
size_t remaining = dest_size - current_len - 1;
if (remaining > 0) {
strncat(dest, src, remaining);
}
}
safe_concat(result, sizeof(result), "Hello");
safe_concat(result, sizeof(result), " ");
safe_concat(result, sizeof(result), "World");
Best Practices
1. Always Check Buffer Sizes
// BAD
char buffer[10];
strcpy(buffer, user_input); // Buffer overflow risk!
// GOOD
char buffer[10];
strncpy(buffer, user_input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
2. Use snprintf for Formatting
// BAD
char msg[50];
sprintf(msg, "Name: %s, Age: %d", name, age);
// GOOD
char msg[50];
snprintf(msg, sizeof(msg), "Name: %s, Age: %d", name, age);
3. Check Return Values
char *result = strstr(haystack, needle);
if (result == NULL) {
// Handle not found case
}
4. Null Terminate After strncpy
char dest[20];
strncpy(dest, source, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // ALWAYS do this!
5. Don't Modify String Literals
char *str = "Hello"; // Points to read-only memory
// str[0] = 'J'; // UNDEFINED BEHAVIOR!
char str[] = "Hello"; // Array copy on stack
str[0] = 'J'; // OK
6. Use const for Read-Only Parameters
// Function doesn't modify the string
size_t count_chars(const char *str, char c) {
// ...
}
Summary
Quick Reference
| Function | Purpose | Safe? |
|---|---|---|
| strlen | Length | Yes |
| strcpy | Copy | No |
| strncpy | Copy n chars | Partial |
| strcat | Concatenate | No |
| strncat | Concat n chars | Partial |
| strcmp | Compare | Yes |
| strncmp | Compare n chars | Yes |
| strchr | Find char | Yes |
| strrchr | Find char (reverse) | Yes |
| strstr | Find substring | Yes |
| strtok | Tokenize | Modifies input |
| sprintf | Format to string | No |
| snprintf | Safe format | Yes |
Function Categories
- •Length: strlen
- •Copy: strcpy, strncpy, memcpy, memmove
- •Concatenate: strcat, strncat
- •Compare: strcmp, strncmp, memcmp
- •Search: strchr, strrchr, strstr, strpbrk
- •Tokenize: strtok, strtok_r
- •Memory: memset, memchr
- •Format: sprintf, snprintf, sscanf
Memory Rule
Size needed for string = strlen(string) + 1 // +1 for null terminator
Common Patterns
// Remove newline from fgets
input[strcspn(input, "\n")] = '\0';
// Safe string copy
strncpy(dest, src, size - 1);
dest[size - 1] = '\0';
// Find position in string
size_t pos = ptr - str; // Where ptr = strchr(str, c)