Хранить разделенную строку в массиве - PullRequest
1 голос
/ 19 апреля 2020

Я использую 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 Я вижу последнее sceneName во всех элементах gSceneTable с помощью gSceneTable [sceneTableNumber] = sceneName и вижу «p]» с помощью gSceneTable [sceneTableNumber] = strdup (sceneName);

Ответы [ 2 ]

1 голос
/ 19 апреля 2020

Маловероятно, что ваша программа выдаст опубликованный вывод. Фрагмент кода обрабатывает только одну строку, и char *table[5]; неинициализирован, поэтому печать строк из table[0], table[2], table[3] и table[4] имеет неопределенное поведение. Вы указали, что строки читаются из файла, для точного и правильного анализа требуется публикация полной программы. Не инициализация массива является проблемой в случае, если файл не охватывает все записи, было бы невозможно определить, какие из них были установлены, а какие нет.

Если ваша программа считывает строки из файла или стандарта input, анализируя их с помощью 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;
}
0 голосов
/ 19 апреля 2020

Пример кода:

Введите сообщение, например "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;

}

...