NCurses getch 总是 returns ERR (-1)
NCurses getch always returns ERR (-1)
我刚开始使用 ROS,我正在尝试编写一个在主题中发布密钥的节点。
我使用 ncurses 在 Linux Ubuntu 16.04.4 上创建了一个节点。
这是我的代码:
#include <curses.h>
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
int ch;
nodelay(stdscr, TRUE);
ros::init(argc, argv, "keyboard_driver");
ros::NodeHandle n;
ros::Publisher key_pub = n.advertise<std_msgs::String>("keys", 1);
ros::Rate loop_rate(100);
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
if ((ch = getch()) != ERR)
{
ss << ch;
std::cout << ch;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
key_pub.publish(msg);
}
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
我正在使用 ncurses 来避免终端缓冲区。
主题出现了,但是如果我在另一个终端中 运行 这个命令,我什么也得不到:
rostopic echo /keys
调试它我发现 getch() 总是 return -1.
我该怎么做才能让它发挥作用?
更新
我试过这个小程序,它没有打印任何东西:
#include <iostream>
#include <curses.h>
int main(int argc, char **argv)
{
int ch;
cbreak();
nodelay(stdscr, TRUE);
for(;;)
{
if ((ch = getch()) != ERR)
{
std::cout << ch;
}
}
return 0;
}
您已设置 nodelay
,因此如果终端没有准备好数据,getch
将立即 return 并 ERR
。这就是 getch 是 returning -1 (ERR) 的原因。您还没有 设置 cbreak 或 raw 来禁用终端缓冲,所以您仍然得到它 -- 在 Enter[=22= 之前不会有数据来自终端]被击中。
因此,在开始时添加对 cbreak()
的调用(就在对 nodelay()
的调用之前或之后),它应该会按预期工作。
要使用 getch()
,您必须执行以下操作:
#include <iostream>
#include <curses.h>
#include <signal.h>
#include <stdlib.h>
void quit(int sig)
{
endwin();
exit(0);
}
int main(int argc, char **argv)
{
int ch;
signal(SIGINT,quit);
initscr();
cbreak();
nodelay(stdscr, TRUE);
for(;;)
{
if ((ch = getch()) != ERR)
{
std::cout << ch;
}
}
return 0;
}
我忘记在程序开头添加 initscr();
调用,在程序结尾添加 endwin();
。
有关如何使用 ncurses 库的更多信息 here。
我刚开始使用 ROS,我正在尝试编写一个在主题中发布密钥的节点。
我使用 ncurses 在 Linux Ubuntu 16.04.4 上创建了一个节点。
这是我的代码:
#include <curses.h>
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
int ch;
nodelay(stdscr, TRUE);
ros::init(argc, argv, "keyboard_driver");
ros::NodeHandle n;
ros::Publisher key_pub = n.advertise<std_msgs::String>("keys", 1);
ros::Rate loop_rate(100);
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
if ((ch = getch()) != ERR)
{
ss << ch;
std::cout << ch;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
key_pub.publish(msg);
}
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
我正在使用 ncurses 来避免终端缓冲区。
主题出现了,但是如果我在另一个终端中 运行 这个命令,我什么也得不到:
rostopic echo /keys
调试它我发现 getch() 总是 return -1.
我该怎么做才能让它发挥作用?
更新
我试过这个小程序,它没有打印任何东西:
#include <iostream>
#include <curses.h>
int main(int argc, char **argv)
{
int ch;
cbreak();
nodelay(stdscr, TRUE);
for(;;)
{
if ((ch = getch()) != ERR)
{
std::cout << ch;
}
}
return 0;
}
您已设置 nodelay
,因此如果终端没有准备好数据,getch
将立即 return 并 ERR
。这就是 getch 是 returning -1 (ERR) 的原因。您还没有 设置 cbreak 或 raw 来禁用终端缓冲,所以您仍然得到它 -- 在 Enter[=22= 之前不会有数据来自终端]被击中。
因此,在开始时添加对 cbreak()
的调用(就在对 nodelay()
的调用之前或之后),它应该会按预期工作。
要使用 getch()
,您必须执行以下操作:
#include <iostream>
#include <curses.h>
#include <signal.h>
#include <stdlib.h>
void quit(int sig)
{
endwin();
exit(0);
}
int main(int argc, char **argv)
{
int ch;
signal(SIGINT,quit);
initscr();
cbreak();
nodelay(stdscr, TRUE);
for(;;)
{
if ((ch = getch()) != ERR)
{
std::cout << ch;
}
}
return 0;
}
我忘记在程序开头添加 initscr();
调用,在程序结尾添加 endwin();
。
有关如何使用 ncurses 库的更多信息 here。