【问题标题】:Store splitted string in array将拆分后的字符串存储在数组中
【发布时间】:2020-04-19 16:16:12
【问题描述】:

我使用 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] = '\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);
}   

这适用于简单工作室 IDE 中的微控制器。

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

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

【问题讨论】:

  • 您能提供一个完整的(可编译的)最小示例吗?
  • char buffer[50] = {"1-Study"}; --> char buffer[50] = "1-Study";
  • @David Ranieri:这是更常见的做法,但两者是等价的
  • @xanoetux,是的,这不是问题,但在单个数组中看到多维符号有点奇怪。

标签: c strtok atoi


【解决方案1】:

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

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

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

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

【讨论】:

  • 我使用 table[tableNumber] = strdup(name);但它不起作用 anr print p[
  • @Majid:在您的问题末尾的 EDIT: 段落之后发布完整的代码。
  • @Majid:你包括&lt;string.h&gt;吗?
  • @Majid:你的strdup() 有问题。代码在什么系统上运行?
  • 在 Simplicity Studio IDE 和 IAR 编译器中,在 Windows 10 中
【解决方案2】:

示例代码:

输入类似“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;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    相关资源
    最近更新 更多