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
设置为-noterror
的内容。通常,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;
}