C++ 从命令行读取()返回EISDIR错误

C++ 从命令行读取()返回EISDIR错误,c++,ros,C++,Ros,我正在尝试从终端读取箭头键字符,并使用通过ROS发送String类型的消息。为此,我使用了termiosread()函数 首先,我做了一个小测试,它在C下运行良好,使用gcc编译。代码如下: #include <unistd.h> #include <stdlib.h> #include <termios.h> // for keyboard input #include <string.h> #include <stdio.h> b

我正在尝试从终端读取箭头键字符,并使用通过
ROS
发送
String
类型的消息。为此,我使用了
termios
read()
函数

首先,我做了一个小测试,它在
C
下运行良好,使用
gcc
编译。代码如下:

#include <unistd.h>
#include <stdlib.h>
#include <termios.h> // for keyboard input
#include <string.h>
#include <stdio.h>

bool quit_requested = false;

void processKeyboardInput (char c)
{
   switch (c)
   {
     case 68:// Left arrow pressed
     {
       puts("Left pressed");
       break;
     }
     case 67://Right arrow pressed
     {
       puts("Right pressed");
       break;
     }
     case 65://Up arrow pressed
     {
       puts("Up pressed");
       break;
     }
     case 66://Down arrow pressed
     {
       puts("Down pressed");
       break;
     }
     case 'q'://Quit arrow pressed
     {
       quit_requested = true;
       puts("q pressed, quitting...");
     }
     default:
     {
       break;
     }
 }

}

int main(int argc, char const *argv[]) {
  int key_file_descriptor;
  struct termios raw;
  struct termios original_terminal_state;

  tcgetattr(key_file_descriptor, &original_terminal_state); // get       terminal properties
  memcpy(&raw, &original_terminal_state, sizeof(struct termios));

  raw.c_lflag &= ~(ICANON | ECHO);//local modes, enable canonical mode and echo
  // Setting a new line, then end of file
  raw.c_cc[VEOL] = 1;//special characters
  raw.c_cc[VEOF] = 2;
  tcsetattr(key_file_descriptor, TCSANOW, &raw);

  puts("Reading from keyboard");
  puts("---------------------------");
  puts("Press the arrow keys to move and q to quit");

  char c;
  while (!quit_requested)
  {
    if (read(key_file_descriptor, &c, 1) < 0)
    {
      perror("read char failed():");
      exit(-1);
    }
    processKeyboardInput(c);
  }
      tcsetattr(key_file_descriptor, TCSANOW,      &original_terminal_state);
      puts("Exit");
    return 0;
    }
一旦创建了
CMakeLists.txt
package.xml
,我就用
catkin\u make
进行了编译。测试它,现在不起作用,大多数时候我在
read()
收到错误返回,它进入
EISDIR
案例并打印它。你知道为什么我现在收到这个错误,而前面的
c
示例工作正常吗


提前谢谢

在@Jonathan的重新命名之后,我将标志
-Wall-Werror-Wextra
添加到
CMake
编译标志中,并发现编译器抛出的下一条消息:

错误:“key\u file\u descriptor”在此函数中可能未初始化使用[-Werror=可能未初始化]


我发现了这一点,并更改了我用于
STDIN\u FILENO
int-key\u文件描述符。所以我已经在代码中全部替换了它,现在正在工作!我还删除了比较打字错误。谢谢大家

哪一行生成EISDIR错误?第二个示例中的
main()
中的
read()
调用?您需要测试
errno
设置为-not
error
的内容。通常,
error
将是
-1
,这与任何
E*
宏都不匹配,因为它们都是正值。是的,
read()
返回负值,这就是为什么我有
大小写的原因。它进入
error=EISDIR
案例。我不明白为什么第一个例子有效,第二个不起作用。你得到了一个赋值而不是等式输入:
else if(error=EISDIR)put(“EISDIR”)。我建议删除此问题,并提高编译器警告级别。如果您使用的是GCC,请至少使用
-Wall-Werror-Wextra
。我使用的不止这些,但我只在C语言中编程了30多年,所以我知道我并不完全了解它(而且这些选项阻止我犯愚蠢的错误,比如赋值而不是比较)。请注意,您不应该测试
错误
;您可能正在测试
errno
,它将包含
E*
宏的值。@mugurumov如果将错误检查代码添加到第一个示例中,您将遇到完全相同的问题。
#include <unistd.h>
#include <termios.h> // for keyboard input
#include <cstring>
#include <stdio.h>

#include "ros/ros.h"
#include "std_msgs/String.h"


bool quit_requested = false;


std::string processKeyboardInput (char c)
{

   switch (c)
   {
     case 68:// Left arrow pressed
     {
       puts("Left pressed");
       return ("left");
     }
     case 67://Right arrow pressed
     {
       puts("Right pressed");
       return ("right");
     }
     case 65://Up arrow pressed
     {
       puts("Up pressed");
       return ("forward");
     }
     case 66://Down arrow pressed
     {
       puts("Down pressed");
       return ("backward");
     }
     case 'q'://Quit arrow pressed
     {
       quit_requested = true;
       puts("q pressed, quitting...");
     }
     default:
     {
       return ("");
     }
 }

}

int main(int argc, char **argv) {

  std::string cmd;
  int key_file_descriptor;
  char c;
  int error;
  struct termios raw;
  struct termios original_terminal_state;
  //std::string name = "key_teleop";

  /**** INIT ROS STUFFS  *****/
  ros::init(argc, argv, "key_teleop");
  std_msgs::String msg;
  ros::NodeHandle n;
  ros::Publisher key_pub = n.advertise<std_msgs::String>("key_teleop", 1000);
  ros::Rate loop_rate(1);
  /***************************/

  tcgetattr(key_file_descriptor, &original_terminal_state); // get terminal properties
  memcpy(&raw, &original_terminal_state, sizeof(struct termios));

  raw.c_lflag &= ~(ICANON | ECHO);//local modes, enable canonical mode and echo
  // Setting a new line, then end of file
  raw.c_cc[VEOL] = 1;//special characters
  raw.c_cc[VEOF] = 2;
  tcsetattr(key_file_descriptor, TCSANOW, &raw);

  puts("Reading from keyboard");
  puts("---------------------------");
  puts("Press the arrow keys to move and q to quit");


  while (ros::ok() & (!quit_requested))
  {
  //if (read(key_file_descriptor, &c, 1) < 0)
    error = read(key_file_descriptor, &c, 1);
    if ( error < 0)//Process the error
    {//TODO I get errors, not ROSify code doesn't, C / C++ code mixture issue??
      if (error == EAGAIN)
        puts ("EAGAIN");
      else if (error == EBADF)
        puts ("EBADF");
      else if (error == EFAULT)
        puts ("EFAULT");
      else if (error == EINTR)
        puts ("EINTR");
      else if (error == EINVAL)
        puts ("EINVAL");
      else if (error == EIO)
        puts ("EIO");
      else if (error = EISDIR)
        puts ("EISDIR");
      perror("read char failed():");
      exit(-1);
    }
    cmd = processKeyboardInput(c);
    if (!cmd.empty())
    {
      msg.data = cmd;
      key_pub.publish(msg);
      ros::spinOnce();
      //loop_rate.sleep();
    }
  }
  tcsetattr(key_file_descriptor, TCSANOW, &original_terminal_state);
  puts("Exit");
return 0;
}