C: Shell命令无故双输出

C: Shell command double output without reason

所以我正在使用 CAN 工具 使用 this CANopenNode 我正在通过 .c 程序文件制作 candump。

我的接收器代码如下所示

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] = '[=11=]';
          else if ( i>29 )
          {
            message_data[cdata] = raw_message[i];
            cdata++;
          }
        }
        message_data[16] = '[=11=]';
        //END OF GETTING MESSAGE
        fprintf(stdout,"%s\n",raw_message); 
        fflush(stdout);
      }

  }

  pclose(fp);

我正在 运行 宁一个 shell 发送脚本

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

我想做的是将 id 从消息的实际数据中分离出来。事情是,正如你所看到的,只有当 raw_message 的第一个插槽不是 space 时我才会这样做,因为我收到一条消息,我用 fgets 得到它,然后我得到 ' ' 然后是消息,然后 ' ' 等等继续。只有当我使用 if (isspace) 似乎有效并且如果我发表评论时,命令 "fprintf(stdout,"%s\n",raw_message);"停止工作。 我尝试了多种解决方案,但似乎没有任何效果。这样做有什么特别的原因吗?我是做错了什么还是 CANUtils 的问题?

我使用 issspace() 时的输出(输出与我 运行 candump on 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] = '[=14=]';
          else if ( i>29 )
          {
            message_data[cdata] = raw_message[i];
            cdata++;
          }
        }
        message_data[16] = '[=14=]';
        //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

问题中显示的示例数据

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

...

行长为 46 个字符,不包括换行符 ('\n') 或 47 个字符,包括换行符。

fgets 需要附加尾随 NUL 字符 ('[=17=]') 以终止字符串。这就是为什么第一次调用将读取没有换行符的行,因为缓冲区已满。缓冲区将包含字符串

"(1585149182.549347) vcan0 123#0801010101010101"

下一次调用将只读取换行符,因为这是行尾。缓冲区将包含

"\n"

您必须将 raw_message 的大小增加到至少 48。 然后你会得到

"(1585149182.549347) vcan0 123#0801010101010101\n"

一次 fgets 通话。

请注意,使用 socketcan interface 读取二进制 CAN 消息可能比解析 candump 的文本输出更好。