C: двойной вывод команды Shell без причины - PullRequest
1 голос
/ 25 марта 2020

, поэтому я работаю с утилитой CAN, используя этот CANopenNode, я делаю подсчет через программный файл. c.

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

char raw_message[47], message_id[4], message_data[17];
fp = popen("candump vcan0 -L", "r");

  if( fp == NULL )
  {
    printf("Failed to run CANDUMP for VCAN0");
    exit(1);
  }

  while ( fgets(raw_message, sizeof(raw_message), fp) )
  {
      if( isspace(raw_message[0]) )
      {
      }
      else
      {
        //GETTING THE ACTUAL MESSAGE = ID+DATA
        cid = 0;
        cdata = 0;
        for(i=26; i<46; i++)
        {
          if( i<29 )
          {
            message_id[cid] = raw_message[i];
            cid++;
          }
          else if ( i==29 )
            message_id[cid] = '\0';
          else if ( i>29 )
          {
            message_data[cdata] = raw_message[i];
            cdata++;
          }
        }
        message_data[16] = '\0';
        //END OF GETTING MESSAGE
        fprintf(stdout,"%s\n",raw_message); 
        fflush(stdout);
      }

  }

  pclose(fp);

и я запускаю скрипт оболочки для отправки

echo "Start"
i=0;
while [ $i -le 5 ] ;
do
    #echo "sent"
    cansend vcan0 123#0801010101010101
    let i=$i+1
done
exit 0

, что я пытаюсь сделать, это отделить идентификатор от фактических данных сообщения. Дело в том, что, как вы можете видеть, я делаю это только в том случае, если первый слот raw_message не является пространством, потому что я получаю сообщение, которое я получаю с помощью fgets, а затем я получаю сообщение «затем сообщение, затем» и так далее go. Только когда я использую if (isspace), кажется, работает и если я добавляю комментарии, команда "fprintf (stdout,"% s \ n ", raw_message);" перестает работать Я пробовал несколько решений, но ничего не работает. Есть ли какая-то конкретная причина, почему это делается? Я делаю что-то не так или это может быть что-то из CANUtils?

Вывод, когда я использую issspace () (вывод такой же, как и при запуске Candump на bash) {}

(1585149182.549347) vcan0 123#0801010101010101
(1585149182.550713) vcan0 123#0801010101010101
(1585149182.555930) vcan0 123#0801010101010101
(1585149182.559413) vcan0 123#0801010101010101
(1585149182.560687) vcan0 123#0801010101010101
(1585149182.561604) vcan0 123#0801010101010101

Вывод, когда я им не пользуюсь

while ( fgets(raw_message, sizeof(raw_message), fpdump) )
  {
      // if( isspace(raw_message[0]) )
      // {
      // }
      // else
      {
        //GETTING THE ACTUAL MESSAGE = ID+DATA
        cid = 0;
        cdata = 0;
        for(i=26; i<46; i++)
        {
          if( i<29 )
          {
            message_id[cid] = raw_message[i];
            cid++;
          }
          else if ( i==29 )
            message_id[cid] = '\0';
          else if ( i>29 )
          {
            message_data[cdata] = raw_message[i];
            cdata++;
          }
        }
        message_data[16] = '\0';
        //END OF GETTING MESSAGE
        fprintf(stdout,"%s\n",raw_message); 
        fflush(stdout);
      }

  }

Вывод:

(1585149305.257591) vcan0 123#0801010101010101


(1585149305.258339) vcan0 123#0801010101010101


(1585149305.259055) vcan0 123#0801010101010101


(1585149305.259651) vcan0 123#0801010101010101


(1585149305.260280) vcan0 123#0801010101010101


(1585149305.260860) vcan0 123#0801010101010101

1 Ответ

1 голос
/ 25 марта 2020

Пример данных, как показано в вопросе

(1585149182.549347) vcan0 123#0801010101010101
(1585149182.550713) vcan0 123#0801010101010101

...

, имеет длину строки 46 символов без символа новой строки ('\n') или 47, включая новую строку .

fgets необходимо добавить завершающий символ NUL ('\0') для завершения строки. Вот почему первый вызов будет читать строку без новой строки, потому что буфер заполнен. Буфер будет содержать строку

"(1585149182.549347) vcan0 123#0801010101010101"

Следующий вызов будет читать символ новой строки только потому, что это конец строки. Буфер будет содержать

"\n"

Вы должны увеличить размер raw_message как минимум до 48. Тогда вы получите

"(1585149182.549347) vcan0 123#0801010101010101\n"

за один fgets вызов.

Обратите внимание, что может быть лучше читать двоичные сообщения CAN, используя интерфейс socketcan вместо анализа текстового вывода candump.

...