【问题标题】:How to arrange the loops to check for numbers如何安排循环以检查数字
【发布时间】:2014-04-25 20:54:58
【问题描述】:

我有一个读取信用卡号的程序。我想添加一些东西,以确保添加了 16 个数字,没有字母,以及任意数量的空格(尽管它们不计入数字)。是否有一个函数或一组函数可以做到这一点,或者我应该只做一堆使用 isdigit() 和 isalpha() 的 while 和 if 循环,一次通过数组一个元素?

char cardNum[32];
cout << "Enter credit card number: ";
cin.getline(cardNum, 32); //Read in the entire line for the name

【问题讨论】:

  • 如果你想那样做,你就不需要一堆while循环。一个while循环就足够了。但是有一个更好的方法来做你想做的事,看看regular expressions

标签: c++ cstring ctype


【解决方案1】:

您可以做很多事情。一种想法是将std::find_if 与自定义谓词一起使用。例如:

bool IsCharIllegal(char ch)
{
  // return true or false based on whatever your exact requirements are
}

然后:

auto itFound = std::find_if(cardNum, cardNum + 32, IsCharIllegal);
if(itFound != cardNum + 32)
   // invalid character was entered!

也有使用std::string 代替原始char 数组的情况:

std::string cardNum;
cout << "Enter credit card number: ";
std::cin >> cardNum;

接着是:

auto itFound = std::find_if(cardNum.begin(), cardNum.end(), IsCharIllegal);
if(itFound != cardNum.end())
   // invalid character was entered!

这有助于避免魔法32,并且还允许输入任意长度。

【讨论】:

    【解决方案2】:

    我会使用正则表达式来匹配这个模式。如果您使用的是 C++11,则可以使用内置标头:http://www.cplusplus.com/reference/regex/

    否则,请在此处查看您可以使用的一些替代库:C++: what regex library should I use?

    不幸的是,我不太擅长正则表达式,但是下面应该匹配 16 个数字,中间有空格。

    (\d[ ]*){16}
    

    如果您正在寻找有关正则表达式的更多信息,这里有一个我经常使用的很好的备忘单:http://regexlib.com/CheatSheet.aspx

    我也喜欢用这个网站测试我的表达方式:http://regexpal.com/

    【讨论】:

    • 现在我们有两个问题。
    • 更新了更好的表达方式
    【解决方案3】:

    那么这样的事情会被允许吗?

    "123  456  789 01     23456"
    

    使用std::string 和独立的std::getline 函数。比同名的成员函数要好,因为它不会强迫你处理指针。

    std::string line;
    std::getline(std::cin, line);
    if (!std::cin)
    {
      // catastrophic input failure
    }
    

    然后你有一个字符串,如我上面的例子中的line。您可以使用std::find_if 来验证没有非法字符,并使用std::count_if 来确保正好有 16 位数字,但我认为编写自己的循环(而不是“一堆循环”)会在这里产生更具可读性的代码。

    顺便说一句,提防isdigit由于历史原因,您必须将其参数转换为unsigned char才能安全使用它。

    【讨论】:

      【解决方案4】:

      cstdlib 中有一个atoll 函数。 http://www.cplusplus.com/reference/cstdlib/atoll/

      它将字符串输入转换为long long,它可以存储一个16位长的信用卡号,但是一旦输入中有一个非数字字符就会退出所以

      atoll("123456abc890")
      

      会返回123456

      如果你想逐个字符地检查每个字符,你可以在每个字符上使用atoi,然后为每个通过的字符重新组合字符串。 http://www.cplusplus.com/reference/cstdlib/atoi/

      【讨论】:

      • atoi 坏了。它将为“0”和“x”返回 0。
      • @ChristianHackl 我猜你看不懂文档。 “如果 str 中的第一个非空白字符序列不是有效整数,或者由于 str 为空或仅包含空白字符而不存在此类序列,则不执行转换并返回零。”
      • "x" 是字符串中的“第一个非空白字符序列”。这与我的评论有何矛盾?它支持它。你真的不应该这样冒犯别人。
      • 顺便说一句,你应该引用你引用的东西。这是您的报价来源:cplusplus.com/reference/cstdlib/atoi
      猜你喜欢
      • 2015-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      相关资源
      最近更新 更多