cin 缓冲区有一些烦人的问题
Having some annoying issues with the cin buffer
这是我的代码。基本上,我主要是将用户传递给这个选择器菜单。当用户做出选择时,我将传回 main,然后将它们传递给适当的 class 以执行进一步的功能。
例如,当用户选择 "send" 时,它们被传递给 main,然后传递给一个函数,该函数收集有关发送到哪里的输入。然后回到 main,然后回到一个询问他们多少钱的函数。第一次使用时效果很好。
问题是,如果他们尝试发送另一笔交易,它会自动用之前输入的金额填充地址。用户必须自己从控制台行删除它。基本上,金额会卡在 cin 缓冲区中并自动填充变量。我试过使用getline,它有同样的问题。我可以使用 cin.clear() 和 cin.ignore(1000,'\n') 使用一个小函数来清除 cin 缓冲区,它解决了我的问题,但是用户必须额外输入一次输入后
我已将问题隔离到菜单上。当我从我的程序中排除菜单时,问题就消失了。菜单还在制作中,我知道它不够漂亮或精致。我不明白为什么要这样做。请帮忙,我要扯掉我的头发了。
此外,问题不在代码的 if(refresh){...} 部分,我已经尝试排除它,但问题仍然存在。
菜单头文件只有一些私有变量和向量声明。我很乐意根据要求 post 额外代码。
menu.cpp
#include "menu.h"
#include "KMD_COMMANDS.h"
#include <windows.h>
std::string menu::userInterface()
{
KMD_COMMANDS displayInfo;
bool selecting = true; //
refresh = true; //
numRight = 3; //reset variables back to default
options = oDWB; // < string vector
system("cls");
hideCursor();
while(selecting)
{
numLeft = 3 - numRight; //sets the number of left movements available
if(refresh) //only refresh the screen when user makes an input. I plan to use a console vector updating method in the future instead of "cls"... I know "cls" sucks
{
system("cls");
std::cout << "Balance: ";
displayInfo.getBalance();
std::cout<<std::endl;
std::cout << "Public Address: ";
displayInfo.getPubKey();
std::cout<<std::endl;
for(int i = 0; i < options.size(); i++)
{
std::cout << options[i];
}
refresh = false; //refresh is done
}
Sleep(100); //this makes a delay so inputs are less sensitive
if(GetAsyncKeyState(VK_RIGHT))
{
refresh = true; //reset refresh variable so console updates
switch(numRight) //moves the selector around
{
case 1:
numRight--;
options = optionsDefault; //sets the options selector
options[12] = "["; //back to default state
options[14] = "]"; //and moves brackets
break;
case 2:
numRight--;
options = optionsDefault;
options[8] = "[";
options[10] = "]";
break;
case 3:
numRight--;
options = optionsDefault;
options[4] = "[";
options[6] = "]";
break;
default:
break;
}
}
if(GetAsyncKeyState(VK_LEFT)) //moves the selector around
{
refresh = true;
switch(numLeft)
{
case 1:
numRight++;
options = optionsDefault;
options[0] = "[";
options[2] = "]";
break;
case 2:
numRight++;
options = optionsDefault;
options[4] = "[";
options[6] = "]";
break;
case 3:
numRight++;
options = optionsDefault;
options[8] = "[";
options[10] = "]";
break;
default:
break;
}
}
if(GetAsyncKeyState(VK_UP)) //takes users selection (changed to up for debugging purposes)
{
switch(numRight) //takes selection choice based from number of right inputs remaining
{
case 1:
userChoice = "send";
return userChoice;
break;
case 2:
userChoice = "unlock";
return userChoice;
break;
case 3:
userChoice = "lock";
return userChoice;
break;
default:
userChoice = "quit";
return userChoice;
break;
}
}
}
}
这里是传递给用户收集信息的地方,cins所在的地方:
#include "confirmSend.h"
#include <iostream>
#include <windows.h>
std::string confirmSend::sendToAddress()
{
Sleep(100); //delay so user doesn't accidentally input twice
bool confirm = false;
std::string addressInput;
while(!confirm)
{
//std::cin.clear();
// std::cin.ignore(1000,'\n');
system("cls");
std::cout << "Type cancel to cancel..." << std::endl;
std::cout<<std::endl;
std::cout << "Enter the address of where to send: ";
std::cin >> addressInput;
Sleep(800);
// std::cout<<std::endl;
confirm = true;
}
return addressInput;
}
int confirmSend::sendAmount()
{
Sleep(100); //delay so user doesn't accidentally input twice
bool confirm = false;
int amount;
while(!confirm)
{
// std::cin.clear();
// std::cin.ignore(1000,'\n');
system("cls");
std::cout << "type 0 to cancel..." << std::endl;
std::cout<<std::endl;
std::cout << "Enter how much to send:" << std::endl;
std::cin >> amount;
std::cout << std::endl;
confirm = true;
}
return amount;
}
每个std::cin输入完后点击"enter",cin缓冲区中会留下一个'\n',需要一些方法来消除它。如果只有 '\n' 或其他,使用 getchar()
作为简单的解决方案。如果'\n'之前的字符较多,可以用getline()
将它们全部消除,直到得到'\n'。
这是我的代码。基本上,我主要是将用户传递给这个选择器菜单。当用户做出选择时,我将传回 main,然后将它们传递给适当的 class 以执行进一步的功能。
例如,当用户选择 "send" 时,它们被传递给 main,然后传递给一个函数,该函数收集有关发送到哪里的输入。然后回到 main,然后回到一个询问他们多少钱的函数。第一次使用时效果很好。
问题是,如果他们尝试发送另一笔交易,它会自动用之前输入的金额填充地址。用户必须自己从控制台行删除它。基本上,金额会卡在 cin 缓冲区中并自动填充变量。我试过使用getline,它有同样的问题。我可以使用 cin.clear() 和 cin.ignore(1000,'\n') 使用一个小函数来清除 cin 缓冲区,它解决了我的问题,但是用户必须额外输入一次输入后
我已将问题隔离到菜单上。当我从我的程序中排除菜单时,问题就消失了。菜单还在制作中,我知道它不够漂亮或精致。我不明白为什么要这样做。请帮忙,我要扯掉我的头发了。
此外,问题不在代码的 if(refresh){...} 部分,我已经尝试排除它,但问题仍然存在。
菜单头文件只有一些私有变量和向量声明。我很乐意根据要求 post 额外代码。
menu.cpp
#include "menu.h"
#include "KMD_COMMANDS.h"
#include <windows.h>
std::string menu::userInterface()
{
KMD_COMMANDS displayInfo;
bool selecting = true; //
refresh = true; //
numRight = 3; //reset variables back to default
options = oDWB; // < string vector
system("cls");
hideCursor();
while(selecting)
{
numLeft = 3 - numRight; //sets the number of left movements available
if(refresh) //only refresh the screen when user makes an input. I plan to use a console vector updating method in the future instead of "cls"... I know "cls" sucks
{
system("cls");
std::cout << "Balance: ";
displayInfo.getBalance();
std::cout<<std::endl;
std::cout << "Public Address: ";
displayInfo.getPubKey();
std::cout<<std::endl;
for(int i = 0; i < options.size(); i++)
{
std::cout << options[i];
}
refresh = false; //refresh is done
}
Sleep(100); //this makes a delay so inputs are less sensitive
if(GetAsyncKeyState(VK_RIGHT))
{
refresh = true; //reset refresh variable so console updates
switch(numRight) //moves the selector around
{
case 1:
numRight--;
options = optionsDefault; //sets the options selector
options[12] = "["; //back to default state
options[14] = "]"; //and moves brackets
break;
case 2:
numRight--;
options = optionsDefault;
options[8] = "[";
options[10] = "]";
break;
case 3:
numRight--;
options = optionsDefault;
options[4] = "[";
options[6] = "]";
break;
default:
break;
}
}
if(GetAsyncKeyState(VK_LEFT)) //moves the selector around
{
refresh = true;
switch(numLeft)
{
case 1:
numRight++;
options = optionsDefault;
options[0] = "[";
options[2] = "]";
break;
case 2:
numRight++;
options = optionsDefault;
options[4] = "[";
options[6] = "]";
break;
case 3:
numRight++;
options = optionsDefault;
options[8] = "[";
options[10] = "]";
break;
default:
break;
}
}
if(GetAsyncKeyState(VK_UP)) //takes users selection (changed to up for debugging purposes)
{
switch(numRight) //takes selection choice based from number of right inputs remaining
{
case 1:
userChoice = "send";
return userChoice;
break;
case 2:
userChoice = "unlock";
return userChoice;
break;
case 3:
userChoice = "lock";
return userChoice;
break;
default:
userChoice = "quit";
return userChoice;
break;
}
}
}
}
这里是传递给用户收集信息的地方,cins所在的地方:
#include "confirmSend.h"
#include <iostream>
#include <windows.h>
std::string confirmSend::sendToAddress()
{
Sleep(100); //delay so user doesn't accidentally input twice
bool confirm = false;
std::string addressInput;
while(!confirm)
{
//std::cin.clear();
// std::cin.ignore(1000,'\n');
system("cls");
std::cout << "Type cancel to cancel..." << std::endl;
std::cout<<std::endl;
std::cout << "Enter the address of where to send: ";
std::cin >> addressInput;
Sleep(800);
// std::cout<<std::endl;
confirm = true;
}
return addressInput;
}
int confirmSend::sendAmount()
{
Sleep(100); //delay so user doesn't accidentally input twice
bool confirm = false;
int amount;
while(!confirm)
{
// std::cin.clear();
// std::cin.ignore(1000,'\n');
system("cls");
std::cout << "type 0 to cancel..." << std::endl;
std::cout<<std::endl;
std::cout << "Enter how much to send:" << std::endl;
std::cin >> amount;
std::cout << std::endl;
confirm = true;
}
return amount;
}
每个std::cin输入完后点击"enter",cin缓冲区中会留下一个'\n',需要一些方法来消除它。如果只有 '\n' 或其他,使用 getchar()
作为简单的解决方案。如果'\n'之前的字符较多,可以用getline()
将它们全部消除,直到得到'\n'。