Home > Software design >  filter strings using * (expand operator) in c
filter strings using * (expand operator) in c

Time:02-17

I have an array of different strings in C, like for example:

char *words[8] = {"hi", "cheesecake", "yellow", "happy", "cupcake", "red", "car", "chocolate cake"};

I want to filter them using a function like char *cakes[3] = filterWords(&words, "*cake*"); where the * represents anything at all. Is there a library for Linux that I could include to do that? If not, what would be the fastest way to implement this? (I have some idea of how to implement this, but it would probably be super inefficient).

CodePudding user response:

You can use string.h header with few tricks to do so. For an example have a look at below snippet. (This solution is cross-platform)

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

// General Time Complexity: O(n), where `n` is the length of string array, (note, time complexities of `strstr`, `strlen` and `strncpy` aren't counted)
char **filter(const char **data, size_t len_data, const char *key, size_t *len_out)
{
    if (!data || !key)
        return NULL;
    char **val = (char **)calloc(len_data, sizeof(char *));
    *len_out = 0;
    for (size_t i = 0, j = 0; i < len_data; i  )
    {
        if (strstr(data[i], key) != NULL)
        {
            size_t len_sub = strlen(data[i]);
            val[j] = (char *)calloc(len_sub   1, sizeof(char));
            strncpy(val[j], data[i], len_sub);
            j  ;
            *len_out  = 1; 
        }
    }
    return val;
}

int main(void)
{
    char *words[8] = {"hi", "cheesecake", "yellow", "happy", "cupcake", "red", "car", "chocolate cake"};
    size_t len_data = 0;
    char **data = filter((const char **)words, 8, "cake", &len_data);
    for (size_t i = 0; i < len_data; i  )
    {
        printf("%s\n", data[i]);
        free(data[i]);
    }
    free(data);
    return 0;
}

CodePudding user response:

I would use the fnmatch function for that. It is POSIX function so it is available under Linux and relatively easy to use: https://man7.org/linux/man-pages/man3/fnmatch.3.html Just beware that it handles other globbing patterns, like ?, so if your pattern is coming from the outside then you might need to handle those characters specially.

Here's an example, you might need some more work with it to have the exact function you need:

#include <fnmatch.h>
#include <stdio.h>

int main() {
  char *words[8] = {"hi", "cheesecake", "yellow", "happy", "cupcake", "red", "car", "chocolate cake"};
  const char *pattern = "*cake*";
  int i;

  for(i = 0; i < sizeof(words)/sizeof(words[0]); i  ) {
    if (fnmatch(pattern, words[i], 0) == 0) {
      printf("Match: %s\n", words[i]);
    }
  }

  return 0;
}
  • Related