简体   繁体   中英

c++ cross-platform console application, how to accept runtime commands from user input?

Is there a way to accept user input at runtime for console applications?

I have a console application outputs a lot information when it is running, I want to change some parameters of the application at runtime without interruping it. I was wondering weather the cmd window can be of an input source for user to type certain pre-defined commands to do that.

For example, if I type "threshold = 10", it will change the parameter's value.

I've googled a lot but couldn't find anything related to my question.

Best

EDIT:

I understand there must be another thread hanlding the input commands and send back to execute them. I was wondering weather there are cross-platform libs for this job.

Think of a chat box, user can type commands at the bottom half of the window, and the application's output messages are at the upper half. This might change the layout of the output window, is it possible?

EDIT:

In case of anyone still interested in doing this, I found a perfect lib for this task:

A cross-platform header only C++14 library for interactive command line interfaces (Cisco style) https://github.com/daniele77/cli

Let's say you have a while loop where the main commands are running. You can pause it with detecting a keypress, like GetAsyncKeyState() and then allow user to enter some commands as text. You can get them with std::cin or scanf() then parse them with std::string functions such as substr find replace . Then you can use system(string.c_str()); , These calls needs to be used with const chars as I recall. I guess it'll do the trick. Or if you want the console to run silently, you can use WinExec(string.c_str(),SW_HIDE); . This is deprecated but still does wonders. If you want to change the value of a variable at runtime, you can map it inside a std::map , for example by using some map<string,int> you can reach variables at runtime.

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());

Hope this gives an idea, good luck

I am assuming you are in a windows environment based on the term "console" you are using so I am going to use Windows-specific constructs for threads here.

Using user4581301 's comment as a reference, it could be done by putting std::getline in a loop on another thread. For example:

#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;
}

Is this kludgy? Maybe... The biggest issue is how do you quit that thread gracefully? Maybe you could interrupt the std::getline somehow? Then you could close the thread properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM