草庐IT

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

coder 2023-11-15 原文

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

#include<iostream>
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<std::streamsize>::max(),\
                                                    '\n');
        }
    }while(true);
    return 0;
}

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

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

我想补充一点,尽管我不是刚开始编写C++代码,但还是刚开始编写符合标准的代码。我正在尝试学习不良做法并学习正确的做法。如果回答者给出详细的解释,我将非常有义务。

编辑:我看到litb回答了我以前的编辑之一。我将在此处发布该代码以供引用。
#include<iostream>
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<std::streamsize>::max(),\
                                                    '\n');
        }
        else
        {
            inputCompletionFlag = false;
        }
    }while(!inputCompletionFlag);
    return 0;
}

该代码在输入“1asdsdf”时失败。我不知道该如何解决,但是litb发布了一个不错的答案。 :)

最佳答案

这是您可以用来确保您也拒绝类似的代码

42crap

数字后面是非数字字符。如果您读了整行然后解析并适本地执行操作,则可能需要您更改程序的工作方式。如果您的程序到现在为止都是从其他地方读取您的电话号码,那么您必须将一个中央位置放在解析一行输入的内容上,然后决定要执行的操作。但这也许也是一件好事-因此,您可以通过将内容分开来提高代码的可读性: I nput- P 处理- O utput

无论如何,这是您如何拒绝上述数字为非数字的方法。将一行读取为字符串,然后使用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位,然后我们进行检查。如果它首先无法读取任何整数,则将设置失败或错误位。

此答案的早期版本直接使用std::cin-但是std::ws与与连接到终端的std::cin一起使用时效果不佳(它会阻止用户等待输入内容),因此我们使用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,具有错误检查功能以及与其他库(例如hex)一起工作的能力。

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

答案:通常,您在这里不需要过多地关注开销(如果您是指运行时开销)。但这具体取决于您在哪里使用该类。如果您要编写一个高性能的系统来处理输入并需要始终保持较高水平,那么这个问题将非常重要。但是,如果您需要从终端或文件中读取输入,那么您已经知道这可以归结为:WAITING用户输入某些内容确实花费了很长时间,因此您现在就不必再为此花费时间了。规模。

如果您指的是代码开销,那么这取决于代码的实现方式。您将需要扫描读取的字符串-它是否包含数字,是否包含任意字符串。根据您要扫描的内容(也许还有“日期”输入或“时间”输入格式。为此,请查看boost.date_time),您的代码可能会变得任意复杂。对于简单的事情,例如是否在数字之间进行分类,我认为您可以省去少量的代码。

关于c++ - 使用cin在C++中进行输入验证的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/545907/

有关c++ - 使用cin在C++中进行输入验证的最佳方法是什么?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  9. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  10. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

随机推荐