C Programming Strings Reference
Essential Topic

C Strings - Complete Guide

Master C strings with detailed syntax, built-in functions, practical examples, and programming best practices for effective string manipulation.

String Functions

Complete reference

Practical Examples

Real-world usage

Common Pitfalls

Avoid mistakes

Introduction to C Strings

In C programming, strings are arrays of characters terminated by a null character ('\0'). Strings are fundamental for text processing, user input, file handling, and data manipulation.

Key Characteristics
  • Null-terminated: Always ends with '\0'
  • Character Arrays: Strings are char arrays
  • Immutable Literals: String literals are read-only
  • Header File: Functions in <string.h>
  • Memory Management: Manual allocation needed
String Types in C
  • String Literals: "Hello" (read-only)
  • Character Arrays: char str[10] (mutable)
  • Pointers to Strings: char *str (dynamic)
  • Array of Strings: 2D char array
  • Formatted Strings: sprintf() output

Important String Concepts

Strings in C are null-terminated character arrays. The null character ('\0') marks the end. String length doesn't include null terminator. Always allocate size + 1 for the null character.

String Declaration and Initialization

Strings can be declared and initialized in several ways. Understanding these methods is crucial for proper string manipulation.

Common Syntax Patterns:
char str1[20]; // Declaration with size char str2[] = "Hello World"; // Auto-size initialization char *str3 = "Hello World"; // Pointer to string literal char str4[] = {'H','e','l','l','o','\0'}; // Character array

Examples:

String Declaration Methods
#include <stdio.h>
#include <string.h>

int main() {
    char arr[] = "Hello";      /* modifiable array */
    char *ptr = "World";       /* pointer to literal (read-only) */
    char buf[20];
    strcpy(buf, arr);
    printf("%s %s\n", buf, ptr);
    printf("Length of arr: %zu\n", strlen(arr));
    return 0;
}
Output:
Hello World
Length of arr: 5

Memory Visualization:

String: "Hello" (6 bytes including '\0')
H
e
l
l
o
\0
[0]
[1]
[2]
[3]
[4]
[5]

String length: 5 characters | Memory: 6 bytes (including null terminator)

Important Note: char *str = "Hello"; creates a string literal in read-only memory.
char str[] = "Hello"; creates a modifiable character array on stack.
Never modify string literals as it causes undefined behavior.

String Input/Output Functions

C provides several functions for reading and writing strings. Understanding their differences is crucial for safe programming.

String I/O Functions Comparison
#include <stdio.h>

int main() {
    char name[20];
    char line[50];

    printf("Enter name (no spaces): ");
    scanf("%19s", name);
    printf("Hello, %s!\n", name);

    while (getchar() != '\n');  /* clear buffer */

    printf("Enter a line: ");
    fgets(line, sizeof(line), stdin);
    puts(line);

    return 0;
}
Function Usage Pros Cons When to Use
scanf("%s") Reads until whitespace Simple, formatted input No space support, buffer overflow risk Single words, known format
fgets() Reads with size limit Safe, reads spaces, includes newline Includes newline, needs cleanup Always for user input
gets() Reads until newline Simple syntax Extremely dangerous, deprecated Never use!
printf() Formatted output Flexible formatting No automatic newline General output
puts() Simple output Automatic newline, simple No formatting Simple messages

String Built-in Functions Reference

The <string.h> header provides numerous functions for string manipulation. Here is an expanded reference of common functions from <string.h> and related headers:

