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