Checking whether one string contains another is one of the most common string operations in C. The standard library provides strstr() in <string.h> — it returns a pointer to the first occurrence of the substring in the main string, or NULL if not found. The position of the match is calculated by subtracting the start pointer from the returned pointer.
The original post used conio.h, gets(), and void main(). It also implemented substring search manually using nested character comparison loops — correct in principle but unnecessary since strstr() does exactly this. This rewrite uses fgets() for safe input and strstr() for clean, proven searching.
C Program: Check if a Substring is Present in a String
/* Check if a substring is present in a string
* Uses strstr() from <string.h>
* Compile: gcc -ansi -Wall -Wextra substring.c -o substring */
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[256], sub[64];
char *pos;
printf("Enter main string: ");
if (fgets(str, sizeof(str), stdin) == NULL) return 1;
str[strcspn(str, "\n")] = '\0'; /* strip trailing newline */
printf("Enter substring to search: ");
if (fgets(sub, sizeof(sub), stdin) == NULL) return 1;
sub[strcspn(sub, "\n")] = '\0';
pos = strstr(str, sub);
if (pos != NULL) {
printf("Found \"%s\" in \"%s\" at position %d\n",
sub, str, (int)(pos - str));
} else {
printf("\"%s\" not found in \"%s\"\n", sub, str);
}
return 0;
}
How to Compile and Run
gcc -ansi -Wall -Wextra substring.c -o substring
./substring
Sample Output
Enter main string: Hello, World! Enter substring to search: World Found "World" in "Hello, World!" at position 7 Enter main string: Hello, World! Enter substring to search: Goodbye "Goodbye" not found in "Hello, World!" Enter main string: abcdefgh Enter substring to search: abc Found "abc" in "abcdefgh" at position 0 Enter main string: abcdefgh Enter substring to search: fgh Found "fgh" in "abcdefgh" at position 5
How strstr() Works
strstr(haystack, needle) searches for the first occurrence of needle in haystack. It returns a pointer to the start of the match, or NULL if the needle is not found.
| Call | Returns | Position |
|---|---|---|
strstr("Hello, World!", "World") |
pointer to ‘W’ | 7 |
strstr("Hello, World!", "Goodbye") |
NULL | not found |
strstr("abcabc", "abc") |
pointer to first ‘a’ | 0 (first occurrence) |
strstr("abc", "") |
pointer to ‘a’ | 0 (empty needle always matches) |
Code Explanation
pos = strstr(str, sub)— returns achar *pointer intostrat the start of the first match. If the substring appears multiple times, strstr only returns the first. To find all occurrences, call strstr again starting frompos + 1in a loop.(int)(pos - str)for position — since bothposandstrare pointers into the same array, subtracting them gives the byte offset (0-based index) of the match. The cast tointis needed because pointer subtraction returnsptrdiff_tand%dexpectsint.fgets()+strcspn()for input —fgets(str, sizeof(str), stdin)reads safely with a length limit.str[strcspn(str, "\n")] = '\0'removes the trailing newline that fgets includes.gets()in the original has no length limit and was removed from C11 due to buffer overflow risk.- Case sensitivity —
strstr()is case-sensitive: “world” and “World” are different strings. For case-insensitive search, convert both strings to lowercase withtolower()in a loop before calling strstr, or use the POSIX functionstrcasestr()on Linux.
Finding All Occurrences
/* Find all occurrences of sub in str */
char *p = str;
int count = 0;
while ((p = strstr(p, sub)) != NULL) {
printf("Found at position %d\n", (int)(p - str));
p++; /* advance past current match to find next */
count++;
}
printf("Total: %d occurrence(s)\n", count);
What This Program Teaches
- Pointer return values from string functions — strstr, strchr, and strrchr all return pointers into the original string. The pointer arithmetic
pos - strrecovers the 0-based index. This pattern appears throughout C string programming. - Always check for NULL before using a returned pointer — if strstr returns NULL and you attempt to dereference it (
*posorpos[0]), the program crashes with a segmentation fault. Always checkif (pos != NULL)first. - fgets is the correct replacement for gets — never use gets().
fgets(buf, sizeof(buf), stdin)prevents buffer overflow by limiting input to sizeof(buf)-1 characters. The extra step of stripping the newline is a small price for safety. - strstr is O(n×m) in the worst case — n = length of haystack, m = length of needle. For extremely large strings or performance-critical code, algorithms like Knuth-Morris-Pratt or Boyer-Moore search in O(n+m). For typical string sizes in C programs, strstr is fast enough.
Related Programs
- Compare Strings in C
- String Functions in C — Complete Guide
- ctype.h Character Classification in C
- atof, atoi, fgets in C
- Pointers in C — Complete Guide
Recommended book:
The C Programming Language — Kernighan & Ritchie (India) |
(US)
|
C Programming: A Modern Approach — K.N. King (India) |
(US)
Practice what you learned: C Aptitude Questions — or try our C Programming Quiz App on Android.