C: создать массив из символа * - PullRequest
0 голосов
/ 18 января 2020

Я использую Arduino для получения РЧ-сообщений от чипа RF69.
Сообщение содержит данные о погоде, такие как температура, влажность и барометрия c давление.
Полученная строка выглядит следующим образом: 1: 22.26 : 41.53: 1023.73 (тип сообщения: temp: hum: pres)
Мне нужно преобразовать это в массив, а затем скопировать данные в значения с плавающей точкой.
Используя strtok, я могу скопировать некоторые данные, но мне кажется, быть пропущенными значениями.

Serial.print("Message: "); 
Serial.println((char*)buf); //Message: 1:22.32:41.39:1023.77

char* data;
data = (char*)buf; //incoming from radio buffer
char separator[] = ":"; //delimeter
char *array[3]; //expect 3 value
int i=0; //start loop at 0
array[i] = strtok(data,separator); //first token
while(array[i]!=NULL) {
    array[++i] = strtok(NULL,separator);
    Serial.println(array[i]);
}

Кажется, что выводится правильно:

Message: 1:22.32:41.18:1023.77
22.32
41.18
1023.77

Когда я назначаю поплавки, мне не хватает значения t:

float t = atof(array[1]);
float h = atof(array[2]);
float p = atof(array[3]);
Serial.print("Temperature =  "); Serial.println(t);
Serial.print("Rel. Humidity =  "); Serial.println(h);
Serial.print("Pressure =  "); Serial.println(p);

Вывод:

Temperature =  0.00
Rel. Humidity =  41.33
Pressure =  1023.78

Может кто-нибудь объяснить, почему мне не хватает значения температуры?
Кроме того, поскольку у меня нет опыта с C, есть ли лучший способ сделать это?

1 Ответ

0 голосов
/ 18 января 2020

Этот код:

while( array[i] != NULL){ 
    array[++i] = strtok(NULL,separator);
    Serial.println(array[i]);
}

записывает в array[3] и array[4], которые находятся за пределами. Поле давления имеет значение array[0], а NULL - array[4].

Изменить на:

while( i < sizeof(array) / sizeof(*array) &&
       array[i] != NULL) 
{
    array[i] = strtok(NULL,separator);
    Serial.println(array[i]);
    i++ ;
}

, который перезаписывает указатель на array[0] с типом сообщения, которое вы отбрасываете, и выполняет итерацию до тех пор, пока все поля не будут извлечены, а не когда strtok() вернет NULL ,

Затем измените индексы в atof():

float t = atof(array[0]);
float h = atof(array[1]);
float p = atof(array[2]);

Вы также можете проверить правильность типа сообщения.

array[i] = strtok(data,separator); //first token
if( array[i][0] == '1' && array[i][1] == 0 )
{
    while( i < sizeof(array) / sizeof(*array) &&
           array[i] != NULL) 
    {
        array[i] = strtok(NULL,separator);
        Serial.println(array[i]);
        i++ ;
    }
}

Если вы действительно хотели чтобы сохранить тип сообщения, для array требуется 4 элемента, а тело l oop станет:

        i++ ;
        array[i] = strtok(NULL,separator);
        Serial.println(array[i]);

Вы можете предварительно увеличить array[++i] в соответствии с исходным кодом, но я бы хотел не рекомендуется - это не служит ясности, а семантика и последовательность усложняются при использовании в более сложных выражениях - всегда используйте его «автономно», чтобы избежать ошибок и недоразумений.

...