Help searching TAG on SD

Hi, I have an SD card with csv file in it.
My CSV file contains this line format

790016098BED,MYREAL NAME,09208884522,0

tag,name,contact,status

Which first column is the TAG I want to search for.

Here is my code so far.

void searchTag()
{
  char tag[] = "790016098BAD"; //Sample tag to search.
  //CSV line content parsing  
  char name;
  int contact;
  int stat;
  //SD Part, reading line by line trapping '\n' indicator
  char line[50];
  char c;
  char* readLine;
  int index = 0;
  
  myFile = SD.open("tags.csv");

  if(myFile)
  {
    while(myFile.available())
    {
      c = myFile.read(); //Get byte from sd card
      if (c != '\n')
      {
        line[index] = c;
        index++;
      }
      else
      {
        readLine = strtok(line, ",");
        while(readLine != NULL)
        {
          Serial.println(readLine);
          readLine = strtok(NULL, ",");
        }
        delay (1000);
        index = 0;
      }
    }
    myFile.close();
  }
};

My codes working properly but I have remaining task to be workout.

  • Search a supplied TAG on my SD card csv file.
  • Get the name and contact number if tag found. So I can send an sms.

Any help is appreciated.
Thanks.

  char tag[] = "790016098BAD"; //Sample tag to search.

You want to search IN this tag? Or, FOR this tag? Differences matter.

        readLine = strtok(line, ",");

That pointer points to a token, not a line.

        delay (1000);

I sincerely hope that there are not 100,000 records in your file. This delay is pointless/useless/stupid/bullshit (take your pick).

Since you are parsing the string you read, one of the tokens should equal the tag you want to search for. You just need to compare the tag to the token (strcmp()), and stop parsing the record and reading the file when the tag matches the token. One of those can be done with break;. The other requires that you set and test a boolean flag.

You want to search IN this tag? Or, FOR this tag? Differences matter.

I want to search that tag on my csv file, and get the corresponding name and contact associated for such tag.

I just use that delay on my test codes, but don't worry, there is not more than 20 lines on my sd card. :slight_smile:

I tried to add strcmp().

while(readLine != NULL)
        {
          if(strncmp(readLine, tag, sizeof(tag))==0)
          {        
            Serial.println(readLine);
            break;
          }
        }
        index = 0;

But after comparing and return true, how can I distribute the remaining line which is name and contact before he break?. Is there any thing I can use aside from using strtok()?

Thanks.

how can I distribute the remaining line which is name and contact before he break?. Is there any thing I can use aside from using strtok()?

You want to copy the other two tokens. Why would you use anything BUT strtok() to get the tokens?

Thanks Paul

Here is my codes so far for now. It work correctly, but I don't know if it is the most efficient way.

void searchTag(char *tag)
{
  //SD Part, reading line by line trapping '\n' indicator
  char line[50];
  char c;
  int index = 0;

  char *line_buff = line;
  char *str;
  char *parsedLine[4] = {
  };
  int i = 0;

  myFile = SD.open("students.csv");

  if(myFile)
  {
    while(myFile.available())
    {
      c = myFile.read(); //Get byte from sd card
      if (c != '\n')
      {
        line[index] = c;
        index++;
      }
      else
      {
        //Serial.println(line);
        while ((str = strtok_r(line_buff, ",", &line_buff)) != NULL)
        {
          parsedLine[i] = str;
          i++;
        }
        if(strncmp(parsedLine[0], tag, sizeof(tag)) == 0)
        {
          Serial.println(parsedLine[0]);
          Serial.println(parsedLine[1]);
          Serial.println(parsedLine[2]);
          Serial.println(parsedLine[3]);
          break;
        }
        index = 0;
      }
    }
    myFile.close();
  }
};

but I don't know if it is the most efficient way.

It is not. No one suggested using strtok_r(). That is the thread-safe version of the strtok() function. It is MUCH bigger, and of no use on a single-threaded system. Not to mention that it is more confusing to use.

        if(strncmp(parsedLine[0], tag, sizeof(tag)) == 0)

The sizeof() "function" is not the correct function to use. strlen() is.

};

Functions end at the curly brace. The ; is not needed.

When the function ends, the parsedLine array goes out of scope, so calling the function seems pointless.

The function does not return anything to indicate whether or not it found the tag, and it certainly doesn't return the related data.

Can you suggest some way to do, so I can try to revise my codes according yours?

Thanks.

Can you suggest some way to do

To do what?

This function will look for the tag, save the rest of the data in the contact and status arguments, and return whether the tag was found.

bool searchTag(char *tagToFind, char *contact, char *status)
{
  bool tagFound = false;

  //SD Part, reading line by line trapping '\n' indicator
  char line[50];
  int index = 0;

  myFile = SD.open("students.csv");
  if(myFile)
  {
    while(myFile.available())
    {
      char c = myFile.read(); //Get byte from sd card
      if (c != '\n')
      {
        line[index] = c;
        index++;
        line[index] = '\0'; // Keep array NULL terminated (i.e. a string)
      }
      else
      {
        //Serial.println(line);
        char *token = strtok(line, ",");
        if(token)
        {
          if(strncmp(tagToFind, token, strlen(tagToFind)) == 0)
          {
             token = strtok(NULL, ",");
             if(token)
                strcpy(contact, token);
              
             token = strtok(NULL, ",");
             if(token)
                strcpy(status, token);

             tagFound = true;
             break;
          }
        }
      }
    }
  }

  return tagFound;
}

Call it like so:

char tag[] = "12345678";
char contact[20];
char status[20];

contact[0] = '\0';
status[0] = '\0';

if(searchTag(tag, contact, status)
{
   // The tag was found. contact and status contain valid data
}