String Operations in C Language for Embedded Development

String Operations in C Language

String operations are a frequent knowledge point in embedded development, where data transmission often requires operations such as copying, concatenating, and splitting strings. This article organizes the commonly used API functions for string operations in C language for easy reference on basic usage.

The following header files basically include all operations on strings in C language:

#include <string.h>
#include <strlib.h>

Among them, <span>string.h</span> includes operations such as copying, comparing, concatenating, and searching, while <span>strlib.h</span> includes operations such as memory management and numeric conversion.

First, define a string constant in C language, which will be used for a series of common operations:

const char *src = "this is a string for test";

String Copy

Common Function APIs

//char *strcpy(char *dst, const char *src);     // unconditional copy
//char *strncpy(char *dst, const char *src, size_t n); // copy up to n bytes, does not guarantee '\0'
//char *strcpy_s(char *dst, rsize_t dmax, const char *src); // C11 optional Annex K safe version
//char *strdup(const char *s);               // non-C standard, but provided by POSIX/mainstream compilers: malloc a copy

Usage Example:

void test_cp(void)
{
    printf("------------------------------------------------\n");
    char dst1[32], dst2[32], dst3[32];
    strcpy(dst1, src); // full copy
    printf("[strcpy]: %s\n" ,dst1);

    strncpy(dst2, src, 7); // copy specified length
    printf("[strncpy]: %s\n" ,dst2);

    strcpy_s(dst3, sizeof(dst3), src); // full copy
    printf("[strcpy_s]: %s\n" ,dst3);

    char *dup = strdup(src); // allocate new memory and copy
    printf("[strdup]: %s\n" ,dup);
}

Run Result:

------------------------------------------------
[strcpy]: this is a string for test
[strncpy]: this is
[strcpy_s]: this is a string for test
[strdup]: this is a string for test

String Concatenation

Common Function APIs

//char *strcat(char *dst, const char *src);     // unconditional append
//char *strncat(char *dst, const char *src, size_t n); // append up to n characters, guarantees ending '\0'

Usage Example:

void test_cat(void)
{
    printf("------------------------------------------------\n");
    char dst1[32] = "[strcat]: ";
    strcat(dst1, src); // full append
    printf("%s\n" ,dst1);

    char dst2[32] = "[strncat]: ";
    strncat(dst2, src, 7); // append specified length
    printf("%s\n" ,dst2);
}

Run Result:

------------------------------------------------
[strcat]: this is a string for test
[strncat]: this is

String Comparison

Common Function APIs

//int strcmp(const char *s1, const char *s2);   // compare in dictionary order
//int strncmp(const char *s1, const char *s2, size_t n); // compare up to n characters
//int strcasecmp(const char *s1, const char *s2); // POSIX extension: case-insensitive comparison

Usage Example:

void test_cmp(void)
{
    printf("------------------------------------------------\n");
    constchar *dst1 = "This is a string for test";
    if (strcmp(dst1, src) == 0) { // compare in dictionary order, returns 0 if equal
        printf("[strcmp], same string\n");
    } else {
        printf("[strcmp], different string\n");
    }
    
    constchar *dst2 = "this is a string";
    if (strncmp(dst2, src, 16) == 0) { // compare specified length, returns 0 if equal
        printf("[strncmp]: same string\n");
    } else {
        printf("[strncmp]: different string\n");
    }

    constchar *dst3 = "This is a string for test";
    if (strcasecmp(dst3, src) == 0) { // case-insensitive comparison
        printf("[strcasecmp]: same string\n");
    } else {
        printf("[strcasecmp]: different string\n");
    }
}

Run Result:

------------------------------------------------
[strcmp], different string
[strncmp]: same string
[strcasecmp]: same string

String Search

Common Function APIs

//char *strchr(const char *s, int c);        // find first occurrence of character c
//char *strrchr(const char *s, int c);       // find last occurrence of character c
//char *strstr(const char *hay, const char *needle); // find first occurrence of substring
//char *strpbrk(const char *s, const char *accept); // find first occurrence of any character in accept
//size_t strcspn(const char *s, const char *reject); // number of characters from the start that do not contain reject
//size_t strspn(const char *s, const char *accept); // number of characters from the start that belong to accept

Usage Example

void test_chr(void)
{
    printf("------------------------------------------------\n");
    char *left = strchr(src, 's'); // find first occurrence
    printf("[strchr]: %d\n", left - src); //[strchr]: 3

    char *right = strrchr(src, 's'); // find last occurrence
    printf("[strchr]: %d\n", right - src); //[strchr]: 23

    char *s = strstr(src, "is"); // find first occurrence of substring
    printf("[strstr]: %d, %s\n", s - src, s); //[strstr]: 2, is is a string for test
    s = strstr(s, "for");
    printf("[strstr]: %s\n", s); //[strstr]: for test

    constchar *sep = "is";
    char *p = strpbrk(src, sep); // find first occurrence of any character in substring
    while (p) {
        printf("[strpbrk]: found sep '%c' at offset %td\n", *p, p - src);
        p = strpbrk(p + 1, sep);
    }

    size_t pos1 = strcspn(src, "is");
    printf("[strcspn]: scheme length = %zu\n", pos1);//strcspn stops at the first character belonging to the set (here 'i', index 2)

    size_t pos2 = strspn(src, "this is");
    printf("[strspn]: scheme length = %zu\n", pos2);//strspn stops at the first character not belonging to the set (here 'a', index 7)
}

