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() {
    // Method 1: Character array with size
    char str1[20];  // Can hold up to 19 characters + null
    
    // Method 2: Character array with initialization
    char str2[] = "Hello World";  // Size automatically calculated (12)
    
    // Method 3: Character pointer to string literal
    char *str3 = "Hello World";  // Read-only memory
    
    // Method 4: Using strcpy() after declaration
    char str4[20];
    strcpy(str4, "Hello World");
    
    // Display all strings
    printf("str1: %s (uninitialized)\n", str1);
    printf("str2: %s (size: %lu)\n", str2, strlen(str2));
    printf("str3: %s\n", str3);
    printf("str4: %s\n", str4);
    
    // Visualize str2 memory layout
    printf("\nMemory layout of str2 \"Hello World\":\n");
    for(int i = 0; i <= strlen(str2); i++) {
        if(str2[i] == '\0')
            printf("Index %d: '\\0' (null terminator)\n", i);
        else
            printf("Index %d: '%c'\n", i, str2[i]);
    }
    
    return 0;
}
Output:
str1: �▯▯� (uninitialized - garbage values)
str2: Hello World (size: 11)
str3: Hello World
str4: Hello World

Memory layout of str2 "Hello World":
Index 0: 'H'
Index 1: 'e'
Index 2: 'l'
Index 3: 'l'
Index 4: 'o'
Index 5: ' '
Index 6: 'W'
Index 7: 'o'
Index 8: 'r'
Index 9: 'l'
Index 10: 'd'
Index 11: '\0' (null terminator)

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>
#include <string.h>

int main() {
    char name[50];
    char sentence[100];
    
    // 1. printf() - Output string
    printf("=== STRING OUTPUT ===\n");
    printf("Hello, World!\n");
    
    // 2. puts() - Output string with newline
    puts("This is puts() function");
    
    // 3. scanf() - Input string (stops at whitespace)
    printf("\nEnter your first name (no spaces): ");
    scanf("%s", name);
    printf("Hello, %s!\n", name);
    
    // Clear input buffer
    while(getchar() != '\n');
    
    // 4. fgets() - Safe string input (with spaces)
    printf("\nEnter a sentence (with spaces): ");
    fgets(sentence, sizeof(sentence), stdin);
    
    // Remove newline from fgets
    sentence[strcspn(sentence, "\n")] = '\0';
    
    printf("You entered: %s\n", sentence);
    
    // 5. sprintf() - Format string into buffer
    char buffer[100];
    int age = 25;
    sprintf(buffer, "Name: %s, Age: %d", name, age);
    printf("\nFormatted string: %s\n", buffer);
    
    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's a comprehensive reference:

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
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

Practical String Examples

Example 1: Common String Operations
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main() {
    char str1[50] = "Hello";
    char str2[50] = "World";
    char result[100];
    
    printf("=== BASIC STRING OPERATIONS ===\n\n");
    
    // 1. String length
    printf("1. strlen():\n");
    printf("   Length of '%s': %lu\n", str1, strlen(str1));
    
    // 2. String copy
    printf("\n2. strcpy():\n");
    strcpy(result, str1);
    printf("   After strcpy, result: %s\n", result);
    
    // 3. String concatenation
    printf("\n3. strcat():\n");
    strcat(result, " ");
    strcat(result, str2);
    printf("   After strcat, result: %s\n", result);
    
    // 4. String comparison
    printf("\n4. strcmp():\n");
    int cmp = strcmp(str1, str2);
    if(cmp < 0)
        printf("   '%s' comes before '%s'\n", str1, str2);
    else if(cmp > 0)
        printf("   '%s' comes after '%s'\n", str1, str2);
    else
        printf("   Strings are equal\n");
    
    // 5. String search
    printf("\n5. strchr() and strstr():\n");
    char *pos = strchr(result, 'W');
    if(pos)
        printf("   Found 'W' at position: %ld\n", pos - result);
    
    char *sub = strstr(result, "World");
    if(sub)
        printf("   Found 'World' at position: %ld\n", sub - result);
    
    // 6. String tokenization
    printf("\n6. strtok() - Tokenization:\n");
    char text[] = "apple,banana,cherry,date";
    char *token = strtok(text, ",");
    
    printf("   Tokens: ");
    while(token != NULL) {
        printf("%s ", token);
        token = strtok(NULL, ",");
    }
    printf("\n");
    
    return 0;
}
Example 2: Password Validator
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int validatePassword(char *password) {
    int hasUpper = 0, hasLower = 0, hasDigit = 0, hasSpecial = 0;
    int length = strlen(password);
    
    // Check length
    if(length < 8) {
        printf("Password must be at least 8 characters long.\n");
        return 0;
    }
    
    // Check each character
    for(int i = 0; i < length; i++) {
        if(isupper(password[i])) hasUpper = 1;
        else if(islower(password[i])) hasLower = 1;
        else if(isdigit(password[i])) hasDigit = 1;
        else if(!isalnum(password[i])) hasSpecial = 1;
    }
    
    // Display validation results
    printf("\n=== PASSWORD VALIDATION REPORT ===\n");
    printf("Length: %d characters %s\n", length, 
           length >= 8 ? "[✓]" : "[✗]");
    printf("Uppercase letter: %s\n", hasUpper ? "[✓]" : "[✗]");
    printf("Lowercase letter: %s\n", hasLower ? "[✓]" : "[✗]");
    printf("Digit: %s\n", hasDigit ? "[✓]" : "[✗]");
    printf("Special character: %s\n", hasSpecial ? "[✓]" : "[✗]");
    
    // Check all conditions
    if(hasUpper && hasLower && hasDigit && hasSpecial) {
        printf("\nPassword is STRONG! ✅\n");
        return 1;
    } else {
        printf("\nPassword is WEAK! ❌\n");
        return 0;
    }
}

int main() {
    char password[100];
    char confirm[100];
    
    printf("=== PASSWORD VALIDATOR ===\n\n");
    
    do {
        printf("Create a new password: ");
        fgets(password, sizeof(password), stdin);
        password[strcspn(password, "\n")] = '\0';
        
        if(!validatePassword(password)) {
            printf("\nPlease try again with a stronger password.\n\n");
            continue;
        }
        
        printf("\nConfirm password: ");
        fgets(confirm, sizeof(confirm), stdin);
        confirm[strcspn(confirm, "\n")] = '\0';
        
        if(strcmp(password, confirm) != 0) {
            printf("Passwords do not match! Try again.\n\n");
        } else {
            printf("\nPassword successfully set! ✅\n");
            break;
        }
        
    } while(1);
    
    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.