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:

C
#include <string.h>

strcpy and strncpy

strcpy

strcpy copies the source string to the destination array, including \0:

C
char dest[20];
strcpy(dest, "Hello World");
printf("%s\n", dest);

Prototype: char *strcpy(char *dest, const char *src);

⚠️ Note: 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:

C
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.

💡 Tip: Always reserve space for \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:

C
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.

⚠️ Note: The destination array must have enough space for the concatenated result. strcat does not check the buffer size.

strncat

strncat limits the maximum number of characters to append and automatically adds \0:

C
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:

C
int result = strcmp("abc", "abd");

Return value meanings:

C
if (strcmp(s1, s2) == 0) {
    printf("Equal\n");
}
⚠️ Note: Use strcmp to compare strings, never ==. == compares pointer addresses, not string contents.

strncmp

strncmp compares only the first n characters:

C
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:

C
#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;
}
▶ Try it Yourself
TEXT
alice
bob
charlie
david
eve

strlen

strlen returns the effective length of a string (not including \0):

C
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:

C
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:

C
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:

C
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:

C
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:

C
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

C
size_t my_strlen(const char *s) {
    size_t len = 0;
    while (s[len] != '\0') {
        len++;
    }
    return len;
}

Custom strcpy

C
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

C
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:

C
#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;
}
▶ Try it Yourself
TEXT
Hello, World!

First find the \0 at the end of dest, then copy the contents of src starting from that position.

❓ FAQ

Q Why doesn't strncpy automatically append \0?
A 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.
Q Does the specific numeric value returned by strcmp matter?
A You should only check whether it is positive, negative, or zero -- do not depend on the exact value. Different implementations return different differences; portable code only uses ==0, <0, >0.
Q strcat is inefficient for multiple concatenations -- what to do?
A Each 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.
Q What is the point of implementing string functions yourself?
A Understanding underlying principles, common interview questions, and embedded development where the standard library may not be available. However, prefer standard library functions in real projects -- they are thoroughly tested and optimized.

📖 Summary

📝 Exercises

  1. Write a function void str_tolower(char *s) that converts all uppercase letters in a string to lowercase.
  2. Write a function int str_count_char(const char *s, char ch) that counts how many times the character ch appears in string s.
  3. Without using any string.h functions, write my_strstr to implement substring search.
100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