获取由逗号分隔的字符数组的函数

时间:2015-07-04 13:34:28

标签: c arduino

我有一个来自串口(Arduino)的char数组。 数据用逗号分隔,如下所示:

header:data

保存此结构的chars数组预先定义如下:char content[50];

我正在尝试编写一个函数,它将获得一个参数content 并仅返回header,然后返回另一个函数以仅返回data。我知道我必须从这开始 - 但不知道如何继续:

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

我根据这里的答案尝试过,但我没有得到任何打印:

  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); 

2 个答案:

答案 0 :(得分:3)

让我们看看strtok()的{​​{3}}。它说

  

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

     

strtok()函数将字符串解析为一系列标记..... delim参数指定一组字节,用于分隔已解析字符串中的标记。 ......每次调用strtok()都会返回一个指向包含下一个标记的以空字符结尾的字符串的指针。

这意味着,当你打电话

 valPosition = strtok(localString, delimiters); /

strtok()会在localString中搜索delimiters中指定的分隔符 如果它找到任何,它将返回令牌作为以null结尾的字符串。

小心strtok()

  

修改他们的第一个参数。

  

不能用于常量字符串。

所以,localString应该是可修改的,即不能是字符串文字。

接下来,根据您的格式,strtok()将返回header,而不是:

所以,您需要将返回的字符串复制到另一个字符串并返回该字符串。您可以按照以下算法

使用动态内存分配
  1. 定义char * header = NULL;
  2. 检查strtok()的返回值,如果不是NULL,则将内存分配给header,如header = malloc(strlen(valPosition) + 1);
  3. 使用strcpy(header, valPosition);
  4. 复制数据
  5. 从函数返回header
  6. 我希望,你明白你需要更改函数原型也会返回一个指针,比如

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

    此外,一旦您使用了返回的值,您需要free()它。

答案 1 :(得分:1)

如果header:data是唯一的用例,您可以查找strchr()

示例:

#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;
}

并像这样使用它:

#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 .*/
}

请注意,成功headerdata(仍然)会引用content的记忆,以及成功后记的内容。

为了好玩,上面的代码可以缩小为:

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;
}