【问题标题】:c++ cross-platform console application, how to accept runtime commands from user input?c++ 跨平台控制台应用程序,如何接受来自用户输入的运行时命令?
【发布时间】:2020-08-17 23:16:33
【问题描述】:

有没有办法在控制台应用程序运行时接受用户输入?

我有一个控制台应用程序在运行时会输出很多信息,我想在运行时更改应用程序的一些参数而不中断它。我想知道 cmd 窗口是否可以成为用户输入某些预定义命令的输入源。

例如,如果我输入“threshold = 10”,它会改变参数的值。

我搜索了很多,但找不到与我的问题相关的任何内容。

最好的

编辑:

我知道必须有另一个线程处理输入命令并发送回执行它们。我想知道这项工作是否有跨平台库。

想象一个聊天框,用户可以在窗口的下半部分输入命令,而应用程序的输出消息在上半部分。这可能会改变输出窗口的布局,有可能吗?

编辑:

如果有人仍然对此感兴趣,我为这项任务找到了一个完美的库:

用于交互式命令行界面(Cisco 风格)的跨平台标头 C++14 库https://github.com/daniele77/cli

【问题讨论】:

  • 是的。听起来您需要一个解析器,可能还需要另一个线程来监控输入,同时仍在处理。
  • 您希望获得哪种特定语言的答案? C 和 C++ 非常不同

标签: c++ terminal console-application cross-platform


【解决方案1】:

假设您有一个运行主要命令的 while 循环。您可以通过检测按键来暂停它,例如GetAsyncKeyState(),然后允许用户以文本形式输入一些命令。您可以使用std::cinscanf() 获取它们,然后使用std::string 函数解析它们,例如substr find replace。然后你可以使用system(string.c_str());,我记得这些调用需要与 const chars 一起使用。我想它会成功的。或者,如果您希望控制台静默运行,您可以使用WinExec(string.c_str(),SW_HIDE);。这已被弃用,但仍然可以创造奇迹。如果您想在运行时更改变量的值,可以将其映射到 std::map 中,例如使用一些 map<string,int> 可以在运行时访问变量。

std::map<std::string,int> mymap;
mymap["playerhealth"]=20;
while(1)
{
    //...
    if(...) break;
}
std::string string;
std::cout<<"Enter command: ";
std::cin>>string;
std::string vartobechanged=string.substr(0,string.find("="));
mymap[vartobechanged]=atoi(string.substr(string.find("=")+1,string.length()-string.find("=")-1).c_str());

希望这能给你一个想法,祝​​你好运

【讨论】:

  • 这不是一个坏主意——您甚至可以使用SetWindowsHookEx 来捕捉按键并以这种方式做出反应。
  • 谢谢,我认为你是对的,但我一直在为此寻找跨平台库,因为它通常应该是一个框架。
【解决方案2】:

我假设您处于基于您使用的术语“控制台”的 Windows 环境中,因此我将在此处为线程使用特定于 Windows 的构造。

使用 user4581301 的评论作为参考,可以通过将std::getline 放入另一个线程的循环中来完成。例如:

#include <windows.h>
#include <iostream>
#include <string>

std::string somevar = "initial value";
HANDLE hMutex = NULL;

DWORD CALLBACK ReadFromStdIn(LPVOID param){
    while (true) {
        std::string line;
        std::getline(std::cin, line);

        WaitForSingleObject(hMutex, INFINITE);
        somevar = line;
        ReleaseMutex(hMutex);
    }
}

int main()
{
    hMutex = CreateMutex(NULL, FALSE, NULL);
    HANDLE hThread = CreateThread(NULL, 0, ReadFromStdIn, NULL, 0, NULL);

    for (int i = 0; i < 1000; ++i) {

        WaitForSingleObject(hMutex, INFINITE);
        std::cout << somevar << " " << i << std::endl;
        ReleaseMutex(hMutex);

        Sleep(1000);
    }

    // TODO: somehow cancel the readline on stdin

    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);

    WaitForSingleObject(hMutex, INFINITE);
    CloseHandle(hMutex);

    return 0;
}

这是笨拙的吗?也许......最大的问题是你如何优雅地退出那个线程?也许您可以以某种方式中断std::getline?然后就可以正常关闭线程了。

【讨论】:

  • 这是个好主意,cin, cout 安全吗?在一般设计中,日志模块可能由第三方库处理,我可能需要稍微修改一下。
猜你喜欢
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多