Run Result:

------------------------------------------------
[strchr]: 3
[strchr]: 23
[strstr]: 2, is is a string for test
[strstr]: for test
[strpbrk]: found sep 'i' at offset 2
[strpbrk]: found sep 's' at offset 3
[strpbrk]: found sep 'i' at offset 5
[strpbrk]: found sep 's' at offset 6
[strpbrk]: found sep 's' at offset 10
[strpbrk]: found sep 'i' at offset 13
[strpbrk]: found sep 's' at offset 23
[strcspn]: scheme length = 2
[strspn]: scheme length = 8

String Memory Operations

Common Function APIs

//void *memcpy(void *dst, const void *src, size_t n);   // memory block copy
//void *memmove(void *dst, const void *src, size_t n); // copy with overlapping regions
//void *memset(void *s, int c, size_t n);              // fill by byte
//int memcmp(const void *s1, const void *s2, size_t n); // compare memory blocks
//void *memchr(const void *s, int c, size_t n);        // find character c within n bytes

Usage Example

void test_mem(void)
{
    printf("------------------------------------------------\n");
    char *src1 = "string";
    char dst1[7];
    memcpy(dst1, src1, 7);
    printf("[memcpy]: %s\n", dst1);//[memcpy]: string

    memmove(dst1, dst1 + 2, 4);
    printf("[memmove]: %s\n", dst1);//[memmove]: ring

    memset(dst1, '0', 6);
    dst1[6] = '\0';
    printf("[memset]: %s\n", dst1);//[memset]: 000000

    char *s = memchr(src, 'a', 7);
    printf("[memchr]: %s\n", s);//[memchr]: (null)

    s = memchr(src, 'a', 10);
    printf("[memchr]: %s\n", s);//[memchr]: a string for test
}

Run Result:

------------------------------------------------
[memcpy]: string
[memmove]: ringng
[memset]: 000000
[memchr]: (null)
[memchr]: a string for test

String Splitting

Common Function APIs

//char *strtok(char *str, const char *delim);          // single-thread reentrant split (first pass str, subsequent passes NULL)

Usage Example

void test_tok(void)
{
    printf("------------------------------------------------\n");
    char src1[] = "This is a string for test";
    char *s = strtok(src1, "s");
    while (s != NULL) {
        printf("[strtok]: %s\n", s);
        s = strtok(NULL, "s");
    }
}

Run Result:

------------------------------------------------
[strtok]: Thi
[strtok]:  i
[strtok]:  a 
[strtok]: tring for te
[strtok]: t

String Formatting

Common Function APIs

//int toupper(int c);
//int tolower(int c);

//int atoi(const char *nptr);
//long strtol(const char *nptr, char **endptr, int base);
//unsigned long strtoul(...);
//double strtod(const char *nptr, char **endptr);
//int sprintf(char *buf, const char *fmt, ...);      // format write string
//int snprintf(char *buf, size_t size, const char *fmt, ...); // safe version
//int sscanf(const char *buf, const char *fmt, ...); // parse from string

Usage Example

void test_fmt(void)
{
    printf("------------------------------------------------\n");
    char a = 'a', t = 'T';
    printf("%c%c\n", toupper(a), tolower(t));

    printf("[atoi]: %d\n", atoi("100"));
    char *end;
    printf("[strtol]: %ld\n", strtol("-31415926", &end, 0));
    printf("[strtoul]: %lu\n", strtoul("31415926", &end, 0));
    printf("[strtod]: %.7f\n", strtod("3.1415926", &end));

    char date[32];
    int year = 2025, month = 9, day = 29;
    int r1 = sprintf(date, "today is %d/%02d/%02d", year, month, day);//len
    printf("[sprintf]: %d, %s\n", r1, date);

    char time[32];
    int hour = 9, minute = 45, second = 29;
    int r2 = snprintf(time, sizeof(time), "timenow is %02d:%02d:%02d", hour, minute, second);//len
    printf("[snprintf]: %d %s\n", r2, time);

    int y, m, d;
    int r3 = sscanf(date, "today is %d/%02d/%02d", &y, &m, &d);//num
    printf("[sscanf]: %d, tomorrow is %d/%02d/%02d", r3, y, m, d + 1);
}

Run Result:

------------------------------------------------
At
[atoi]: 100
[strtol]: -31415926
[strtoul]: 31415926
[strtod]: 3.1415926
[sprintf]: 19, today is 2025/09/29
[snprintf]: 19 timenow is 17:59:59
[sscanf]: 3, tomorrow is 2025/09/30

Unlike C++, which has a dedicated <span>string</span> class, C language commonly uses <span>char *</span> to define a string. Since it involves pointer operations, there is a risk of array overflow, so operations on strings need to be particularly cautious about length.

I hope the above content can assist you in your daily development work. If there are any errors or omissions, please feel free to communicate and correct them.

Leave a Comment