C course menu
String Functions in C: strlen, strcpy, strcat, strcmp, strchr, strstr and snprintf
Learn the C string library string.h: strlen, strcpy and strncpy, strcat, strcmp and why == does not compare strings, strchr and strstr for searching, strtok for splitting, building strings safely with snprintf, and converting text to numbers with strtol.
On this page
<string.h> provides the standard functions for working with null-terminated strings. None of them know how big your arrays are, so you must make sure the destination has room.
Length, copy and join#
#include <stdio.h>
#include <string.h>
int main(void) {
char full[40];
const char *first = "Asha";
const char *last = "Raman";
strcpy(full, first); /* copy */
strcat(full, " "); /* append */
strcat(full, last);
printf("%s\n", full);
printf("length %zu, array size %zu\n", strlen(full), sizeof full);
return 0;
}Asha Raman
length 10, array size 40strlen counts characters before the '\0', so it is different from sizeof, the array's size in bytes.
strcpy and strcat write past the end of the destination if it is too small: a buffer overflow. Check the sizes first, or build strings with snprintf (below).
Comparing strings#
== compares two addresses, not the text. Use strcmp, which returns 0 when the strings are equal, a negative value if the first comes earlier in dictionary (character-code) order, and a positive value if it comes later:
#include <stdio.h>
#include <string.h>
int main(void) {
char input[] = "admin";
const char *role = "admin";
printf("same text: %d\n", strcmp(input, role) == 0);
printf("%d\n", strcmp("apple", "banana") < 0);
printf("%d\n", strcmp("Zebra", "apple") < 0); /* 'Z' (90) < 'a' (97) */
printf("%d\n", strncmp("prefix-123", "prefix", 6) == 0);
return 0;
}same text: 1
1
1
1Uppercase letters have smaller character codes than lowercase ones, so strcmp sorts "Zebra" before "apple".
Searching#
#include <stdio.h>
#include <string.h>
int main(void) {
const char *email = "student@example.com";
const char *at = strchr(email, '@'); /* first '@' */
if (at != NULL) {
printf("domain: %s\n", at + 1);
printf("user length: %d\n", (int)(at - email));
}
const char *found = strstr(email, "example");
printf("%s\n", found ? "contains example" : "not found");
return 0;
}domain: example.com
user length: 7
contains examplestrchr and strstr return a pointer to the match, or NULL when there is none.
Splitting with strtok#
strtok splits a string into tokens. The first call gets the string; later calls pass NULL to continue. It modifies the string (it writes '\0' over the separators), so it needs a modifiable array, not a literal:
#include <stdio.h>
#include <string.h>
int main(void) {
char line[] = "C,Java,Python,,SQL";
for (char *tok = strtok(line, ","); tok != NULL; tok = strtok(NULL, ",")) {
printf("[%s]\n", tok);
}
return 0;
}[C]
[Java]
[Python]
[SQL]Empty fields (,,) are skipped, and strtok keeps hidden state, so you cannot split two strings at the same time with it.
Building strings safely with snprintf#
snprintf works like printf but writes into an array, never writing more than the size you give, and always adding '\0'. It returns the length the full text would have had, so you can detect truncation:
#include <stdio.h>
int main(void) {
char label[32];
int roll = 42;
double score = 91.456;
snprintf(label, sizeof label, "Roll %03d: %.1f%%", roll, score);
printf("%s\n", label);
char small[8];
int needed = snprintf(small, sizeof small, "%s", "truncated text");
printf("[%s] needed %d\n", small, needed);
return 0;
}Roll 042: 91.5%
[truncat] needed 14When the lengths are known at compile time, GCC even warns about this: '%s' directive output truncated.
Text to numbers#
atoi("42") is simple but cannot report errors (atoi("abc") returns 0). strtol tells you where the number stopped:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *inputs[] = {"250", "12abc", "abc"};
for (int i = 0; i < 3; i++) {
char *end;
long value = strtol(inputs[i], &end, 10);
if (end == inputs[i]) {
printf("\"%s\": not a number\n", inputs[i]);
} else if (*end != '\0') {
printf("\"%s\": %ld, then extra text \"%s\"\n", inputs[i], value, end);
} else {
printf("\"%s\": %ld\n", inputs[i], value);
}
}
return 0;
}"250": 250
"12abc": 12, then extra text "abc"
"abc": not a numberstrtod does the same for floating-point numbers.
Quick reference#
Practice#
Practice exercise
Given char csv[] = "Asha,87;Ravi,92;Meena,78";, split it into records with ;, then split each record at the comma with strchr, and print the name with the highest mark.
Show solution
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char csv[] = "Asha,87;Ravi,92;Meena,78";
char best_name[20] = "";
int best = -1;
for (char *rec = strtok(csv, ";"); rec != NULL; rec = strtok(NULL, ";")) {
char *comma = strchr(rec, ',');
if (comma == NULL) continue;
*comma = '\0'; /* rec is now just the name */
int mark = (int)strtol(comma + 1, NULL, 10);
if (mark > best) {
best = mark;
snprintf(best_name, sizeof best_name, "%s", rec);
}
}
printf("%s scored highest with %d\n", best_name, best);
return 0;
}Ravi scored highest with 92Key takeaway#
Finished this lesson?