每次用户按下enter键时程序都会保存,并在调用cin时将程序吐出

问题描述 投票:-2回答:1

这实际上与我提出的另一个问题有关,但我已经缩小了问题并重新编写了程序,以便更清洁,更准确。

主要功能将用户传递到菜单,在菜单中他们可以选择他们想要做的事情。问题是,每次按下返回键时,它似乎都会将输入记录到cin缓冲区中。当用户最终做出选择并被传递给适当的函数时,它会吐出所有输入的键,这会导致它跳过整个过程。这非常烦人,特别是因为我想使用VK_RETURN进行选择。

现在,我可以随处可见一堆cin.clear()和cin.ignore(),但据我所知,这是不好的做法。此外,它与程序混淆,因为它强制用户点击输入键一个额外的时间来下线,并混乱格式化。

有没有解决的办法?或者是cin.clear()和cin.ignore我唯一的希望?

main.cpp中

#include <limits>
#include <iostream>

#include "menu_GUI.h"

int main()
{
    bool running = true;
    std::string selection;  //user selection for selector menu
    std::string address;    //address to send funds to
    int amount;             //amount of funds to send

    std::string password;   //password for wallet encryption

    menu_GUI menu;  //object for menu_GUI class

    while(running)
    {
        selection = menu.mainMenu();    //collect users selection from the menu_GUI class selector function

        if(selection == "send")
        {
            address = menu.askAddress(address);    //collects the address the user wants to send funds to
            if(address != "cancel"){amount = menu.askAmount(amount);}     //collects the amount the user wants to send if they don't cancel
            if(amount != 0){}   //if the amount isn't 0, then it sends the transaction (unfinished, does nothing right now)
        }

        if(selection == "lock")     //unfinished, but will lock the wallet
        {

        }

        if(selection == "unlock")   //unfinished, but will lock the wallet
        {

        }
    }

    return 0;
}

menu_GUI.h

#ifndef MENU_GUI_H
#define MENU_GUI_H

#include <vector>
#include <string>

class menu_GUI
{
    public:

        std::string mainMenu();
        std::string askAddress(std::string address);
        int askAmount(int amount);
        void moveCursor(int x, int y);
        void hideCursor();

    private:

        std::vector<std::string> UI {"[Send] ", "Lock ", "Unlock"};
        int rightMoves = 2;
        int leftMoves;
        int inputDelay = 150;   //modify this value to change the delay between user selector movements
        std::string selection;
};

#endif // MENU_GUI_H

menu_GUI.cpp

#include "menu_GUI.h"

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

std::string menu_GUI::mainMenu()
{

    bool selecting = true;

    while(selecting)
    {
        hideCursor();   //hides the cursor

        leftMoves = 2 - rightMoves;     //sets the number of left movements remaining based on right movements remaining

        for(int x = 0, y = 0; x < UI.size(); x++)
        {
            moveCursor(0, 0);
            std::cout << "Balance: ";     //displays users balance
            moveCursor(0, 2);
            std::cout << "Address: ";    //displays users public key

            moveCursor(y, 4);    //prints out the map
            std::cout << UI[x];

            y += UI[x].length();    //sets y equal to the total length accumulated on the line so far
        }

        if(GetAsyncKeyState(VK_RIGHT))      //handles right key inputs
        {
            if(rightMoves != 0)     //check if user can move right
            {
                switch(rightMoves)
                {
                    case 1:
                    rightMoves--;
                    UI[1] = "Lock ";
                    UI[2] = "[Unlock]";
                    break;
                                            //modifies  the UI vector accordingly
                    case 2:
                    rightMoves--;
                    UI[0] = "Send ";
                    UI[1] = "[Lock] ";
                    break;

                    default:
                    break;
                }
            }
            Sleep(inputDelay);     //Delay, so that user doesn't input twice
        }

        if(GetAsyncKeyState(VK_LEFT))      //handles right key inputs
        {
            if(leftMoves != 0)     //check if user can move left
            {
                switch(leftMoves)
                {
                    case 1:
                    rightMoves++;
                    UI[0] = "[Send] ";
                    UI[1] = "Lock ";
                    break;
                                            //modifies  the UI vector accordingly
                    case 2:
                    rightMoves++;
                    UI[1] = "[Lock] ";
                    UI[2] = "Unlock";
                    break;

                    default:
                    break;
                }
            }
            Sleep(inputDelay);     //Delay, so that user doesn't input twice
        }

        if(GetAsyncKeyState(VK_RETURN))      //handles which selection the user chooses based on how many rightMoves remaining
        {
            system("cls");      //clears the screen, since it's about to display a new page

            switch(rightMoves)
            {
                case 2:
                selection = "send";
                return (selection);
                break;

                case 1:
                selection = "lock";
                return (selection);
                break;

                case 0:
                selection = "unlock";
                return (selection);
                break;

                default:
                break;
            }
        }
    }
}

std::string menu_GUI::askAddress(std::string address)   //asks user where they wanna send it
{
    std::cout << "Enter where you wanna send the BigBoiCoins. Or type cancel." << std::endl;
    std::cout << "Address: ";
    getline(std::cin, address);     //shouldn't need to check failbit. user input can be anything.

    return address;
}

int menu_GUI::askAmount(int amount)     //asks user how much they wanna send
{
    bool inputting = true;
    while(inputting)
    {
        std::cout << "Enter how many BigBoiCoins you wanna send. Just put 0 if you don't wanna send any." << std::endl;
        std::cout << "Amount: ";
        std::cin >> amount;

        if(!std::cin)    //checks failbit to make sure user isn't an idiot and inputs something other than a number
        {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "who buckaroo! That wasn't a good input. I'll let you try again, I know some of us are special." << std::endl;
        }
        else{inputting = false;}
    }
    return amount;
}

void menu_GUI::moveCursor(int x, int y)     //move the cursor to the desired coords
{
    static const HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    std::cout.flush();
    COORD coord = { (SHORT)x, (SHORT)y };
    SetConsoleCursorPosition(hOut, coord);
}

void menu_GUI::hideCursor()     //hides the cursor
{
   CONSOLE_CURSOR_INFO info;
   info.dwSize = 100;
   info.bVisible = false;
   SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
}
c++ winapi cin
1个回答
0
投票

你需要添加一些输入函数来“吃掉”一些字符。你最好用if(GetAsyncKeyState(KEY) & 0x8000)代替。

if (GetAsyncKeyState(VK_RETURN)& 0x8000)      //handles which selection the user chooses based on how many rightMoves remaining
        {
            getline(std::cin,NULL);
            //...
        }

std::cin >> amount;
char c = getchar();//eat '\n'
© www.soinside.com 2019 - 2024. All rights reserved.