Question

I have a string which has been sent using udp. Now I want to read the string, tokenize it and save it to an char array. Only the first letter of each word is saved. So I just get 5 'e's from element01 to element05. I'm working in Arduino, and I know some c# but no c or c++.

//p_params->packetBuffer contains the following string:
//element01#element02#element03#element04#element05

void packtStriper( receivedPacket * p_params )
{
  char delims[] = "#";
  char *result = NULL;
  int i = 0;

  //Tokenize string - 'split' it on hash mark
  result = strtok( p_params->packetBuffer, delims );

  //Iterate through the tokens and save them to my list
  while( result != NULL )
  {
    p_params->listData[i] = *result;
    i++;

    result = strtok( NULL, delims );
  }

  //Display the data just received
  for(int j =0; j<i; j++)
  {
    Serial.print( "Data " );
    Serial.print( j );
    Serial.print( ": " );

    Serial.println( p_params->listData[j] );
  } 
}

typedef struct receivedPacket
{
  char            * REQType;
  char            * confName;
  unsigned  int   confData[64];
  char            listData[10];
  char            packetBuffer[UDP_BUFFER_SIZE];
  int             packetSize;
  int             inProduction;

}receivedPacket;

Since the following code prints the full element names I thought I could use just result. But this also return an error.

char str[] = "element01#element02#element03#element04#element05";
char delims[] = "#";
char *result = NULL;
result = strtok( str, delims );
while( result != NULL ) {
    printf( "result is \"%s\"\n", result );
    result = strtok( NULL, delims );
}
Was it helpful?

Solution

The following line:

p_params->listData[i] = *result

takes the first char of result, and copies it to the ith char of p_params->listData. So only the first char of each token is copied. How do you expect to get those tokens, as one sequence of element01element02element03element04element05, or as an array of strings?

Bear in mind that in C and C++, an array of chars holds only one string, simply put. To hold more than one string, you need an array of array of chars, or some delimiter (which is where you've started...).

Edit:

Given you want to get an array of strings, you can use the following: declare listData as

char* listData[10];

which means listData can now hold up to 10 strings. Then, instead of assigning *result to listData[i], use the following:

p_params->listData[i] = strdup(result);

which will create a copy of the string, and store it in the next entry.

Note:

  1. If you want to display the strings, you'll have to loop again, and print them one by one. You can't just print the whole array of them.
  2. strdup allocates memory for you. You must free() those strings when you're done with them.
  3. Your code uses magic numbers, which is bad. I'm assuming this is only to make it easier to read here ;)
  4. If you get more than 10 elements, you'll get a buffer overflow, because listData can only hold up to 10 strings. You should at least make sure i doesn't get over 9 in the while or so.

OTHER TIPS

result is a pointer to a character (which can be an element in an array of characters), whereas *result is the character it points to. So the line

p_params->listData[i] = *result;

is putting a character into p_params->listData[i].

In C strings are represented by an array of type char and are generally terminated by a null (i.e. the value 0). It sounds like you need an array of strings, which you can create as a two dimensional array. For example:

// 5 strings each with 9 characters and a null terminator
char ArrayOfStrings[5][10];

You can then copy one token into each string using the strcpy() or strncpy() function. I would recommend using strncpy() for safety (so you don't copy more characters than you have space for), and manually set the last element of each string to null.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top