upgrade
upgrade

🧑🏽‍💻Intro to C Programming

String Manipulation Functions

Study smarter with Fiveable

Get study guides, practice questions, and cheatsheets for all your subjects. Join 500,000+ students with a 96% pass rate.

Get Started

Why This Matters

String manipulation is fundamental to nearly every C program you'll write—from parsing user input to processing file data to building command-line tools. These functions from <string.h> represent the core toolkit you're expected to master, and exam questions frequently test not just what each function does, but why you'd choose one over another. You're being tested on your understanding of memory safety, buffer management, and pointer arithmetic—concepts that separate competent C programmers from those who write vulnerable code.

Don't just memorize function signatures. Know which function to use when, understand the security implications of unbounded operations versus bounded alternatives, and recognize how these functions interact with C's null-terminated string model. When you see a question about string handling, ask yourself: What could go wrong here? What's the safer alternative?


Measuring and Examining Strings

Before you can manipulate a string, you need to understand its contents. These functions let you measure length and locate specific characters or patterns—all by traversing the string until they hit the null terminator.

strlen()

  • Returns the length of a string—the count of characters excluding the null terminator \0
  • Time complexity is O(n)O(n) where nn is the string length; the function must traverse the entire string
  • Takes a single pointer argument (const char *str) and is essential for calculating buffer sizes before copying or concatenating

strchr()

  • Searches for the first occurrence of a character in a string, returning a pointer to that position
  • Returns NULL if not found—always check the return value before dereferencing
  • Case-sensitive search—useful for locating delimiters, newlines, or specific markers in parsed text

strstr()

  • Searches for a substring within a larger string, returning a pointer to where the match begins
  • Returns NULL if the substring isn't found—critical for pattern matching and text processing
  • Case-sensitive matching—for case-insensitive searches, you'll need to implement your own or use non-standard functions

Compare: strchr() vs. strstr()—both search and return pointers (or NULL), but strchr() finds a single character while strstr() finds a multi-character pattern. If an exam asks about parsing a file path, strchr() finds the / delimiter; strstr() finds a filename pattern.


Copying Strings

Copying strings requires careful attention to buffer sizes. The destination must always have enough allocated memory to hold the source string plus its null terminator—getting this wrong causes buffer overflows.

strcpy()

  • Copies the entire source string to the destination, including the null terminator
  • No bounds checking—if the destination buffer is too small, you get a buffer overflow (major security vulnerability)
  • Returns a pointer to the destination—allows function chaining but doesn't indicate success or failure

strncpy()

  • Copies up to nn characters from source to destination, providing bounded copying
  • Does NOT guarantee null termination—if source is n\geq n characters, destination won't be null-terminated
  • Pads with null bytes if source is shorter than nn—useful when you need fixed-width fields

Compare: strcpy() vs. strncpy()strcpy() is simpler but dangerous; strncpy() is safer but requires manual null termination. Exam tip: if asked about secure string handling, always mention that strncpy() needs dest[n-1] = '\0' to guarantee termination.


Concatenating Strings

Concatenation appends one string to another. The destination must have enough space for both strings plus the null terminator—a common source of bugs.

strcat()

  • Appends source string to the end of destination, overwriting destination's null terminator
  • No bounds checking—vulnerable to buffer overflow if destination can't hold both strings
  • Returns pointer to destination—the result is automatically null-terminated

strncat()

  • Appends at most nn characters from source to destination, providing bounded concatenation
  • Always null-terminates the result—unlike strncpy(), this function guarantees proper termination
  • Destination needs space for existing content + nn characters + null terminator—calculate carefully

Compare: strcat() vs. strncat()—both concatenate and null-terminate, but strncat() limits how many characters are appended. Key difference from the copy functions: strncat() always adds a null terminator, while strncpy() might not.


Comparing Strings

You cannot compare C strings with == (that compares pointer addresses). These functions perform lexicographic comparison based on ASCII values, character by character.

strcmp()

  • Returns 0 if strings are equal, negative if first string is "less than" second, positive if "greater"
  • Case-sensitive comparison'A' (ASCII 65) differs from 'a' (ASCII 97)
  • Compares until a difference is found or both strings end—essential for sorting algorithms and search operations

strncmp()

  • Compares only the first nn characters of both strings
  • Same return value convention as strcmp()—zero for equal, negative/positive for less/greater
  • Useful for prefix matching—check if a string starts with a specific pattern without comparing the entire string

Compare: strcmp() vs. strncmp()—use strcmp() for full equality checks; use strncmp() when you only care about the beginning of strings (like checking command prefixes). Both are O(n)O(n) but strncmp() can terminate earlier.


Tokenizing Strings

Tokenization breaks a string into smaller pieces based on delimiters—essential for parsing structured text like CSV files or command-line input.

strtok()

  • Splits a string into tokens based on delimiter characters, returning one token per call
  • Modifies the original string—replaces delimiters with null terminators (destructive operation)
  • Uses static internal state—call with string pointer first, then with NULL for subsequent tokens; not thread-safe

Compare: strtok() vs. manual parsing with strchr()strtok() is convenient but destructive and not reentrant. For multi-threaded code or when you need to preserve the original string, consider strtok_r() (POSIX) or manual parsing.


Quick Reference Table

ConceptBest Examples
Measuring lengthstrlen()
Character searchstrchr()
Substring searchstrstr()
Unbounded copystrcpy()
Bounded copystrncpy()
Unbounded concatenationstrcat()
Bounded concatenationstrncat()
Full comparisonstrcmp()
Partial comparisonstrncmp()
Tokenizationstrtok()
Security-conscious operationsstrncpy(), strncat(), strncmp()

Self-Check Questions

  1. Which two functions share the property of not guaranteeing null termination, and why does this matter for security?

  2. You need to check if a filename ends with .txt. Which function would you use, and what would you compare against the return value?

  3. Compare and contrast strcpy() and strncpy(): when would you choose each, and what extra step does strncpy() require?

  4. If you're parsing a comma-separated string like "apple,banana,cherry", which function would you use? What happens to the original string?

  5. A function receives user input and needs to copy it into a fixed-size buffer of 64 bytes. Write the two lines of code that safely copy and guarantee null termination.