String Functions
String functions are like wrenches and screwdrivers in a toolbox -- each tool solves a specific problem: copying, concatenating, comparing, searching. Master them, and you will handle text with confidence.
string.h Overview
<string.h> is the core header file for string operations in the C standard library, providing functions for copying, concatenating, comparing, and searching. You must include it before use:
#include <string.h>
strcpy and strncpy
strcpy
strcpy copies the source string to the destination array, including \0:
char dest[20];
strcpy(dest, "Hello World");
printf("%s\n", dest);
Prototype: char *strcpy(char *dest, const char *src);
strcpy does not check the destination buffer size. If the source string is larger than the destination array, it writes out of bounds. Ensure the destination array is large enough before using it.
strncpy
strncpy limits the maximum number of bytes to copy, making it safer:
char dest[6];
strncpy(dest, "Hello World", sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';
printf("%s\n", dest);
Prototype: char *strncpy(char *dest, const char *src, size_t n);
strncpy copies at most n bytes. If the source string is shorter than n, the remaining positions are filled with \0; if the source string is n bytes or longer, it does not automatically append \0. Therefore, you must add it manually.
\0 when using strncpy, and manually append \0 after copying.
strcat and strncat
strcat
strcat appends the source string to the end of the destination string:
char buf[50] = "Hello";
strcat(buf, " World");
printf("%s\n", buf);
Prototype: char *strcat(char *dest, const char *src);
The existing \0 at the end of the destination string is overwritten, and a new \0 is placed after the concatenated result.
strcat does not check the buffer size.
strncat
strncat limits the maximum number of characters to append and automatically adds \0:
char buf[10] = "Hi";
strncat(buf, " World!", sizeof(buf) - strlen(buf) - 1);
printf("%s\n", buf);
Prototype: char *strncat(char *dest, const char *src, size_t n);
It appends at most n characters, then automatically adds \0. It is safer than strncpy because it guarantees null termination.
strcmp and strncmp
strcmp
strcmp compares two strings lexicographically, character by character:
int result = strcmp("abc", "abd");
Return value meanings:
< 0: s1 is less than s2= 0: s1 equals s2> 0: s1 is greater than s2
if (strcmp(s1, s2) == 0) {
printf("Equal\n");
}
strcmp to compare strings, never ==. == compares pointer addresses, not string contents.
strncmp
strncmp compares only the first n characters:
if (strncmp(str, "GET ", 4) == 0) {
printf("GET request\n");
}
Useful for comparing prefixes or limiting the comparison scope.
Example
Sort an array of strings in lexicographic order:
#include <stdio.h>
#include <string.h>
void sort_strings(char arr[][32], int n) {
int i, j;
char temp[32];
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - 1 - i; j++) {
if (strcmp(arr[j], arr[j + 1]) > 0) {
strcpy(temp, arr[j]);
strcpy(arr[j], arr[j + 1]);
strcpy(arr[j + 1], temp);
}
}
}
}
int main(void) {
char names[5][32] = {
"david",
"alice",
"charlie",
"bob",
"eve"
};
int i;
sort_strings(names, 5);
for (i = 0; i < 5; i++) {
printf("%s\n", names[i]);
}
return 0;
}
alice
bob
charlie
david
eve
strlen
strlen returns the effective length of a string (not including \0):
char s[] = "Hello";
printf("%zu\n", strlen(s));
printf("%zu\n", sizeof(s));
Output: 5 and 6. strlen counts up to \0; sizeof includes \0.
strlen traverses the string to find \0, with O(n) time complexity. If you use the same string's length multiple times, cache the result:
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) {
}
Rather than calling strlen in the loop condition every iteration.
strchr and strrchr
strchr finds the first occurrence of a character in a string:
const char *p = strchr("Hello World", 'o');
if (p != NULL) {
printf("Found: %s\n", p);
}
Output: "o World". It returns a pointer to that character, or NULL if not found.
strrchr finds the last occurrence of a character:
const char *p = strrchr("Hello World", 'o');
if (p != NULL) {
printf("Last occurrence: %s\n", p);
}
Output: "orld".
strstr
strstr finds the first occurrence of a substring in a string:
const char *p = strstr("Hello World", "World");
if (p != NULL) {
printf("Substring at: %s\n", p);
}
Output: "World". Returns NULL if not found.
Finding all occurrences:
const char *text = "abababab";
const char *p = text;
while ((p = strstr(p, "ab")) != NULL) {
printf("Position %ld\n", (long)(p - text));
p++;
}
After each find, advance the pointer by one and continue searching for subsequent occurrences.
Custom String Function Implementations
Understanding how standard functions work internally helps you grasp the essence of string operations.
Custom strlen
size_t my_strlen(const char *s) {
size_t len = 0;
while (s[len] != '\0') {
len++;
}
return len;
}
Custom strcpy
char *my_strcpy(char *dest, const char *src) {
char *d = dest;
while ((*d++ = *src++) != '\0') {
}
return dest;
}
This compact form: *d++ = *src++ copies the character first, then both pointers advance, until \0 is copied.
Custom strcmp
int my_strcmp(const char *s1, const char *s2) {
while (*s1 == *s2) {
if (*s1 == '\0') return 0;
s1++;
s2++;
}
return (unsigned char)*s1 - (unsigned char)*s2;
}
Compare character by character: continue while equal, stop when a difference or \0 is found. Return the difference to indicate the ordering. Casting to unsigned char ensures negative character values do not affect the comparison result.
Example
Custom strcat and test:
#include <stdio.h>
char *my_strcat(char *dest, const char *src) {
char *d = dest;
while (*d != '\0') {
d++;
}
while ((*d++ = *src++) != '\0') {
}
return dest;
}
int main(void) {
char buf[50] = "Hello";
my_strcat(buf, ", ");
my_strcat(buf, "World!");
printf("%s\n", buf);
return 0;
}
Hello, World!
First find the \0 at the end of dest, then copy the contents of src starting from that position.
❓ FAQ
\0?strncpy was originally designed to fill fixed-length buffers (like filename fields): pad with \0 when shorter than n, but do not add \0 when n bytes are reached. When used as a safer strcpy, you must add \0 manually.strcmp matter?==0, <0, >0.strcat is inefficient for multiple concatenations -- what to do?strcat scans from the beginning of dest to the end before appending, making the total efficiency O(n^2) for multiple concatenations. You can manually track the current end position and append directly from there.📖 Summary
strcpy/strncpycopy strings; strncpy is safer but requires manual\0terminationstrcat/strncatconcatenate strings; strncat automatically adds\0strcmp/strncmpcompare strings; never use==to compare string contentsstrchr/strrchrsearch for characters;strstrsearches for substrings- Custom implementations help understand underlying principles; use standard library in real projects
📝 Exercises
- Write a function
void str_tolower(char *s)that converts all uppercase letters in a string to lowercase. - Write a function
int str_count_char(const char *s, char ch)that counts how many times the characterchappears in strings. - Without using any string.h functions, write
my_strstrto implement substring search.



