TarjisoMartin
TarjisoMartin

Reputation: 57

How to find a word within a string without case sensitivity?

Is there a way to find a word within a string in a case insensitive manner?

I would like to find "Word" or "WOrd" or "word" etc... in a C program.

I saw some solutions before posting this question but they don't work anymore or force me to touch the original string to make it all upper cases which is not what I want. Any suggestion to make it?

Upvotes: 4

Views: 1095

Answers (5)

chqrlie
chqrlie

Reputation: 144949

If you want to find a word within a string in a case independent manner, there is a library function strcasestr() on GNU systems. Here is a simple implementation:

#include <ctype.h>
#include <string.h>

char *strcasestr(const char *haystack, const char *needle) {
    size_t i;
    for (;;) {
        for (i = 0;; i++) {
            if (needle[i] == '\0')
                return (char *)haystack;
            if (tolower((unsigned char)haystack[i]) != tolower((unsigned char)needle[i]))
                break;
        }
        if (*haystack++ == '\0')
            return NULL;
    }
}

Upvotes: 1

RKou
RKou

Reputation: 5221

It is possible to make it more general using regular expressions with the regex() service. Here is an example program with a function named find_pattern() accepting two parameters: the string into which the search is to be done and a pattern to look for.

#include <stdio.h>
#include <sys/types.h>
#include <regex.h>
#include <libgen.h>


const char *find_pattern(const char *string, const char *pattern)
{
int         rc;
regex_t     reg;
const char *found = (const char *)0;
regmatch_t  match;

  rc = regcomp(&reg, pattern, REG_EXTENDED|REG_NEWLINE);
  if (rc != 0) {
    fprintf(stderr, "Invalid regex '%s', error %d\n", pattern, rc);
    return (const char *)0;
  }

  rc = regexec(&reg, string, 1, &match, 0);
  if (0 == rc) {
    found = string + match.rm_so; 
  }

  regfree(&reg);

  return found;

} // find_pattern


int main(int ac, char *av[])
{
  const char *str;  

  if (ac != 3) {
    fprintf(stderr, "Usage: %s string regex\n", basename(av[0]));
    return 1;
  }

  str = find_pattern(av[1], av[2]);

  if (str) {
    printf("%s\n", str);
    return 0;
  }

  return 1;
} // main

Some tries:

$ gcc search.c -o search
$ ./search "azerty wOrD qwErty" '[wW][Oo][rR][dD]'
wOrD qwErty
$ ./search "azerty word qwErty" '[wW][Oo][rR][dD]'
word qwErty
$ ./search "azerty word qwErty" '[wW][Oo][R][D]'
$ echo $?
1
$ ./search "azerty woRD qwErty" '[wW][Oo][R][D]'
woRD qwErty

Upvotes: -1

chux
chux

Reputation: 154245

Is there a way to compare a string witihn a word with case insensitive?

To compare strings without case sensitivity, fold the values using tolower() or toupper().

#include <ctype.h>

int compare(const char *s1, const char *s2) {
  const unsigned char *u1 = (const unsigned char *) s1; // Use unsigned char for use with `to....()`
  const unsigned char *u2 = (const unsigned char *) s2;

  while (*u1 && toupper(*u1) == toupper(*u2)) {
    u1++;
    u2++;
  }
  int ch1 = toupper(*u1);
  int ch2 = toupper(*u2);
  return (ch1 > ch2) - (ch1 < ch2);
}

To cope with letters outside the common ASCII range which may have a non-one-to-one upper/lower mapping, convert twice:

while (*u1 && tolower(toupper(*u1)) == tolower(toupper(*u2))) {
  

Using tolower() or toupper() or the above in either order makes no difference when looking for equality, but can make an order difference. e.g. Is _ before or after A-Z?

Upvotes: 1

anotherOne
anotherOne

Reputation: 1573

That's one way to do it

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

#define SIZE 100

int matchWord( char *s );

int main() {

    char s[SIZE];
    int i, len, match = 0;

    fgets(s, SIZE, stdin);

    len = strlen(s);

    for(i = 0; i < len - 3; i++) {
    
        if( matchWord(s+i) ) {
        
            match = 1;
            break;
        }
    }

    match ? printf("Match found in position %d\n", i) : puts("Not found");

    return 0;
}

int matchWord( char *s )
{
    static char w[8] = "wordWORD";
    int response = 1;

    for(int i = 0; i < 4; i++) {
    
        if( s[i] != w[i] && s[i] != w[i+4] ) {
        
            response = 0;
            break;
        }
    }

    return response;
}

Upvotes: 0

crackaf
crackaf

Reputation: 552

You can make your own function to compare these types of strings. I've implemented it and you can modify it for yourself.

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

// returns true if X and Y are same
int compare(const char *X, const char *Y)
{
    while (*X && *Y)
    {
        if (abs(*X-*Y)!=32 && *X != *Y) //here 32 is neglecting the case
            return 0;

        X++;
        Y++;
    }

    return (*Y == '\0');
}

// Function to implement mystrstr() function
const char *mystrstr(const char *X, const char *Y)
{
    while (*X != '\0')
    {
        if ((*X == *Y) && compare(X, Y))
            return X;
        X++;
    }

    return NULL;
}

// Implement mystrstr function in C
int main()
{
    char *X = "GHOST HUNT - Coding made easy";
    char *Y = "CodiNg";

    printf("%s\n", mystrstr(X, Y));

    return 0;
}

//OUTPUT
Coding made easy

Upvotes: 0

Related Questions