C strstr Function

The strstr() function finds the first occurrence of a substring within a larger string. It returns a pointer to the beginning of the found substring, or NULL if the substring is not found.


Basic Syntax

#include <string.h>
char *strstr(const char *haystack, const char *needle);
ParameterDescription
haystackThe main string to search in
needleThe substring to search for
Return valuePointer to first occurrence, or NULL if not found

Example 1: Basic Substring Search

#include <stdio.h>
#include <string.h>
int main() {
char text[] = "The quick brown fox jumps over the lazy dog";
char word[] = "fox";
char *result = strstr(text, word);
if(result != NULL) {
printf("Found '%s' at position: %ld\n", word, result - text);
printf("Remaining string: %s\n", result);
} else {
printf("Substring not found\n");
}
return 0;
}

Output:

Found 'fox' at position: 16
Remaining string: fox jumps over the lazy dog

Example 2: Substring Not Found

#include <stdio.h>
#include <string.h>
int main() {
char sentence[] = "Hello World";
char search[] = "xyz";
char *result = strstr(sentence, search);
if(result == NULL) {
printf("'%s' not found in '%s'\n", search, sentence);
}
return 0;
}

Output:

'xyz' not found in 'Hello World'

Example 3: Finding All Occurrences

#include <stdio.h>
#include <string.h>
int main() {
char text[] = "the cat in the hat sat on the mat";
char search[] = "the";
char *ptr = text;
int count = 0;
while((ptr = strstr(ptr, search)) != NULL) {
printf("Found '%s' at position: %ld\n", search, ptr - text);
ptr++;  // Move past this occurrence
count++;
}
printf("Total occurrences: %d\n", count);
return 0;
}

Output:

Found 'the' at position: 0
Found 'the' at position: 11
Found 'the' at position: 23
Total occurrences: 3

Example 4: Extracting Text Before/After Substring

#include <stdio.h>
#include <string.h>
int main() {
char data[] = "username=john123&password=secret";
char delimiter[] = "=";
char *equal_sign = strstr(data, delimiter);
if(equal_sign != NULL) {
// Extract key (before =)
int key_len = equal_sign - data;
char key[50];
strncpy(key, data, key_len);
key[key_len] = '\0';
// Extract value (after =)
char *value = equal_sign + 1;
char val[50];
strcpy(val, value);
printf("Key: %s\n", key);
printf("Value: %s\n", val);
}
return 0;
}

Output:

Key: username
Value: john123&password=secret

Example 5: Finding File Extension

#include <stdio.h>
#include <string.h>
int main() {
char filename[] = "document.pdf";
char *dot = strstr(filename, ".");
if(dot != NULL) {
printf("Filename: %.*s\n", (int)(dot - filename), filename);
printf("Extension: %s\n", dot + 1);
}
// Another example with multiple dots
char file2[] = "backup.tar.gz";
char *last_dot = strrchr(file2, '.');  // strrchr finds last occurrence
if(last_dot != NULL) {
printf("\nFile: %s\n", file2);
printf("Extension: %s\n", last_dot + 1);
}
return 0;
}

Output:

Filename: document
Extension: pdf
File: backup.tar.gz
Extension: gz

Example 6: Case-Sensitive vs Case-Insensitive

#include <stdio.h>
#include <string.h>
#include <ctype.h>
// Custom case-insensitive version
char *stristr(const char *haystack, const char *needle) {
if(!*needle) return (char*)haystack;
for(; *haystack; haystack++) {
if(tolower(*haystack) == tolower(*needle)) {
const char *h = haystack;
const char *n = needle;
while(*h && *n && tolower(*h) == tolower(*n)) {
h++;
n++;
}
if(!*n) return (char*)haystack;
}
}
return NULL;
}
int main() {
char text[] = "Hello WORLD, world is beautiful";
// strstr is case-sensitive
char *result1 = strstr(text, "world");
printf("strstr('world'): %s\n", result1 ? "Found" : "Not found");
char *result2 = strstr(text, "WORLD");
printf("strstr('WORLD'): %s\n", result2 ? result2 : "Not found");
// Case-insensitive version
char *result3 = stristr(text, "world");
printf("stristr('world'): %s\n", result3);
return 0;
}

Output:

strstr('world'): Found
strstr('WORLD'): WORLD, world is beautiful
stristr('world'): Hello WORLD, world is beautiful

Example 7: Replacing Substring

#include <stdio.h>
#include <string.h>
void replaceFirst(char *text, const char *find, const char *replace) {
char *pos = strstr(text, find);
if(pos != NULL) {
char temp[200];
int prefix_len = pos - text;
int find_len = strlen(find);
// Build new string
strncpy(temp, text, prefix_len);
temp[prefix_len] = '\0';
strcat(temp, replace);
strcat(temp, pos + find_len);
// Copy back
strcpy(text, temp);
}
}
int main() {
char message[200] = "I like apples and apples are tasty";
printf("Original: %s\n", message);
replaceFirst(message, "apples", "oranges");
printf("After replace: %s\n", message);
return 0;
}

Output:

Original: I like apples and apples are tasty
After replace: I like oranges and apples are tasty

Example 8: Validating String Format

#include <stdio.h>
#include <string.h>
int isValidEmail(const char *email) {
// Check for @ symbol
char *at = strstr(email, "@");
if(at == NULL) return 0;
// Check for dot after @
char *dot = strstr(at, ".");
if(dot == NULL) return 0;
// Check minimal length
if(at - email < 1) return 0;
if(strlen(dot + 1) < 2) return 0;
return 1;
}
int main() {
char emails[][50] = {
"[email protected]",
"invalid.email",
"test@domain",
"[email protected]"
};
for(int i = 0; i < 4; i++) {
printf("%s: %s\n", emails[i], 
isValidEmail(emails[i]) ? "Valid" : "Invalid");
}
return 0;
}

Output:

[email protected]: Valid
invalid.email: Invalid
test@domain: Invalid
[email protected]: Valid

Common Mistakes

#include <stdio.h>
#include <string.h>
int main() {
char text[] = "Hello World";
// ❌ WRONG - Checking wrong way
if(strstr(text, "World") > 0) {  // Comparing pointer to int
printf("This comparison is wrong\n");
}
// ✅ CORRECT - Check against NULL
if(strstr(text, "World") != NULL) {
printf("Found correctly\n");
}
// ❌ WRONG - Empty needle (returns haystack always)
char *result = strstr(text, "");
printf("Empty needle returns: %s\n", result);  // Returns whole string
// ❌ WRONG - Modifying string literal with result
char *literal = "Constant string";
char *found = strstr(literal, "stant");
// found[0] = 'X';  // CRASH - String literal is read-only
// ✅ CORRECT - Use modifiable array
char modifiable[] = "Constant string";
char *found2 = strstr(modifiable, "stant");
if(found2) found2[0] = 'X';  // Works fine
printf("Modified: %s\n", modifiable);
return 0;
}

Output:

Found correctly
Empty needle returns: Hello World
Modified: ConXtant string

strstr vs Other Search Functions

FunctionDescriptionReturn Value
strstr(haystack, needle)Find first substringPointer or NULL
strchr(str, char)Find first characterPointer or NULL
strrchr(str, char)Find last characterPointer or NULL
strpbrk(str, chars)Find any character from setPointer or NULL
strspn(str, chars)Length of initial segmentLength (size_t)
strcspn(str, chars)Length before any matchLength (size_t)

Performance Considerations

#include <stdio.h>
#include <string.h>
#include <time.h>
// Simple naive search (similar to strstr)
char *naive_search(const char *haystack, const char *needle) {
size_t hlen = strlen(haystack);
size_t nlen = strlen(needle);
if(nlen == 0) return (char*)haystack;
for(size_t i = 0; i <= hlen - nlen; i++) {
if(memcmp(haystack + i, needle, nlen) == 0) {
return (char*)(haystack + i);
}
}
return NULL;
}
int main() {
char text[1000] = "This is a test string for searching patterns";
char pattern[] = "searching";
// strstr is highly optimized (often uses advanced algorithms)
clock_t start = clock();
for(int i = 0; i < 1000000; i++) {
strstr(text, pattern);
}
clock_t end = clock();
printf("strstr time: %f seconds\n", (double)(end - start) / CLOCKS_PER_SEC);
return 0;
}

Practical Example: Simple HTML Parser

#include <stdio.h>
#include <string.h>
void extractLinks(const char *html) {
const char *ptr = html;
char *link_start, *link_end;
while((link_start = strstr(ptr, "href=\"")) != NULL) {
link_start += 6;  // Skip 'href="'
link_end = strstr(link_start, "\"");
if(link_end != NULL) {
int len = link_end - link_start;
printf("Found link: %.*s\n", len, link_start);
ptr = link_end;
} else {
break;
}
}
}
int main() {
char html[] = 
"<a href=\"https://example.com\">Example</a> "
"<a href=\"/page.html\">Page</a> "
"<img src=\"image.jpg\">";
extractLinks(html);
return 0;
}

Output:

Found link: https://example.com
Found link: /page.html

Quick Reference

OperationCodeResult
Find substringstrstr(text, "word")Pointer or NULL
Get positionpos = strstr(text, "word") - textIndex or -1 if not found
Check existsif(strstr(text, "word"))True if found
Find after positionstrstr(ptr + 1, "word")Search after current
Extract beforestrncpy(buf, text, pos - text)Text before match
Extract afterstrcpy(buf, pos + len)Text after match

Best Practices

  1. Always check if result is NULL before using the pointer
  2. Don't modify string literals returned by strstr
  3. Use pointer arithmetic to get position indices
  4. Remember it's case-sensitive - convert both strings to same case if needed
  5. Empty needle returns haystack - handle this case if problematic
  6. For single characters, use strchr (more efficient than strstr)

Complete Guide to Core & Advanced C Programming Concepts (Functions, Strings, Arrays, Loops, I/O, Control Flow)

https://macronepal.com/bash/building-blocks-of-c-a-complete-guide-to-functions/
Explains how functions in C work as reusable blocks of code, including declaration, definition, parameters, return values, and modular programming structure.

https://macronepal.com/bash/the-heart-of-text-processing-a-complete-guide-to-strings-in-c-2/
Explains how strings are handled in C using character arrays, string manipulation techniques, and common library functions for text processing.

https://macronepal.com/bash/the-cornerstone-of-data-organization-a-complete-guide-to-arrays-in-c/
Explains arrays in C as structured memory storage for multiple values, including indexing, initialization, and efficient data organization.

https://macronepal.com/bash/guaranteed-execution-a-complete-guide-to-the-do-while-loop-in-c/
Explains the do-while loop in C, where the loop body executes at least once before checking the condition.

https://macronepal.com/bash/mastering-iteration-a-complete-guide-to-the-for-loop-in-c/
Explains the for loop in C, including initialization, condition checking, and increment/decrement for controlled iteration.

https://macronepal.com/bash/mastering-iteration-a-complete-guide-to-while-loops-in-c/
Explains the while loop in C, focusing on condition-based repetition and proper loop control mechanisms.

https://macronepal.com/bash/beyond-if-else-a-complete-guide-to-switch-case-in-c/
Explains switch-case statements in C, enabling multi-branch decision-making based on variable values.

https://macronepal.com/bash/mastering-conditional-logic-a-complete-guide-to-if-else-statements-in-c/
Explains if-else statements in C for decision-making and controlling program flow based on conditions.

https://macronepal.com/bash/mastering-the-fundamentals-a-complete-guide-to-arithmetic-operations-in-c/
Explains arithmetic operations in C such as addition, subtraction, multiplication, division, and operator precedence.

https://macronepal.com/bash/foundation-of-c-programming-a-complete-guide-to-basic-input-output/
Explains basic input and output in C using scanf and printf for interacting with users and displaying results.

Online C Code Compiler
https://macronepal.com/free-online-c-code-compiler-2/

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper