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.