2013-06-03 3 views
1

Моего внешним устройства посылает мне данные каждые 5 секунд, как эти:странные лексемы результатов с использованием strtok

+DATA: 43 BYTES FROM 0000:0000 (043) 
Nodo_8:(T=21.45,HR=45.65,DW=9.34,Vcc=3.46V) 

мне нужно некоторые значения из здесь, чтобы сохранить их в тузде datadase. Поэтому с использованием strtok я хочу получить значения 043, 21.45, 45.65, 9.34, 3.46.

Я написал следующий код, который считывает буфер с устройства:

int learn_port(int fd) 
{ 
    int n; 
    char buff[83]; 

for (;;) 
    { 
    n=read(fd,buff,83); 
    printf("%s", buff); 
    char dev_a[25] = "", temp_a[25] = "", hr_a[25] = "", dw_a[25] = "", vcc_a[25] = ""; 
    char* ptr; 

    ptr = strtok(buff, "+DATA:BYTESFROM()\nNodo_ ,=T:HR:DW:Vcc()"); 
    int i = 0; 
    while (ptr != NULL) 
    { 
    ptr = strtok(NULL, "+DATA:BYTESFROM()\nNodo_ ,=T:HR:Dw:Vcc()"); 
    if (i == 2) 
     strcat(dev_a, ptr); // copies device 
    if (i == 5) 
     strcat(temp_a, ptr); // copies T 
    if (i == 6) 
     strcat(hr_a, ptr); // copies HR 
    if (i == 7) 
     strcat(dw_a, ptr); // copies DW 
    if (i == 10) 
     strcat(vcc_a, ptr); 
    i++; 
    } 
    sleep(1); 
    printf("%s, %s, %s, %s, %s\n", dev_a, temp_a,hr_a,dw_a,vcc_a); 
} 

Но у меня есть некоторые странные результаты, и я не знаю, где есть проблема. Терминал возвращает меня в первый раз:

+DATA: 43 BYTES FROM 0000:0000 (043) 
Nodo_8:(T=21.45,HR=45.65,DW=9.34,Vcc=3.46V) 
??,??043, 21.45, 45.65, 9.34, 3.46 

после 5 секунд

+DATA: 43 BYTES FROM 0000:0000 (043) 
Nodo_8:(T=21.23,HR=42.65,DW=9.45,Vcc=3.46V) 
?3.46043, 21.23, 42.65, 9.45, 3.46 

через 5 секунд

+DATA: 43 BYTES FROM 0000:0000 (051) 
Nodo_8:(T=21.67,HR=42.45,DW=9.23,Vcc=3.46V) 
?3.46051, 21.67, 42.45, 9.23, 3.46 

и т.д. Кто-нибудь знает, где проблема и у меня есть 3,46? до 051? Есть ли проблемы с strtok? Мои результаты хотят быть 043, 21.67, 42.45, 9.23, 3.46

ответ

0

Помогая, прежде чем на это, я чувствовал, что это мой долг, чтобы вмешаться и попытаться разобраться код шахты, который прекратил делать то, что он должен делать :)

Хорошо, я предлагаю вам иметь два отдельных случая для ввода, я разделил их на те, которые начинаются с «+» для «+ DATA» и «N» для «Nodo_8» (это очень грубо, убедитесь, что это действительно, дело в противном случае имеет некоторую дополнительную валидацию).

Я переместил вызов на strok с начала цикла до конца, так как он может «символизировать» строку дважды на первой итерации, прежде чем у нас появилась возможность извлечь что-либо. Я поставил его перед приращением i. Если вы хотите сохранить его с самого начала, просто вычтите 1 из i, где мы делаем проверки.

Тогда это было просто вопрос об обнаружении, при котором итерация цикла будет выплевывать правильные значения.

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

