简体   繁体   English

如何将使用 curses/ncurses 的 ac 程序的输出传递给另一个程序?

[英]How do I pass the output of a c program which use curses/ncurses to another program?

I have a simple c program which use ncurses to display some text on the screen.我有一个简单的 c 程序,它使用ncurses在屏幕上显示一些文本。 When running, it will print out hello , when the user press the arrow key up, it will exit the program printing on screen bye see you soon .运行时会打印出hello ,当用户按向上箭头键时,会退出程序打印在屏幕上, bye see you soon

I would like to be able to use the output printed by the program, in this case bye see you soon as input of another program, for instance I would like to pass it to grep or cat , like:我希望能够使用程序打印的输出,在这种情况下, bye see you soon ,作为另一个程序的输入,例如我想将它传递给grepcat ,例如:

./main.out | grep "bye"

similarly of the result I would get if I could pipe it like echo "bye see you soon" | grep "bye"如果我可以像echo "bye see you soon" | grep "bye" echo "bye see you soon" | grep "bye"

or alternatively by using something like command substitution $(...) .或者通过使用类似命令替换的东西$(...)

With my current solution, if I use ./main.out | grep "bye"使用我当前的解决方案,如果我使用./main.out | grep "bye" ./main.out | grep "bye" I get always a blank screen and I am not able to pipe to grep. ./main.out | grep "bye"我总是看到一个空白屏幕,我无法通过管道连接到 grep。

Currently looking to a solution for Linux/macOS only.目前正在寻找仅适用于 Linux/macOS 的解决方案。

I would like to know:我想知道:

  • How I could solve this problem?我该如何解决这个问题? (I would appreciate a snippet of code) (我会很感激一段代码)
  • Is atexit the only solution available? atexit是唯一可用的解决方案吗?

I am learning a bit of c, if you are able to give me a bit more context in the answer I would really appreciate it.我正在学习一点 c,如果您能够在答案中给我更多的背景信息,我将非常感激。

Run the program with:运行程序:

make all
./main.out
================================== main.c

#include <stdio.h>
#include <curses.h>
#include <stdlib.h>

void print_menu(WINDOW *menu_win);

void bye(void)
{
    printf("bye see you soon\n");
}

void print_menu(WINDOW *menu_win)
{
    printf("hi");
    wrefresh(menu_win);
}

int main()
{
    WINDOW *menu_win;
    int c;

    initscr();
    clear();
    noecho();
    cbreak();

    menu_win = newwin(30, 30, 0, 0);
    keypad(menu_win, TRUE);
    refresh();
    print_menu(menu_win);
    
    while (1)
    {
        c = wgetch(menu_win);
        switch (c)
        {
        case KEY_UP:
            endwin();

            int i = atexit(bye);
            if (i != 0)
            {
                fprintf(stderr, "cannot set exit function\n");
                exit(EXIT_FAILURE);
            }
            exit(EXIT_SUCCESS);
            break;
        default:
            refresh();
            break;
        }
    }
    clrtoeol();
    refresh();
    endwin();
    return 0;
}
================================== Makefile

SHELL   = /bin/sh
PROGRAM = main
CC      = gcc
CFLAGS  = -g -O0 -Wall -Werror
LIBS    = -lncurses

all:
    $(CC) ./${PROGRAM}.c -o ./${PROGRAM}.out $(CFLAGS) $(LIBS)

initscr does the equivalent of newterm(NULL, stdout, stdin) , which pretty well makes it impossible to also pipe output into some other utility. initscr相当于newterm(NULL, stdout, stdin) ,这使得将输出也通过管道传输到其他实用程序是不可能的。 If you want to do both, you can force ncurses to use /dev/tty for both input and output by replacing initscr() with something like:如果你想两者都做,你可以强制 ncurses 使用/dev/tty输入和输出,方法是将initscr()替换为:

    FILE* tty = fopen("/dev/tty", "r+");
    SCREEN* screen = newterm(NULL, tty, tty);
    set_term(screen);

