C String Functions
Introduction to String Functions
C provides a rich set of string handling functions in the string.h header file. These functions allow you to perform various operations on strings without having to implement the logic yourself.
Understanding these functions is crucial for efficient string manipulation in C programs.
Common String Functions
The string.h library provides several essential functions:
• strlen() - Calculate string length
• strcpy() - Copy one string to another
• strncpy() - Copy limited characters from one string to another (be careful: may not null-terminate)
• strcat() - Concatenate two strings (risk of overflow if destination too small)
• strncat() - Concatenate limited characters from one string to another
• strcmp() - Compare two strings
• strncmp() - Compare limited characters of two strings
• strchr() - Find first occurrence of a character in a string
• strstr() - Find first occurrence of a substring in a string
• strtok() - Split string into tokens (modifies the input, not thread-safe)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[50] = "Hello";
char str2[50] = "World";
char str3[50];
printf("Length of '%s': %zu\n", str1, strlen(str1));
strcpy(str3, str1);
printf("After strcpy: %s\n", str3);
strcat(str3, " ");
strcat(str3, str2);
printf("After strcat: %s\n", str3);
int result = strcmp(str1, str2);
if (result < 0) {
printf("'%s' comes before '%s'\n", str1, str2);
} else if (result > 0) {
printf("'%s' comes after '%s'\n", str1, str2);
} else {
printf("'%s' equals '%s'\n", str1, str2);
}
return 0;
}
Length of 'Hello': 5 After strcpy: Hello After strcat: Hello World 'Hello' comes before 'World'
Safer String Handling (Portable Patterns)
Many classic functions (strcpy/strcat) do not check buffer sizes. C11 defined optional bounds-checking interfaces with a _s suffix in Annex K (e.g., strcpy_s), but they are not widely implemented and are non-portable.
Portable approaches you can use today:
• Prefer snprintf() for copying/formatting into fixed buffers.
• When concatenating, compute remaining space and use strncat().
• Always ensure the destination is large enough and null-terminated.
#include <stdio.h>
#include <string.h>
int main(void) {
// Safe copy with snprintf (always null-terminates if size > 0)
char dest[10];
const char *src = "This is a long string that might overflow";
snprintf(dest, sizeof dest, "%s", src);
printf("Safe copy: %s\n", dest);
// Safe-ish concatenation: compute remaining space
char buf[16] = "Hello";
const char *add = " World!";
size_t space = sizeof buf - strlen(buf) - 1; // space for new chars (excluding NUL)
strncat(buf, add, space);
printf("Safe concat: %s\n", buf);
return 0;
}
Safe copy: This is a Safe concat: Hello World!
String Search Functions
C provides functions to search for characters and substrings within strings:
• strchr() - Find first occurrence of a character
• strrchr() - Find last occurrence of a character
• strstr() - Find first occurrence of a substring
• strpbrk() - Find first occurrence of any character from a set
#include <stdio.h>
#include <string.h>
int main(void) {
const char text[] = "The quick brown fox jumps over the lazy dog";
const char *firstO = strchr(text, 'o');
if (firstO) {
printf("First 'o' at position: %td\n", firstO - text);
}
const char *lastO = strrchr(text, 'o');
if (lastO) {
printf("Last 'o' at position: %td\n", lastO - text);
}
const char *fox = strstr(text, "fox");
if (fox) {
printf("Substring 'fox' found at position: %td\n", fox - text);
}
const char *vowel = strpbrk(text, "aeiou");
if (vowel) {
printf("First vowel '%c' at position: %td\n", *vowel, vowel - text);
}
return 0;
}
First 'o' at position: 12 Last 'o' at position: 41 Substring 'fox' found at position: 16 First vowel 'e' at position: 2
String Tokenization
The strtok() function is used to split a string into tokens based on delimiters. It modifies the original string and keeps internal state, so it is not thread-safe.
Alternatives: POSIX provides strtok_r() (reentrant), and some platforms provide strtok_s() (Annex K).
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "apple,banana,cherry,date,elderberry";
char *token;
printf("Original string: %s\n", text);
printf("Tokens:\n");
token = strtok(text, ",");
while (token != NULL) {
printf("- %s\n", token);
token = strtok(NULL, ",");
}
printf("Modified string: %s\n", text);
return 0;
}
Original string: apple,banana,cherry,date,elderberry Tokens: - apple - banana - cherry - date - elderberry Modified string: apple
String Conversion & Formatting
Prefer strtol/strtoul/strtod for robust string-to-number conversion (they report errors). Use snprintf for formatted output to a buffer and width limits in sscanf to avoid overflows.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(void) {
const char numStr[] = "12345";
const char floatStr[] = "3.14159";
char *end;
errno = 0;
long num = strtol(numStr, &end, 10);
if (errno == 0 && *end == '\0') {
printf("'%s' -> long: %ld\n", numStr, num);
}
errno = 0;
double pi = strtod(floatStr, &end);
if (errno == 0 && *end == '\0') {
printf("'%s' -> double: %.6f\n", floatStr, pi);
}
char buffer[50];
int value = 42; double amount = 99.95;
snprintf(buffer, sizeof buffer, "Value: %d, Amount: %.2f", value, amount);
printf("Formatted string: %s\n", buffer);
char data[] = "John 25 75.5";
char name[20]; int age; float score;
if (sscanf(data, "%19s %d %f", name, &age, &score) == 3) {
printf("Name: %s, Age: %d, Score: %.1f\n", name, age, score);
}
return 0;
}
'12345' -> long: 12345 '3.14159' -> double: 3.141590 Formatted string: Value: 42, Amount: 99.95 Name: John, Age: 25, Score: 75.5
Best Practices
1. Always ensure destination buffers are large enough; bound all writes (snprintf, width limits in scanf-family).
2. Prefer %zu for size_t (e.g., printing strlen results) and %td for pointer differences.
3. Be cautious with strncpy: it doesn't always null-terminate; add the terminator yourself when truncating.
4. Avoid unsafe copies/concats (strcpy/strcat) unless you are certain of buffer sizes.
5. strtok modifies its input; if you need thread-safety or to keep the original, use strtok_r (POSIX) or tokenize a copy.
6. For numeric parsing, prefer strtol/strtoul/strtod over atoi/atof/atol; they provide error detection.