将拆分后的字符串存储在数组中

Store splitted string in array

我使用 strtok() 拆分字符串并存储在数组中,如下所示

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

输入 5 次后结果应为:

table 0 = Study
table 1 = Sleep
table 2 = Party
table 3 = Hello
table 4 = Exit

但结果是:

table 0 = Exit
table 1 = Exit
table 2 = Exit
table 3 = Exit
table 4 = Exit

有什么问题?

请帮帮我?

谢谢


完整代码:

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] = '[=13=]';
            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);
}   

这是用于 simplicity studio 中的微控制器 IDE。

我在 emberAfPreMessageReceivedCallback 中正确获取了负载 我把它分成 4 个部分并正确打印。

但是在将 sceneName 复制到 gSceneTable 数组后,我看到 gSceneTable 的所有元素中的最后一个 sceneName 为 gSceneTable[sceneTableNumber] = sceneName 并且我看到 "p]" 为 gSceneTable[sceneTableNumber] = strdup(sceneName);

示例代码:

输入类似 "sceneNumber.sceneName.sceneID.Update"

的消息

例如:1.Study.12345.Update

#include <stdio.h>
#include <string.h>
#include <conio.h>

char *gSceneTable[13];
char gMessageBuffer[50];

int main()
{
   char *sceneNumber;
   char *sceneName;
   char *sceneID;
   char *sceneAction;
   int sceneTableNumber;
   int check;
   int c;

   printf("Enter payload for 3 Times\r\n");

   while(check != 3)
   {
       scanf("%s", &gMessageBuffer);

       printf("Message is: %s\r\n",gMessageBuffer);

       sceneNumber = strtok(gMessageBuffer, ".");
       sceneName = strtok(NULL, ".");
       sceneID = strtok(NULL, ".");
       sceneAction = strtok(NULL, ".");

       printf("%s\r\n", sceneNumber);
       printf("%s\r\n", sceneName);
       printf("%s\r\n", sceneID);
       printf("%s\r\n", sceneAction);

       if (strcmp(sceneAction, "Update") == 0)
       {
        sceneTableNumber = atoi(sceneNumber);
        gSceneTable[sceneTableNumber] = sceneName;
       }

   check++;
   }

   for (c = 0; c < 4; c++)    
   {
       printf("Scene Table: %d ----- %s \r\n", c, gSceneTable[c]);
   }

return 0;

}

您的程序极不可能产生发布的输出。代码片段仅处理单个字符串并且 char *table[5]; 未初始化,因此打印 table[0]table[2]table[3]table[4] 中的字符串具有未定义的行为。您指定从文件中读取字符串,需要发布完整的程序才能进行精确和正确的分析。如果文件没有涵盖所有条目,则不初始化数组是一个问题,将无法判断哪些已设置,哪些未设置。

假设您的程序从文件或标准输入中读取字符串,使用 strtok returns 指向源字符串的指针解析它们,这是您从文件中读取行的数组.因此,table[] 数组中的所有条目都指向该数组中的相同字节,这解释了您获得的输出:最后一行内容的 5 倍。

您应该复制存储在 table 中的字符串:

table[tableNumber] = strdup(name);

这是一个完整的修改后的程序:

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

如果你的目标系统不支持strdup(),使用这个:

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