If you do that, you'll want to avoid writing to stdout (if it hasn't been redirected) while ncurses is active, since ncurses assumes that no-one else is writing to the console.如果您这样做,您将希望避免在 ncurses 处于活动状态时写入标准输出(如果尚未重定向),因为 ncurses 假定没有其他人正在写入控制台。

It might be useful to change the behaviour of your application, depending on whether stdout has been redirected.根据stdout是否已被重定向,更改应用程序的行为可能很有用。 You could use isatty() for a fairly conservative test.您可以使用isatty()进行相当保守的测试。

I don't really understand why you think it is necessary to use atexit() in your sample program.我真的不明白为什么你认为有必要在你的示例程序中使用atexit() As soon as you call endwin() , it's safe to write to stdout .只要您调用endwin() ,就可以安全地写入stdout (But the printf of Hi in print_menu is problematic.) (但是print_menuHiprintf是有问题的。)

It's also possible to use stderr as the ncurses output, on the assumption that it has not been redirected.假设它没有被重定向,也可以使用stderr作为 ncurses 输出。 I prefer the use of /dev/tty because it doesn't interfere with the use of stderr for error logging (invalidating the assumption that it has not been redirected).我更喜欢使用/dev/tty ,因为它不会干扰使用stderr进行错误记录(使它没有被重定向的假设无效)。 But if that's not important to you, newterm(NULL, stderr, stdin) is possibly simpler.但是,如果这对您不重要,那么newterm(NULL, stderr, stdin)可能更简单。

In any case, make sure you always check return values for error indications (which I omitted in the above code snippet).在任何情况下,请确保您始终检查错误指示的返回值(我在上面的代码片段中省略了)。

Traditionally, programs that use ncurses (or the older curses) don't output anything to stdout -- they only ever use stdin (and actually write to stdin to write to the terminal).传统上,使用 ncurses(或较旧的 curses)的程序不会向标准输出输出任何内容——它们只使用标准输入(实际上写入标准输入以写入终端)。 So they don't "play nice" with pipes that take the stdout of one process and connect it to the stdin of another process.因此,他们不会“玩得很好”,这些管道采用一个进程的标准输出并将其连接到另一个进程的标准输入。

If you want to have a program that interacts with a terminal on stdin with ncurses and outputs something to stdout, you can do that -- stdin and stdout don't need to have anything to do with each other -- and that would allow you to pipe the output from stdout somewhere else.如果您想要一个程序与标准输入上的终端进行交互,并使用 ncurses 将某些内容输出到标准输出,您可以这样做——标准输入和标准输出不需要相互关联——这将允许您将 stdout 的输出传输到其他地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何获取一个程序的输出并将其用作C ++上另一个程序的输入? - How do I take the output of one program and use it as the input of another on C++? 如何从另一个程序运行程序并通过 c 或 c++ 中的 stdin 将数据传递给它? - How do I run a program from another program and pass data to it via stdin in c or c++? 如何在不结束C ++程序的情况下结束ncurses? - How can I end ncurses without ending the C++ program? 如何从C ++程序运行另一个程序 - How do I run another program from a C++ program 如何使用 Windows 程序在 C++ 中获得控制台输出? - How do I get console output in C++ with a Windows program? 如何将结构从非托管C ++程序传递到C#程序? - How do I pass a struct from an unmanaged C++ program to a C# program? 如何将 C 程序的输入传递给在命令行中运行的另一个程序? [等候接听] - How can I pass inputs from my C program to another program running in the command line? [on hold] 如何在 C++ 程序中使用 C 标头? - How do I use C Headers in a C++ Program? 将c ++程序的输出管道输出到另一个程序 - Pipe output of a c++ program to another program 如何在另一个 C++ 程序中使用 preprocessed.i 文件? - How to use a preprocessed .i file in another C++ program?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM