Find the Position of a Substring in C

Finding the position of a substring means locating the index where one string first appears inside another — for example, “world” starts at index 6 in “hello world”. This is one of the most common string operations in C, used for parsing text, validating input, and implementing search features. The standard library already provides strstr() for this, but implementing it yourself is a classic exercise for understanding how string matching actually works under the hood.

This page covers a manual implementation using nested loops, a complete C program, sample runs, and how it compares to the built-in strstr() function.

How It Works — Step by Step

  1. Walk through the main string one character at a time, treating each position as a possible starting point for a match.
  2. At each starting position, compare characters one by one against the substring.
  3. If all characters match, that starting index is the answer.
  4. If any character differs, abandon this starting position and try the next one.
  5. If no starting position produces a full match, the substring isn’t present — return -1.

Step-by-step trace

Searching for "world" in "hello world":

Index 0: 'h' vs 'w' -> mismatch, try next index
Index 1: 'e' vs 'w' -> mismatch
...
Index 6: 'w','o','r','l','d' all match "world" -> found at index 6

C Program to Find the Position of a Substring

/* Find the Position of a Substring in C
 * Compile: gcc -ansi -Wall -Wextra findsub.c -o findsub */
#include <stdio.h>
#include <string.h>

int find_substring(const char *str, const char *sub)
{
    int i, j, str_len, sub_len;
    str_len = (int)strlen(str);
    sub_len = (int)strlen(sub);

    if (sub_len == 0)
        return 0;

    for (i = 0; i <= str_len - sub_len; i++) {
        for (j = 0; j < sub_len; j++) {
            if (str[i + j] != sub[j])
                break;
        }
        if (j == sub_len)
            return i;
    }
    return -1;
}

int main(void)
{
    char str[200], sub[100];
    int pos;

    printf("Enter the main string: ");
    fgets(str, sizeof(str), stdin);
    str[strcspn(str, "\n")] = '\0';

    printf("Enter the substring to find: ");
    fgets(sub, sizeof(sub), stdin);
    sub[strcspn(sub, "\n")] = '\0';

    pos = find_substring(str, sub);

    if (pos == -1)
        printf("\"%s\" not found in \"%s\"\n", sub, str);
    else
        printf("\"%s\" found at index %d in \"%s\"\n", sub, pos, str);

    return 0;
}

How to Compile and Run

gcc -ansi -Wall -Wextra findsub.c -o findsub
./findsub

Sample Input and Output — Test 1 (found)

Enter the main string: hello world
Enter the substring to find: world
"world" found at index 6 in "hello world"

Sample Input and Output — Test 2 (not found)

Enter the main string: programming in c
Enter the substring to find: xyz
"xyz" not found in "programming in c"

Code Explanation

  • Loop bound i <= str_len - sub_len — there’s no point checking a starting index where the substring couldn’t possibly fit before the string ends. This also naturally handles the case where the substring is longer than the string (the loop simply never runs).
  • Inner loop with early break — as soon as one character mismatches, there’s no need to keep comparing; abandoning early is what keeps this fast in practice even though its worst case is O(n·m).
  • fgets + strcspn instead of gets/scanf(“%s”)fgets is bounds-safe and reads strings with spaces; strcspn(str, "\n") finds and strips the trailing newline that fgets keeps.
  • Empty substring edge case — an empty substring is considered to match at index 0, matching the behavior of the standard strstr().

Time and Space Complexity

Case Time Space
Worst case (many partial matches) O(n × m) O(1) extra
Typical case (few partial matches) Close to O(n) O(1) extra

n = length of the main string, m = length of the substring. For guaranteed O(n + m) worst-case performance, algorithms like KMP (Knuth-Morris-Pratt) avoid re-checking characters already known to match — but for typical strings, this simple approach is more than fast enough.

What This Program Teaches

  • Nested loop pattern-matching — the foundation every string-search algorithm builds on.
  • Reading strings safely — using fgets() with a bounded buffer instead of unsafe input functions.
  • Reimplementing a standard library function<string.h> already provides strstr(str, sub), which does exactly this and should be preferred in real code; writing it yourself is what builds the understanding.

Related Programs

Recommended Books

Practice C string handling with the C Programming Quiz App — 500+ MCQs covering strings, pointers, sorting, and more.
Download on Google Play →

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>