I using strtok() to split a string and store in an array like following below
char *table[5];
char buffer[50] = {"1-Study"}; // The value is example, get new value by user
char *number;
char *name;
uint8_t tableNumber;
number = strtok(buffer, "-"); //equals "1"
name = strtok(NULL, "-"); //equals "Study"
tableNumber = atoi(number); //convert char to int
table[tableNumber] = name;
for (c = 0; c < 5; c++)
{
printf("table %d = %s\n", c, table[c]);
}
after get input for 5 times the result should be:
table 0 = Study
table 1 = Sleep
table 2 = Party
table 3 = Hello
table 4 = Exit
But the resualt is:
table 0 = Exit
table 1 = Exit
table 2 = Exit
table 3 = Exit
table 4 = Exit
whats the problem?
please help me?
Thanks
complete code:
char gMessageBuffer[40];
char *gSceneTable[13];
boolean emberAfPreMessageReceivedCallback(EmberAfIncomingMessage* incomingMessage)
{
if (incomingMessage->apsFrame->profileId == HA_PROFILE_ID)
{
if (incomingMessage->apsFrame->clusterId == ZCL_SCENES_CLUSTER_ID)
{
MEMCOPY(gMessageBuffer, incomingMessage->message, incomingMessage->msgLen); // Get incoming message
gMessageBuffer[incomingMessage->msgLen] = '\0';
emberEventControlSetDelayMS(getScenePayloadEventControl, SCENE_ACTION_TRESH);
return true;
}
}
return false;
}
void getScenePayloadEventFunction(void)
{
char *sceneNumber;
char *sceneName;
char *sceneID;
char *sceneAction;
uint8_t sceneTableNumber;
emberAfCorePrintln("///Incoming Message: %s///", gMessageBuffer);
sceneNumber = strtok(gMessageBuffer, ".");
sceneName = strtok(NULL, ".");
sceneID = strtok(NULL, ".");
sceneAction = strtok(NULL, ".");
emberAfCorePrintln("///SCENE NUMBER: %s///", sceneNumber);
emberAfCorePrintln("///SCENE NAME: %s///", sceneName);
emberAfCorePrintln("///SCENE ID: %s///", sceneID);
emberAfCorePrintln("///SCENE ACTION: %s///", sceneAction);
if (strcmp(sceneAction, "Update") == 0)
{
sceneTableNumber = atoi(sceneNumber);
gSceneTable[sceneTableNumber] = strdup(sceneName);
}
emberEventControlSetInactive(getScenePayloadEventControl);
}
this is for microcontroller in simplicity studio IDE.
I get payload in emberAfPreMessageReceivedCallback correctly and I split it into 4 parts and print correctly too.
But after copy the sceneName to gSceneTable array I see the last sceneName in all the elements of gSceneTable with gSceneTable[sceneTableNumber] = sceneName and I see "p]" with gSceneTable[sceneTableNumber] = strdup(sceneName);
It is highly unlikely that your program produce the posted output. The code fragment only handles a single string and char *table[5];
is uninitialized, so printing the strings from table[0]
, table[2]
, table[3]
and table[4]
has undefined behavior. You specified that the strings are read from a file, posting a complete program is required for a precise and correct analysis. Not initializing the array is a problem in case the file does not have all entries covered, it would be impossible to tell which were set and which weren't.
Assuming your program reads the strings from a file or standard input, parsing them with strtok
returns pointers to the source string, which is the array into which you read the lines from the file. Hence all entries in the table[]
array point to the same byte in this array, which explains the output you get: 5 times the contents of the last line.
You should make a copy of the string you store in the table:
table[tableNumber] = strdup(name);
Here is a completed and modified program:
#include <stdio.h>
#include <string.h>
int main() {
char *table[5] = { NULL, NULL, NULL, NULL, NULL };
char buffer[50];
char *number;
char *name;
int tableNumber;
for (int i = 0; i < 5; i++) {
if (!fgets(buffer, sizeof buffer, stdin))
break;
number = strtok(buffer, "-");
if (number == NULL) {
printf("empty line\n");
continue;
}
name = strtok(NULL, "-\n");
if (name == NULL) {
printf("no name after -\n");
continue;
}
tableNumber = atoi(number);
if (tableNumber < 0 || tableNumber >= 5) {
printf("invalid number: %d\n", tableNumber);
continue;
}
table[tableNumber] = strdup(name);
}
for (int i = 0; i < 5; i++) {
if (table[i])
printf("table %d = %s\n", i, table[i]);
}
for (int i = 0; i < 5; i++) {
free(table[i]);
}
return 0;
}
If your target system does not support strdup()
, use this:
#include <stdlib.h>
#include <string.h>
char *mystrdup(const char *s) {
size_t size = strlen(s) + 1;
char *p = malloc(size);
return (p != NULL) ? memcpy(p, s, size) : NULL;
}