0

Beginner at C here.

I understand that strstr() can be used for finding if strings contain a certain substring and that printf() can display colored output (as explained here: stdlib and colored output in C).

What I am trying to figure out is a simple way to color only the matching portion of the string (like in grep), since strstr() returns the entire part of the line from the match. Alternatively I could print the entire matching line but that would end up with the entire line being colored.

Assuming that bold = coloring for illustrative purposes, my desired result when searching for the substring elephant is:

this is an elephant's tusk

printf + coloring the strstr() output gives:

elephant's tusk

and of course printf + coloring the entire matched line gives:

this is an elephant's tusk

Thank you in advance for the help.

Community
  • 1
  • 1
Reuben L.
  • 2,806
  • 2
  • 29
  • 45

2 Answers2

1

The easiest solution is to break the printing process into three pieces. If strstr returns a non-NULL result, print the number of characters from the start of the initial string until reaching the strstr result. Then color the strstr result until the length of the "needle" is matched. Then print the uncolored remainder of the haystack:

const char *color_start, *color_end;

print_head = haystack;
color_start = strstr (haystack, needle);
color_end = color_start + strlen (needle) - 1;

while (*print_head) {
    if (print_head == color_start) { /* init color change */ }
    else if (print_head == color_end) { /* revert color change */ }
    putchar (*print_head++);
}

A more efficient version would be:

const char *color_start, *color_end;

print_head = haystack;
color_start = strstr (haystack, needle);
color_end = color_start + strlen (needle) - 1;

while (print_head < color_start)
    putchar (*print_head++);
/* init color change */
while (print_head <= color_end)
    putchar (*print_head++);
/* revert color change */
while (*print_head)
    putchar (*print_head++);

It is more efficient because it tests only one condition through each loop, rather than up to three conditions per loop.

Michael Tiemann
  • 251
  • 2
  • 9
1

It's because strstr returns a pointer to the first occurence on needle in haystack, from the manual

NAME

   strstr, strcasestr - locate a substring

SYNOPSIS

   #include <string.h>

   char *strstr(const char *haystack, const char *needle);

   #define _GNU_SOURCE         /* See feature_test_macros(7) */

   #include <string.h>

   char *strcasestr(const char *haystack, const char *needle);

DESCRIPTION 

   The strstr() function finds the first occurrence of the substring
   needle in the string haystack.  The terminating null bytes ('\0') are
   not compared.

   The strcasestr() function is like strstr(), but ignores the case of
   both arguments.

RETURN VALUE

   These functions return a pointer to the beginning of the located
   substring, or NULL if the substring is not found.

so that is the correct output, if you want that result, you must use strtok.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97