Function Syntax Description Return Value Category
strlen()
size_t strlen(const char *str)
Returns length of string (excluding '\0') Length as size_t Length
strcpy()
char *strcpy(char *dest, const char *src)
Copies source string to destination Pointer to destination Copy
strcat()
char *strcat(char *dest, const char *src)
Appends source string to destination Pointer to destination Concatenation
strcmp()
int strcmp(const char *str1, const char *str2)
Compares two strings lexicographically <0, 0, or >0 Comparison
strchr()
char *strchr(const char *str, int c)
Finds first occurrence of character Pointer to char or NULL Search
strtok()
char *strtok(char *str, const char *delim)
Breaks string into tokens Pointer to token or NULL Tokenization
memcpy()
void *memcpy(void *dest, const void *src, size_t n)
Copies n bytes from source to destination Pointer to destination Memory
atoi()
int atoi(const char *str)
Converts string to integer Converted integer Conversion
strncpy()
char *strncpy(char *dest, const char *src, size_t n)
Copy at most n characters; may not add \0 if src longer than n Pointer to dest Copy
strncat()
char *strncat(char *dest, const char *src, size_t n)
Append at most n characters from src Pointer to dest Concatenation
strncmp()
int strncmp(const char *s1, const char *s2, size_t n)
Compare at most n characters <0, 0, or >0 Comparison
strstr()
char *strstr(const char *haystack, const char *needle)
Find first occurrence of substring Pointer or NULL Search
strrchr()
char *strrchr(const char *str, int c)
Find last occurrence of character Pointer or NULL Search
strspn()
size_t strspn(const char *str, const char *accept)
Length of initial segment matching accept chars Count Search
strcspn()
size_t strcspn(const char *str, const char *reject)
Length before first char in reject set Count Search
strpbrk()
char *strpbrk(const char *str, const char *accept)
Find first char in str that appears in accept Pointer or NULL Search
strnlen()
size_t strnlen(const char *str, size_t max)
Length up to max chars (C11) Length Length
memset()
void *memset(void *s, int c, size_t n)
Set n bytes to value c (often 0 to clear) Pointer to s Memory
memmove()
void *memmove(void *dest, const void *src, size_t n)
Copy n bytes; safe if regions overlap Pointer to dest Memory
memcmp()
int memcmp(const void *s1, const void *s2, size_t n)
Compare first n bytes <0, 0, or >0 Memory
memchr()
void *memchr(const void *s, int c, size_t n)
Search n bytes for byte c Pointer or NULL Memory
atol()
long atol(const char *str)
Convert string to long (stdlib.h) long value Conversion
atof()
double atof(const char *str)
Convert string to double (stdlib.h) double value Conversion
Important Notes:
  • Always include #include <string.h> for string functions
  • Functions with 'n' (like strncpy, strncat) are safer as they limit operations
  • Check return values for NULL when using search functions
  • Ensure destination buffers are large enough for operations
  • Use memmove() instead of memcpy() when memory regions overlap

Implementing Built-in Functions in C

Understanding how standard string functions work helps you debug, interview, and write safer code. Below are simple educational versions of common <string.h> routines. They are not replacements for the library — use the real functions in production.

my_strlen — like strlen()

Count characters until '\0'.

my_strlen.c
#include <stdio.h>

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

int main() {
    printf("Length = %zu\n", my_strlen("Hello"));
    return 0;
}

my_strcpy — like strcpy()

Copy source into destination including the null terminator.

my_strcpy.c
#include <stdio.h>

char *my_strcpy(char *dest, const char *src) {
    char *start = dest;
    while ((*dest++ = *src++) != '\0')
        ;
    return start;
}

int main() {
    char buf[20];
    my_strcpy(buf, "C strings");
    printf("%s\n", buf);
    return 0;
}

my_strcmp — like strcmp()

Compare unsigned char values; return negative, zero, or positive.

my_strcmp.c
#include <stdio.h>

int my_strcmp(const char *a, const char *b) {
    while (*a && (*a == *b)) {
        a++;
        b++;
    }
    return (unsigned char)*a - (unsigned char)*b;
}

int main() {
    printf("cat vs dog: %d\n", my_strcmp("cat", "dog"));
    printf("abc vs abc: %d\n", my_strcmp("abc", "abc"));
    return 0;
}

my_strcat — like strcat()

Find end of dest, then append src.

my_strcat.c
#include <stdio.h>

char *my_strcat(char *dest, const char *src) {
    char *start = dest;
    while (*dest)
        dest++;
    while ((*dest++ = *src++) != '\0')
        ;
    return start;
}

int main() {
    char buf[30] = "Hello";
    my_strcat(buf, " World");
    printf("%s\n", buf);
    return 0;
}

