简体   繁体   中英

Best way to search for a string in a list of strings in C

I have a list of device IDs in a file and I have a list of device IDs to verify against the first list. What would be the best way to go about it? This is how I'm trying to go about it:

char *token, *str, *tofree;
char line[13];
tofree = str = strdup(device_list_str);
while ((token = strsep(&str, ","))) {
    printf("\nLOOKING FOR: %s\n", token);
    while (fgets(line, sizeof line, fd) != NULL) {
        if (strcasecmp(line, token) == 0) {
            printf("FOUND THE DEVICE!!");
            break;
        }
    }
    printf("DID NOT FIND THE DEVICE!!"");
}
free(tofree);

Here, device_list_str is the list of devices to be searched separated by commas. Looks something like this: b4e62d95c5cd,b4e62ddc3ffd .

The problem for me is how do I specify exactly with this logic that the device has not been found, because the way it is now, it always prints DID NOT FIND THE DEVICE even after FOUND THE DEVICE .

EDIT 1 : I want to use a function, but when exactly should it return false ?

bool find_device(FILE *fd, char *token) {
    char line[13]; /* or some other suitable maximum line size */
    while (fgets(line, sizeof line, fd) != NULL) {
        if (strcasecmp(line, token) == 0)
            break;
    }
    return true;
}

Use a bool flag:

bool found = false;
while ((token = strsep(&str, ","))) {
  printf("\nLOOKING FOR: %s\n", token);
  while (fgets(line, sizeof line, fd)!=NULL) {
    ....
    found = true;
    break;
  }
  if (found) { ...

But a better way is to use a function:

//...
while ((token = strsep(&str, ","))) {
    printf("\nLOOKING FOR: %s\n", token);
    if (find_device(fd, token)) {
      printf("FOUND THE DEVICE!!");
    } else {
       printf("DID NOT FIND THE DEVICE!!"");
    }
} 

bool find_device(FILE *fd, char *token) {
    char line [13]; /* or some other suitable maximum line size */
    while (fgets(line, sizeof line, fd) != NULL) {
        if (strcasecmp(line, token) == 0)
            return true;
    }
    return false;
}

To read the file once, you can rearrange the original code:

char line[13];
while (fgets(line, sizeof line, fd) != NULL) {
  char *token, *str, *tofree;
  tofree = str = strdup(device_list_str);
  while ((token = strsep(&str, ","))) {
    printf("\nLOOKING FOR: %s\n", token);
        if (strcasecmp(line, token) == 0) {
            printf("FOUND THE DEVICE!!");
            break;
        }
    printf("DID NOT FIND THE DEVICE!!"");
  }
  free(tofree);
}

but in this case you should change the function too:

bool find_device(char* line, char* device_list_str) {
   // ..., leaving this as an exercise
   return false;
 }

There are multiple solutions to your problem:

  • you can use a boolean indicator:

     char *token, *str, *tofree; char line[80]; tofree = str = strdup(device_list_str); while ((token = strsep(&str, ",")) != NULL) { bool found = false; printf("\\nLOOKING FOR: %s\\n", token); while (fgets(line, sizeof line, fd) != NULL) { if (strcasecmp(line, token) == 0) { printf("FOUND THE DEVICE!!\\n"); found = true; break; } } if (!found) { printf("DID NOT FIND THE DEVICE!!\\n""); } } free(tofree);
  • you can use a utility function:

     bool find_device(FILE *fd, const char *token) { char line[80]; while (fgets(line, sizeof line, fd) != NULL) { if (strcasecmp(line, token) == 0) return true; } return false; }

Use it this way:

    while ((token = strsep(&str, ","))) {
        printf("\nLOOKING FOR: %s\n", token);
        if (find_device(fd, token)) {
            printf("FOUND THE DEVICE!!\n");
        } else {
            printf("DID NOT FIND THE DEVICE!!"");
        }
    }

Note however that you should rewind the stream to allow for multiple tests and you should strip the trailing newline before comparing the strings:

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

bool find_device(FILE *fd, const char *token) {
    char line[80];
    rewind(fd);
    while (fgets(line, sizeof line, fd) != NULL) {
        line[strcspn(line, "\n")] = '\0'; // strip the newline if present
        if (strcasecmp(line, token) == 0)
            return true;
    }
    return false;
}

You might actually want to strip all initial and trailing white space.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM