Docs

README

String Functions in C

Table of Contents

  1. Introduction
  2. Header File
  3. String Length - strlen()
  4. String Copy Functions
  5. String Concatenation Functions
  6. String Comparison Functions
  7. String Search Functions
  8. String Tokenization - strtok()
  9. Memory Functions
  10. Other Useful Functions
  11. Safe Alternatives
  12. Best Practices
  13. Summary

Introduction

The C Standard Library provides a rich set of functions for string manipulation through the <string.h> header file. These functions are essential for:

  • Measuring string length
  • Copying strings
  • Concatenating strings
  • Comparing strings
  • Searching within strings
  • Tokenizing strings
  • Memory manipulation

Understanding these functions and their proper usage is crucial for effective C programming.


Header File

All string functions require the <string.h> header:

#include <string.h>

Some character functions are in <ctype.h>:

#include <ctype.h>  // For toupper, tolower, isalpha, etc.

String Length - strlen()

Syntax

size_t strlen(const char *str);

Description

Returns the number of characters before the null terminator.

Examples

char str[] = "Hello";

size_t len = strlen(str);  // Returns 5

strlen("Hello World")      // Returns 11
strlen("")                 // Returns 0
strlen("Hi\0There")        // Returns 2 (stops at first \0)

Important Notes

  1. Does NOT count the null terminator
  2. Returns size_t (unsigned integer)
  3. Undefined behavior if string lacks null terminator

Visual Representation

String: "Hello"
        ┌───┬───┬───┬───┬───┬───┐
        │ H │ e │ l │ l │ o │\0 │
        └───┴───┴───┴───┴───┴───┘
          1   2   3   4   5   (not counted)

strlen returns: 5

String Copy Functions

strcpy() - Copy String

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

Copies the source string (including null terminator) to destination.

char dest[20];
strcpy(dest, "Hello");  // dest = "Hello"

Warning: No bounds checking! Buffer overflow risk.

strncpy() - Copy with Limit

char *strncpy(char *dest, const char *src, size_t n);

Copies at most n characters from source to destination.

char dest[10];
strncpy(dest, "Hello World", sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';  // Ensure null termination!

Important Behaviors:

  • If src < n characters: pads with null characters
  • If src >= n characters: NO null terminator added!
  • Always manually null-terminate when using strncpy

Comparison

FunctionSafeNull-TerminatesPadding
strcpyNoYesNo
strncpyPartialNot alwaysYes

String Concatenation Functions

strcat() - Concatenate Strings

char *strcat(char *dest, const char *src);

Appends source string to destination string.

char str[20] = "Hello";
strcat(str, " World");  // str = "Hello World"

Warning: No bounds checking!

strncat() - Concatenate with Limit

char *strncat(char *dest, const char *src, size_t n);

Appends at most n characters from source, then adds null terminator.

char str[15] = "Hello";
strncat(str, " World!", 6);  // str = "Hello World"

Note: Unlike strncpy, strncat always adds null terminator.

Safe Concatenation Pattern

char buffer[50] = "Hello";
size_t remaining = sizeof(buffer) - strlen(buffer) - 1;
strncat(buffer, " World", remaining);

String Comparison Functions

strcmp() - Compare Strings

int strcmp(const char *s1, const char *s2);

Compares two strings lexicographically.

Return Values:

  • 0 : Strings are equal
  • < 0 : s1 is less than s2
  • > 0 : s1 is greater than s2
strcmp("abc", "abc")   // Returns 0
strcmp("abc", "abd")   // Returns < 0
strcmp("abd", "abc")   // Returns > 0
strcmp("ab", "abc")    // Returns < 0

strncmp() - Compare First n Characters

int strncmp(const char *s1, const char *s2, size_t n);

Compares only the first n characters.

strncmp("Hello World", "Hello There", 5)  // Returns 0
strncmp("Hello World", "Hello There", 6)  // Returns < 0

strcasecmp() / stricmp() - Case-Insensitive (Non-Standard)

// POSIX (Linux/Mac)
int strcasecmp(const char *s1, const char *s2);

// Windows
int _stricmp(const char *s1, const char *s2);

Note: These are not part of the C standard.

Comparison Table

ReturnMeaningExample
0Equal"abc" == "abc"
< 0s1 < s2"abc" < "abd"
> 0s1 > s2"abd" > "abc"

String Search Functions

strchr() - Find Character

char *strchr(const char *str, int c);

Returns pointer to first occurrence of character, or NULL if not found.

char *str = "Hello World";
char *ptr = strchr(str, 'o');  // Points to first 'o'
if (ptr) {
    printf("Found at position: %ld\n", ptr - str);  // 4
}

strrchr() - Find Character (Reverse)

char *strrchr(const char *str, int c);

Returns pointer to LAST occurrence of character.

char *str = "Hello World";
char *ptr = strrchr(str, 'o');  // Points to second 'o'
printf("Position: %ld\n", ptr - str);  // 7

strstr() - Find Substring

char *strstr(const char *haystack, const char *needle);

Returns pointer to first occurrence of substring, or NULL.

char *str = "Hello World";
char *ptr = strstr(str, "World");  // Points to "World"
if (ptr) {
    printf("Found: %s\n", ptr);  // "World"
}

strstr(str, "xyz")  // Returns NULL

strpbrk() - Find Any Character from Set

char *strpbrk(const char *str, const char *accept);

Returns pointer to first character in str that matches any character in accept.

char *str = "Hello World";
char *ptr = strpbrk(str, "aeiou");  // Points to 'e'

strspn() - Span of Characters

size_t strspn(const char *str, const char *accept);

Returns length of initial segment containing only characters from accept.

strspn("hello123", "helo")   // Returns 5 (hel + lo)
strspn("123abc", "0123456789")  // Returns 3

strcspn() - Complementary Span

size_t strcspn(const char *str, const char *reject);

Returns length of initial segment NOT containing any characters from reject.

strcspn("hello123", "0123456789")  // Returns 5
strcspn("hello\nworld", "\n")      // Returns 5

Common use: Find newline position:

char input[100];
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0';  // Remove newline

String Tokenization - strtok()

Syntax

char *strtok(char *str, const char *delim);

Description

Splits a string into tokens based on delimiters.

Basic Usage

char str[] = "Hello,World,How,Are,You";
char *token = strtok(str, ",");

while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, ",");  // NULL for subsequent calls
}

Output:

Hello
World
How
Are
You

Important Characteristics

  1. Modifies original string - Replaces delimiters with '\0'
  2. Uses static variable - Not thread-safe
  3. First call: Pass the string
  4. Subsequent calls: Pass NULL

Visual Representation

Before: "Hello,World,Test"
         H e l l o , W o r l d , T e s t \0

After strtok:
         H e l l o \0 W o r l d \0 T e s t \0
         ^           ^             ^
         token 1     token 2       token 3

Thread-Safe Alternative: strtok_r()

char *strtok_r(char *str, const char *delim, char **saveptr);

char str[] = "a,b,c";
char *saveptr;
char *token = strtok_r(str, ",", &saveptr);
while (token) {
    printf("%s\n", token);
    token = strtok_r(NULL, ",", &saveptr);
}

Memory Functions

These work with raw memory, not just strings.

memset() - Fill Memory

void *memset(void *ptr, int value, size_t num);

Fills memory with a byte value.

char str[20];
memset(str, 'A', 10);  // Fill first 10 bytes with 'A'
str[10] = '\0';
printf("%s\n", str);   // "AAAAAAAAAA"

int arr[5];
memset(arr, 0, sizeof(arr));  // Zero out array

memcpy() - Copy Memory

void *memcpy(void *dest, const void *src, size_t num);

Copies num bytes from source to destination. Does NOT handle overlapping regions.

char src[] = "Hello";
char dest[10];
memcpy(dest, src, 6);  // Include null terminator

memmove() - Safe Memory Copy

void *memmove(void *dest, const void *src, size_t num);

Like memcpy, but handles overlapping memory regions correctly.

char str[] = "Hello World";
memmove(str + 6, str, 5);  // Overlapping regions OK
// str = "Hello Hello"

memcmp() - Compare Memory

int memcmp(const void *ptr1, const void *ptr2, size_t num);

Compares num bytes of memory.

char a[] = "Hello";
char b[] = "Hello";
if (memcmp(a, b, 5) == 0) {
    printf("Equal\n");
}

memchr() - Search Memory for Byte

void *memchr(const void *ptr, int value, size_t num);

Finds first occurrence of byte in memory block.

char str[] = "Hello";
char *ptr = memchr(str, 'l', 5);
if (ptr) {
    printf("Found at position: %ld\n", ptr - str);  // 2
}

Other Useful Functions

sprintf() - Print to String

int sprintf(char *str, const char *format, ...);

