Search code examples
cstring-comparisonstrtokstrcmpstrstr

How to compare strings in C without hard coding the increments?


I have a buffer that holds a string from a CSV file that I opened and read. I split the string up by using strtok() and split on the " , ". So now my string looks like this:

char buff[BUFFER_SIZE] = "1000" "CAP_SETPCAP" "CAP_NET_RAW"

I want to make comparisons now for each section of the string, but for the life of me I cannot get it to work. I want to be able to do it without hard coding anything meaning I don't want to assume how many spaces I need to move over. For example to start at CAP_SETPCAP I don't want to have to put buff+5. Anybody know a better way to handle this?

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

#define BUFFER_SIZE 1024

int main(int argc, char *argv[]) {

       FILE *fp = fopen("csvtest.csv", "r");
       char buff[BUFFER_SIZE];


       fgets(buff, 1024, fp);
       char *csvData = strtok(buff, ",");
       while(csvData != NULL){
             csvData = strtok(NULL, ",");
       }

      int i;
      while(buff[i] != '\0'){
         strcmp(buff, "CAP_NET_RAW")
         printf("Match found");
         i++;
      }

      //or I wanted to do string comparison, but I kept getting
      //segmentation fault (core dumped)

      char *found;
      found = strstr(buff, "CAP_NET_RAW");
      printf("%s\n", found);

      fclose(fp);

      return 0;
}

Solution

  • Your code has three different sections. Lets analyze them:


    1. The strtok section

    You get the data from the file and then you iterate on strtok:

    fgets(buff, 1024, fp);
    char *csvData = strtok(buff, ",");
    while(csvData != NULL){
        csvData = strtok(NULL, ",");
    }
    

    You seem not interested in what you found in the different positions: in fact csvData is always overwritten with the last token. And at last it is equal to NULL.

    The only thing you get is having the commas in the original array buff overwritten with '\0'. Printing buff you will only see "1000", because after this substring there is the string terminator placed by strtok.


    2. Searching "CAP_NET_RAW"

    You now iterate on buff[i] until the string terminator. But the string terminator is after the first substring "1000"!

    int i;
    while(buff[i] != '\0'){
        strcmp(buff, "CAP_NET_RAW")
        printf("Match found");
        i++;
    }
    

    Furthermore you search for CAP_NET_RAW, but even without the inner-terminators-issue, the comparison would never succeed. That's because (1) the string actually present in buff is "CAP_NET_RAW" (with double quotes); (2) that token is the last of the row, an it sitll will have the trailing '\n' (fgets doesn't remove it).

    By the way: I copied the code after your edit, and now there's no check on strcmp() return value. I suppose it is a typo. Note: strcmp returns 0 if the string match.


    3. The strstr attempt

    Finally you look for the string using the strstr function. That's a clever idea. But as already said before, buff doesn't contain it. Well, the buffer actually do contain it, but string utilities will stop at the first '\0' they found.

      char *found;
      found = strstr(buff, "CAP_NET_RAW");
      printf("%s\n", found);
    

    So found will be NULL, and dereferencing a NULL pointer (that's what %s tells printf to do) will lead to a segmentation fault.


    4. Conclusions

    As a very simple way to find the only string you care of, I suggest to use only strstr, without using strtok before. Alternatively you can still use strtok, but saving tokens in different strings so that you can access them later.