当前位置:  开发笔记 > 编程语言 > 正文

使用cin在C++中进行输入验证的最佳方法是什么?

如何解决《使用cin在C++中进行输入验证的最佳方法是什么?》经验,为你挑选了2个好方法。

我哥哥最近开始学习C++.他告诉我在尝试在简单程序中验证输入时遇到的问题.他有一个文本菜单,用户输入一个整数choice,如果他们输入了无效的选项,他们会被要求再次输入(循环时).但是,如果用户输入的是字符串而不是int,则代码会中断.我在stackoverflow上阅读了各种问题,并告诉他重写他的代码:

#include
using namespace std;

int main()
{
    int a;
    do
    {
    cout<<"\nEnter a number:"
    cin>>a;
        if(cin.fail())
        {
            //Clear the fail state.
            cin.clear();
            //Ignore the rest of the wrong user input, till the end of the line.
            cin.ignore(std::numeric_limits::max(),\
                                                    '\n');
        }
    }while(true);
    return 0;
}

虽然这个工作正常,但我还尝试了其他一些想法:
1.使用try catch块.它没用.我认为这是因为输入错误不会引发异常.我试过if(! cin){//Do Something}哪个也没用.我还没想出来.
3.第三,我尝试输入一个固定长度的字符串然后解析它.我会用atoi().这个标准是否合规且便携?我应该编写自己的解析函数吗?
4.如果编写一个使用cin的类,但动态地进行这种错误检测,也许通过在运行时确定输入变量的类型,它会有太多的开销吗?它甚至可能吗?

我想知道进行这种检查的最佳方法是什么,最佳做法是什么?

我想补充一点,虽然我不是新编写C++代码,但我是编写符合标准的良好代码的新手.我试图忘掉不良做法并学习正确的做法.如果回答者提供详细解释,我将非常感激.

编辑:我看到litb回答了我以前的一个编辑.我会在这里发布该代码以供参考.

#include
using namespace std;

int main()
{
    int a;
    bool inputCompletionFlag = true;
    do
    {
    cout<<"\nEnter a number:"
    cin>>a;
        if(cin.fail())
        {
            //Clear the fail state.
            cin.clear();
            //Ignore the rest of the wrong user input, till the end of the line.
            cin.ignore(std::numeric_limits::max(),\
                                                    '\n');
        }
        else
        {
            inputCompletionFlag = false;
        }
    }while(!inputCompletionFlag);
    return 0;
}

此代码在输入失败,如"1asdsdf".我不知道如何修复它,但litb发布了一个很好的答案.:)



1> Johannes Sch..:

这是您可以使用的代码,以确保您也拒绝这样的事情

42crap

其中非数字字符跟随数字.如果您阅读整行,然后解析它并适当地执行操作,则可能需要您更改程序的工作方式.如果您的程序从不同的地方读取您的号码,那么您必须放置一个解析一行输入的中心位置,并决定该操作.但也许这是一件好事-这样你就可以通过分离有东西增加代码的可读性这样: NPUT - P rocessing - Ø本安输出

无论如何,这里是你如何拒绝上面的数字 - 非数字.将一行读入一个字符串,然后用stringstream:解析它:

std::string getline() {
  std::string str;
  std::getline(std::cin, str);
  return str;
}

int choice;
std::istringstream iss(getline());
iss >> choice >> std::ws;
if(iss.fail() || !iss.eof()) {
  // handle failure
}

它吃掉所有尾随的空白.当它在读取整数或尾随空格时命中字符串流的文件结尾时,它会设置eof-bit,然后检查它.如果它首先无法读取任何整数,那么将设​​置失败或坏位.

这个答案的早期版本std::cin直接使用- 但连接到终端std::ws时不能很好地工作std::cin(它会阻塞而不是等待用户输入内容),所以我们用a stringstream来读取整数.


回答你的一些问题:

问题: 1.使用try catch块.它没用.我认为这是因为输入错误不会引发异常.

答:嗯,你可以告诉流你在读东西时抛出异常.您可以使用该istream::exceptions函数来确定要抛出异常的错误类型:

iss.exceptions(ios_base::failbit);

我从来没用过它.如果你这样做std::cin,你将不得不记住恢复依赖它而不是投掷的其他读者的标志.找到方法更容易使用函数失败,不好要求流的状态.

问题: 2.我试过if(!cin){ //Do Something }哪个也没用.我还没想出来.

答:这可能来自于你给它类似"42crap"的事实.对于流,在提取整数时,这是完全有效的输入.

问题: 3.第三,我尝试输入固定长度的字符串然后解析它.我会用atoi().这个标准是否合规且便携?我应该编写自己的解析函数吗?

答: atoi符合标准.但是当你想要检查错误时,它并不好.没有错误检查,由它完成,而不是其他功能.如果你有一个字符串,并想检查它是否包含一个数字,那么就像在上面的初始代码中那样做.

有类似C的函数可以直接从C字符串中读取.它们的存在是为了允许与旧的遗留代码进行交互并编写快速执行的代码.人们应该在程序中避免它们,因为它们的工作水平较低,需要使用原始的裸指针.就其本质而言,它们无法增强以使用用户定义的类型.具体来说,这谈到了函数"strtol"(字符串到长),它基本上是atoi,具有错误检查和与其他基础(例如十六进制)一起工作的能力.

问题: 4.如果我编写了一个使用cin的类,但是动态地执行这种错误检测,也许通过在运行时确定输入变量的类型,它会有太多的开销吗?它甚至可能吗?

答:通常,您不需要过多关注开销(如果您的意思是运行时开销).但它具体取决于您使用该类的位置.如果您正在编写一个处理输入并且需要高整数的高性能系统,那么这个问题将非常重要.但是如果你需要从终端或文件中读取输入,你已经看到了这一点:等待用户输入的东西需要很长时间,你现在不需要再看这个时候的运行时成本规模.

如果你的意思是代码开销 - 那么它取决于代码的实现方式.您需要扫描您读取的字符串 - 是否包含数字,是否包含任意字符串.根据您要扫描的内容(也许您有"日期"输入或"时间"输入格式.请查看boost.date_time),您的代码可能会变得任意复杂.对于简单的事情,比如在数字与否之间进行分类,我认为你可以通过少量的代码来逃避.



2> paxdiablo..:

这就是我用C做的,但它也可能适用于C++.

将所有内容输入为字符串.

然后,只有这样,才能将字符串解析为您需要的字符串.有时候自己编码比尝试根据自己的意愿弯曲别人更好.

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有