my_strchr — like strchr()

Return pointer to first match or NULL.

my_strchr.c
#include <stdio.h>

char *my_strchr(const char *s, int c) {
    while (*s) {
        if (*s == (char)c)
            return (char *)s;
        s++;
    }
    return (c == '\0') ? (char *)s : NULL;
}

int main() {
    char text[] = "programming";
    char *p = my_strchr(text, 'g');
    if (p)
        printf("First 'g' at: %s\n", p);
    return 0;
}

Demo: library vs our versions

compare_builtin_vs_custom.c
#include <stdio.h>
#include <string.h>

size_t my_strlen(const char *s) {
    size_t n = 0;
    while (s[n]) n++;
    return n;
}

int my_strcmp(const char *a, const char *b) {
    while (*a && *a == *b) { a++; b++; }
    return (unsigned char)*a - (unsigned char)*b;
}

int main() {
    const char *word = "LearnHub";
    printf("strlen:  lib=%zu  mine=%zu\n", strlen(word), my_strlen(word));
    printf("strcmp:  lib=%d  mine=%d\n",
           strcmp(word, "LearnHub"), my_strcmp(word, "LearnHub"));
    return 0;
}

Learning tip

Real <string.h> functions are highly optimized and handle edge cases. Practice writing your own once, then always prefer strncpy, strncat, and bounded buffers in real projects.

Practical String Examples

Example 1: strlen, strcpy, strcat, strcmp
#include <stdio.h>
#include <string.h>

int main() {
    char s[30] = "Hello";
    char t[30];

    printf("strlen = %zu\n", strlen(s));

    strcpy(t, s);
    strcat(t, " C");
    printf("after strcat: %s\n", t);

    printf("strcmp with \"Hello C\" = %d\n", strcmp(t, "Hello C"));
    return 0;
}
Example 2: Compare two strings
#include <stdio.h>
#include <string.h>

int main() {
    char a[20], b[20];

    printf("Enter two words: ");
    scanf("%19s %19s", a, b);

    if (strcmp(a, b) == 0)
        printf("Strings are equal\n");
    else
        printf("Strings are different\n");

    return 0;
}

Common Mistakes and Best Practices

Common Mistake 1: Buffer Overflow
char str[10]; strcpy(str, "This string is too long!"); // BUFFER OVERFLOW!
Solution: Use strncpy() or ensure destination size is sufficient
Common Mistake 2: Modifying String Literals
char *str = "Hello"; str[0] = 'J'; // CRASH! String literals are read-only
Solution: Use character arrays: char str[] = "Hello";
Common Mistake 3: Forgetting Null Terminator
char str[5] = {'H', 'e', 'l', 'l', 'o'}; // Missing '\0' printf("%s", str); // UNDEFINED BEHAVIOR!
Solution: Always include null terminator
String Best Practices:
  1. Always use fgets() instead of gets() for input
  2. Check buffer sizes before string operations
  3. Use 'n' versions of functions (strncpy, strncat) for safety
  4. Always null-terminate strings manually if building them
  5. Validate input strings before processing
  6. Use sizeof() for array sizes, not hardcoded numbers
  7. Handle whitespace properly (trim if needed)
  8. Be careful with string literals vs character arrays
  9. Always check return values of string functions
  10. Use const for strings that shouldn't be modified

Key Takeaways

  • Strings in C are null-terminated character arrays ('\0' marks end)
  • Include <string.h> for string manipulation functions
  • Use fgets() for safe input (never use gets())
  • Always ensure sufficient buffer size for string operations
  • String literals are read-only; use arrays for modifiable strings
  • strlen() returns length excluding null terminator
  • strcpy()/strcat() vs strncpy()/strncat() - use 'n' versions for safety
  • strcmp() returns 0 for equal strings, not 1
  • Always null-terminate strings when building them manually
  • Use const keyword for strings that shouldn't be modified
  • Check for NULL returns from search functions (strchr, strstr)
  • Be mindful of buffer overflows - biggest security risk with strings
Next Topics: We'll explore types of functions,, creating a user defined function, passing arrays as parameters etc.