简体   繁体   中英

Function that gets a chars array separated by commas

I have a char array that i get from serial port (Arduino) . the data is separated by commas so its like this :

header:data

The chars array that holds this structure is pre defined like this : char content[50];

I am trying to write a function , that will get a parameter content and return only the header , and then another function to return only the data . I know i have to start with this - but dont really know how to continue:

void getHeader( char* localString)
{

  char delimiters[] = ":";
  char *valPosition=NULL;
  char newString=NULL ;

  valPosition = strtok(localString, delimiters); //what is this doing ?
  .... //whats now ?

  //also how do you return the header to the argument

I have tried that according to an answer here ,but i get nothing to print:

  char delimiters[] = ":";
  char *valPosition=NULL;
  char newString=NULL ;
  char * header = NULL;
  valPosition = strtok(content, delimiters);
   malloc(strlen(valPosition) + 1);
   strcpy(header, valPosition);
       Serial.println(header); 

Let's have a look at the man page for strtok() . It says

char *strtok(char *str, const char *delim);

The strtok() function parses a string into a sequence of tokens..... The delim argument specifies a set of bytes that delimit the tokens in the parsed string. ...... Each call to strtok() returns a pointer to a null-terminated string containing the next token.

That means, when you call

 valPosition = strtok(localString, delimiters); /

strtok() will search localString for the delimiter specified in delimiters and if it finds any, it will return the token as a null-terminated string.

Beware , strtok()

modify their first argument.

and

cannot be used on constant strings.

so, the localString should be modifiable, ie, cannot be a string literal.

Next, as per your format, strtok() will return the header , without the : .

so, you need to copy the returned string into another and return that. You can use dynamic memory allocation, as per following algorithm

  1. Define a char * header = NULL;
  2. Check the returned value of strtok() , if not NULL, allocate memory to header , like header = malloc(strlen(valPosition) + 1);
  3. copy the data using strcpy(header, valPosition);
  4. return the header from the function.

I hope, you understand that you need to change the function prototype also return a pointer, like

char * getHeader( char* localString){....

Also, once you're done using the returned value, you need to free() it.

If header:data is the only use case you have you want to look for strchr() .

Example:

#include <string.h> /* for strchr() and strlen() */
#include <errno.h> /* for EINVAL */

int get_header_and_data(const char * input, char ** pheader, char ** pdata)
{
  int result = 0;

  if (NULL == input  
      || NULL == pheader || NULL == *pheader 
      || NULL == pdata || NULL == *pdata 
  )
  {
    /* Trivial case of "no" input and/or missing references to store the result. */
    errno = EINVAL;
    result = -1;
  }
  else
  {
    char * pcolon = strchr(input, ':');
    if (NULL == pcolon) 
    {
      /* No delimiter found. */
      errno = EINVAL;
      result = -1;
    }
    else
    {
      /* Delimiter found. */
      if (pcolon == input) 
      {
        /* No header found. */
        errno = EINVAL;
        result = -1;
      }
      else 
      {
        if (1 == strlen(pcolon)) 
        {
          /* No data found. */
          errno = EINVAL;
          result = -1;
        }
        else
        {
          /* Success. */
          *pcolon = '\0';

          ++pcolon;

          (*data) = pcolon;
          (*pheader) = input;
        }
      }
    }
  }

  return result;
}

and use it like this:

#include <stdio.h>  

int get_header_and_data(const char *, char **, char **);

...

char content[50] = "";

 /* Load content here. */

char * header = NULL;
char * data = NULL;
if (-1 == get_header_and_data(content, &header, &data)
{
  perror("get_header_and_data() failed.");
  abort(); /* Or what ever to handle the error. */
}
else
{
  /* Dereference and/or use header and data here .*/
}

Please not that on success header and data (still) refer to the memory of content , as well as that on success the latter is modifed.


Just for fun, the code above can be shrunk down to:

int get_header_and_data(const char * input, char ** pheader, char ** pdata)
{
  int result = 0;

  if (NULL == input  
    || NULL == pheader || NULL == *pheader 
    || NULL == pdata || NULL == *pdata 
  )
  {
    /* Trivial case of "no" input and/or missing references to store the result. */
    errno = EINVAL;
    result = -1;
  }
  else
  {
    char * pcolon = strchr(input, ':');
    if (NULL == pcolon /* No delimiter found. */
      || pcolon == input /* No header found. */
      || 1 == strlen(pcolon) /* No data found. */
    )
    {
      errno = EINVAL;
      result = -1;
    }
    else
    {
      /* Success. */
      *pcolon = '\0';
      ++pcolon;

      (*data) = pcolon;
      (*pheader) = input;
    }
  }

  return result;
}

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