0

This is a function of Linux grep command, (It basically search for a specific word and prints each line that has that word)

How can I modify this function to color the word that I'm looking for in "red color" ? (I want to color the word only, not the whole sentence)

#include<stdio.h>
#include<string.h>
void main()
{
char fn[10],pat[10],temp[200];
FILE *fp;
printf("Enter file name\n");
scanf("%s",fn);
printf("Enter pattern to be searched\n");
scanf("%s",pat);
fp=fopen(fn,"r");
while(!feof(fp))
{
fgets(temp,1000,fp);
if(strstr(temp,pat))
  printf("%s",temp);
}
fclose(fp);
}

I can add colors

#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"

But, how can I design the logic of splitting each line into words and then coloring each word that match my input without using strtok(), I tried to expand

if(strstr(temp,pat))
    printf("%s",temp);

and to add an array newString[] and match it withtemp[] for i and j to check if newString[] is equivalent to pat[] or not but that didn't work

Mohan
  • 135
  • 1
  • 7
  • 1
    Possible duplicate of [Using colors with printf](https://stackoverflow.com/questions/5412761/using-colors-with-printf) – Tormund Giantsbane Apr 05 '18 at 16:58
  • `char temp[200]` and `fgets(temp,1000,fp)`? That's not very good. Use `sizeof temp` as the argument for `fgets`. The `scanf` calls are equally bad in a similar buffer overflowy way. – Some programmer dude Apr 05 '18 at 16:59
  • Also please read [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Some programmer dude Apr 05 '18 at 17:01
  • 2
    `strstr` does not only tell you whether a string is contained in another string; it also tells you where it is. – M Oehm Apr 05 '18 at 17:22

2 Answers2

1
#include <stdio.h>

#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define KBLU  "\x1B[34m"
#define KWHT  "\x1B[37m"

int main()
{
    printf("%s%s\n", KRED, "mystr");
    printf("%s%s\n", KGRN, "mystr");
    printf("%snormal\n", KNRM);
    return 0;
}

This should work. Now you can try modifying the printfs in your example with above idea. This is how you can do now: (Just pointer manipulations)

int main () {
    char hay[] = "haystack";
    char *needle = "ay";

    char *ptr = strstr(hay, needle);
    if (ptr)
    {
        int i = 0;
        int len = strlen(needle);
        char x = ptr[0];
        ptr[0] = 0;
        fprintf(stdout, "%s%s", KGRN, hay);
        ptr[0] = x;
        x = ptr[len];
        ptr[len]=0;
        fprintf(stdout, "%s%s", KRED, ptr);
        ptr[len]=x;
        ptr += len;
        fprintf(stdout, "%s%s\n", KGRN, ptr);

    }
    return 0;
}
Ritesh
  • 1,809
  • 1
  • 14
  • 16
0

There are two things that can help you here:

  • The function strstr(s, f) returns a pointer to the first occurrence of the string f in s or NULL if it doesn't occur in s. Because s is a C string – a null-terminated array of chars – you can use pointer arithmetic on the results to get the exact position:

    const char *s = "abcde";
    const char *p = strstr(s, "c");     // p == &s[2] == s + 2
    int pos = p - s;                    // pos == 2
    

    Make sure that you calculate the position only if the result from strstr isn't NULL.

  • You can print only parts of a string in printf by specifying a precision between the % and the s after a dot; refer to the printf format string documentation for more information. That precision can be an asterisk, in which case it is read from the list of arguments:

    const char *s = "Hello world!";
    
    printf("%s.50s\n", s);              // printf "Hello, world!"
    printf("%s.4s\n", s);               // prints "Hell"
    printf("%s.*s\n", 5, s);            // prints "Hello"
    

    Because of how printf works, the argument (the 5 in the last line) must be an int, not just any integer type. Take care.

We can use these two features to write a function that prints a string s and wraps all occurrences of a certain word find in the strings open and close:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void put(const char *s, const char *find,
         const char *open, const char *close)
{
    int flen = strlen(find);
    const char *m = strstr(s, find);

    while (m) {
        int l = m - s;

        printf("%.*s", l, s);
        printf("%s%s%s", open, find, close);

        s = m + flen;
        m = strstr(s, find);
    }

    puts(s);
}

int main()
{
    put("Yo-ho-ho! A short life, far from home, ahoy!", "ho", "<", ">");

    return 0;
}

This prints:

Yo-<ho>-<ho>! A s<ho>rt life, far from <ho>me, a<ho>y!

I've used angle brackets here, but the delimiting strings can, of course, also be escape sequences for changing the colours in the terminal.

M Oehm
  • 28,726
  • 3
  • 31
  • 42