int main() 
{ 
    /* dev_a and dev_b could be the same source in your case, modify accordingly */ 
    char dev_a[] = "+DATA: 43 BYTES FROM 0000:0000 (043)"; 
    char dev_b[] = "Nodo_8:(T=21.23,HR=42.65,DW=9.45,Vcc=3.46V)"; 

    char out0[35] = ""; 
    char out1[35] = ""; 
    char out2[35] = ""; 
    char out3[35] = ""; 
    char out4[45] = ""; 

    char* ptr; 
    int i; 

    if (dev_a[0] == '+') 
    { 
     ptr = strtok(dev_a, "+DATA: BYTES FROM()"); 

     i = 0; 

     while (ptr != NULL) 
     {    
      if (i == 3) 
       strcat(out0, ptr); /* copies DATA (value in brackets) */ 

      ptr = strtok(NULL, "+DATA: BYTES FROM()"); 

      i++; 
     } 

     printf("+DATA: %s\n", out0); 
    } 
    if (dev_b[0] == 'N') 
    { 
     ptr = strtok(dev_b, "Nodo_,=T:HR:DW:Vcc()"); 

     i = 0; 

     while (ptr != NULL) 
     {   
      if (i == 1) 
       strcat(out1, ptr); /* copies T */ 
      if (i == 2) 
       strcat(out2, ptr); /* copies HR */ 
      if (i == 3) 
       strcat(out3, ptr); /* copies DW */ 
      if (i == 4) 
       strcat(out4, ptr); /* copies Vcc */ 

      ptr = strtok(NULL, "Nodo_,=T:HR:DW:Vcc()"); 

      i++; 
     } 

     printf("Nodo_8: %s, %s, %s, %s\n", out1, out2, out3, out4); 
    } 

    return 0; 
} 

С помощью этого кода я получаю следующий результат (со всех трех случаях для «NODO»):

$ ./a.out 
+DATA: 043 
Nodo_8: 21.45, 45.65, 9.34, 3.46 

$ ./a.out 
+DATA: 043 
Nodo_8: 21.67, 42.45, 9.23, 3.46 

$ ./a.out 
+DATA: 043 
Nodo_8: 21.23, 42.65, 9.45, 3.46 

«043» соответствует части в «+ DATA», а остальные для ' Nodo 'бит.

Есть ли у меня правильные значения? Я сделал предположение с вашего поста. Я тестировал все три образца Nodo, которые вы предоставили.

2

Я считаю, что вы неправильно понимаете второй аргумент strtok(); это не целая строка разделителя, это «набор символов». Другими словами, каждый символ в строке считается допустимым разделителем.

См the manual page для получения более подробной информации, обратите внимание, что он говорит:

DELIM аргумент определяет набор байтов, которые разграничивают маркеры в разобранном строке.

В общем, это выглядит как-то вы должны решить с простой sscanf(), нет необходимости использовать strtok(), который является немного более низким уровнем и сложен.

0

Как говорится, проблема связана с strtok(). Я думаю, что ваш код сделал некоторое неопределенное поведение, потому что вы неправильно использовали параметр разделителя.

Лексемы strtok будет найти будет: 43,0000,0000,043,8,21.45,45.65,9.34,3.46 Я даже не знаю, почему это работает для вас, чтобы извлечь T, HR и т.д.

Если вы удаляете разделители, которые вы ему давали несколько раз, и вы снова подсчитываете маркеры, будет рабочее (не элегантное) решение.

Проверьте код и выход HERE

0

Возможно, я думаю, что buff содержит скрытые символы, которых вы не ожидаете.

Итак, я думаю, мне нужно добавить процесс, чтобы избавиться от скрытых символов от buff.

E.g.

#include <ctype.h> 

void strip_nonprint(char s[]) { 
    char *from, *to; 
    from = to = s; 
    while(*from){ 
     if(isprint(*from))//note: remove newline 
      *to++ = *from++; 
     else 
      ++from; 
    } 
    *to = '\0'; 
} 

код изменения:

n=read(fd,buff,83); 
strip_nonprint(buff);//add 

/* { i | 2, 4, 5, 6, 7} */ 
if (i == 2) 
strcat(dev_a, ptr); // copies device 
if (i == 4) 
strcat(temp_a, ptr); // copies T 
if (i == 5) 
    strcat(hr_a, ptr); // copies HR 
if (i == 6) 
    strcat(dw_a, ptr); // copies DW 
if (i == 7) 
    strcat(vcc_a, ptr);