Writes formatted output to a string.

char buffer[100];
int num = 42;
sprintf(buffer, "The answer is %d", num);
// buffer = "The answer is 42"

Warning: No bounds checking!

snprintf() - Safe Print to String

int snprintf(char *str, size_t size, const char *format, ...);

Like sprintf but with size limit.

char buffer[20];
snprintf(buffer, sizeof(buffer), "A very long message that exceeds buffer");
// Truncated to fit, always null-terminated

sscanf() - Read from String

int sscanf(const char *str, const char *format, ...);

Parses a string according to format.

char str[] = "42 3.14 Hello";
int i;
float f;
char word[20];
sscanf(str, "%d %f %s", &i, &f, word);
// i = 42, f = 3.14, word = "Hello"

Safe Alternatives

Why Use Safe Functions?

Standard functions like strcpy, strcat, sprintf have no bounds checking and can cause:

  • Buffer overflows
  • Security vulnerabilities
  • Undefined behavior

Recommended Safe Alternatives

UnsafeSafe Alternative
strcpystrncpy + null terminate OR strlcpy (BSD)
strcatstrncat OR strlcat (BSD)
sprintfsnprintf
getsfgets

strlcpy and strlcat (BSD/macOS)

size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char *dst, const char *src, size_t size);

Always null-terminates and returns total length needed.

char buffer[10];
size_t len = strlcpy(buffer, "Hello World", sizeof(buffer));
// buffer = "Hello Wor\0" (truncated)
// len = 11 (full length of source)
if (len >= sizeof(buffer)) {
    printf("Truncation occurred!\n");
}

Note: Not available on all systems (not in glibc).

Example: Safe String Building

char result[100] = "";

// Safe concatenation pattern
void safe_concat(char *dest, size_t dest_size, const char *src) {
    size_t current_len = strlen(dest);
    size_t remaining = dest_size - current_len - 1;

    if (remaining > 0) {
        strncat(dest, src, remaining);
    }
}

safe_concat(result, sizeof(result), "Hello");
safe_concat(result, sizeof(result), " ");
safe_concat(result, sizeof(result), "World");

Best Practices

1. Always Check Buffer Sizes

// BAD
char buffer[10];
strcpy(buffer, user_input);  // Buffer overflow risk!

// GOOD
char buffer[10];
strncpy(buffer, user_input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';

2. Use snprintf for Formatting

// BAD
char msg[50];
sprintf(msg, "Name: %s, Age: %d", name, age);

// GOOD
char msg[50];
snprintf(msg, sizeof(msg), "Name: %s, Age: %d", name, age);

3. Check Return Values

char *result = strstr(haystack, needle);
if (result == NULL) {
    // Handle not found case
}

4. Null Terminate After strncpy

char dest[20];
strncpy(dest, source, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';  // ALWAYS do this!

5. Don't Modify String Literals

char *str = "Hello";  // Points to read-only memory
// str[0] = 'J';      // UNDEFINED BEHAVIOR!

char str[] = "Hello";  // Array copy on stack
str[0] = 'J';          // OK

6. Use const for Read-Only Parameters

// Function doesn't modify the string
size_t count_chars(const char *str, char c) {
    // ...
}

Summary

Quick Reference

FunctionPurposeSafe?
strlenLengthYes
strcpyCopyNo
strncpyCopy n charsPartial
strcatConcatenateNo
strncatConcat n charsPartial
strcmpCompareYes
strncmpCompare n charsYes
strchrFind charYes
strrchrFind char (reverse)Yes
strstrFind substringYes
strtokTokenizeModifies input
sprintfFormat to stringNo
snprintfSafe formatYes

Function Categories

  1. Length: strlen
  2. Copy: strcpy, strncpy, memcpy, memmove
  3. Concatenate: strcat, strncat
  4. Compare: strcmp, strncmp, memcmp
  5. Search: strchr, strrchr, strstr, strpbrk
  6. Tokenize: strtok, strtok_r
  7. Memory: memset, memchr
  8. Format: sprintf, snprintf, sscanf

Memory Rule

Size needed for string = strlen(string) + 1  // +1 for null terminator

Common Patterns

// Remove newline from fgets
input[strcspn(input, "\n")] = '\0';

// Safe string copy
strncpy(dest, src, size - 1);
dest[size - 1] = '\0';

// Find position in string
size_t pos = ptr - str;  // Where ptr = strchr(str, c)
README - C Programming Tutorial | DeepML