为什么这个 C++基于 Luhn 算法检查信用卡的代码行不通?

发布于 2025-01-09 10:06:48 字数 1226 浏览 4 评论 0原文

我编写此代码是为了根据 Luhn 算法检查信用卡号是否有效:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

bool ccc(string cc) {
  vector<string> digits;
  int aux;
  for (int n = 0; n < cc.length(); ++n) {
    digits.push_back(to_string(cc.at(n)));
    cout << digits[n];
  }
  for (int s = 1; s < digits.size(); s += 2) {
    aux = stoi(digits[s]);
    aux *= 2;
    digits[s] = to_string(aux);
    aux = 0;
    for (int f = 0; f < digits[s].length(); ++f) {
      aux += stoi(to_string(digits[s].at(f)));
    }
    digits[s] = to_string(aux);
    aux = 0;
  }
  for (int b = 0; b < digits.size(); ++b) {
    aux += stoi(digits[b]);
  }
  aux *= 9;
  if (aux % 10 == 0) {
    return true;
  } else {
    return false;
  }
}

int main(int argc, char* argv[]) {
  string crecar;
  cout << "CC:\n";
  cin >> crecar;
  if (ccc(crecar)) {
    cout << "Valid\n";
  } else {
    cout << "Invalid\n";
  }
}

我编译时没有错误或警告,并得到以下输出:

CC:
4895045418823857
52565753485253524956565051565355Invalid

它应该首先打印每个数字,我用它来检查什么是程序内部执行的操作,但我得到的数字太大了。为什么这个程序失败了?我应该做什么来修复它?

I wrote this code in to check if a credit card number is valid according to the Luhn algorithm:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

bool ccc(string cc) {
  vector<string> digits;
  int aux;
  for (int n = 0; n < cc.length(); ++n) {
    digits.push_back(to_string(cc.at(n)));
    cout << digits[n];
  }
  for (int s = 1; s < digits.size(); s += 2) {
    aux = stoi(digits[s]);
    aux *= 2;
    digits[s] = to_string(aux);
    aux = 0;
    for (int f = 0; f < digits[s].length(); ++f) {
      aux += stoi(to_string(digits[s].at(f)));
    }
    digits[s] = to_string(aux);
    aux = 0;
  }
  for (int b = 0; b < digits.size(); ++b) {
    aux += stoi(digits[b]);
  }
  aux *= 9;
  if (aux % 10 == 0) {
    return true;
  } else {
    return false;
  }
}

int main(int argc, char* argv[]) {
  string crecar;
  cout << "CC:\n";
  cin >> crecar;
  if (ccc(crecar)) {
    cout << "Valid\n";
  } else {
    cout << "Invalid\n";
  }
}

And I compile with no errors or warnings and I get the following output:

CC:
4895045418823857
52565753485253524956565051565355Invalid

It should print first every digit of digits, I used that to check what is the program doing internally, but I get that number that is too big. Why is this program failing and what should I do to fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初吻给了烟 2025-01-16 10:06:48

请查阅 to_string 文档(示例)您会发现 char 没有重载,但是 char 很容易转换为 int,因此 int<将使用 /code> 重载。不幸的是你没有得到这个数字。您可以获得字符的编码值。因此,假设 ascii,to_string('4') 不会返回包含 4 的 string,它将返回包含 ascii 的 string值为 4: 52。

如果您将这个奇怪的数字视为 2 位数字的流,您将看到原始数字的 ASCII 表示形式。

52 56 57 53 48 52 53 52 49 56 56 50 51 56 53 55
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 
4  8  9  5  0  4  5  4  1  8  8  2  3  8  5  7 

此问题的破解方法是更改

digits.push_back(to_string(cc.at(n)));

​​为

digits.push_back(string(1,cc.at(n)));

构造一个包含给定字符的 1 个副本的字符串,并将其放置在向量中

立即提高可读性是

digits.push_back(cc.substr(n,1));

获得子 -我们正在查看的当前字符的字符串并将其放入digits中。

但是从stringint再到string的所有这些都是make-work。只需存储 int 并对其进行操作即可。如果您有数字,可以使用 digit -'0' 将数字转换为 int,然后使用 digit + '0' 再次转换回来。这将为您和计算机节省很多精力。

Consult the to_string documentation (example) and you'll see that there is no overload for char, but char is easily convertible to an int, so the int overload will be used. Unfortunately you don't get the digit. You get the character's encoded value. So, assuming ascii, to_string('4') won't return a string containing 4, it'll return a string containing the ascii value of 4: 52.

If you look at the strange number as a stream of 2 digit numbers you'll see you have an ascii representation of your original number.

52 56 57 53 48 52 53 52 49 56 56 50 51 56 53 55
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 
4  8  9  5  0  4  5  4  1  8  8  2  3  8  5  7 

The hack fix for this problem is to change

digits.push_back(to_string(cc.at(n)));

to

digits.push_back(string(1,cc.at(n)));

construct a string that contains 1 copy of the given character and place it in the vector

An immediate readability improvement is

digits.push_back(cc.substr(n,1));

get a sub-string of the current character we're looking at and put it in digits.

But all this to string to int back to string is make-work. Just store ints and operate on ints . If you have digits you can convert digit into an int with digit -'0' and back again with digit + '0'. This will save you and the the computer a lot of effort.

梦毁影碎の 2025-01-16 10:06:48

我不知道为什么你的代码这么长。根据有关算法的维基百科页面:

function checkLuhn(string purportedCC) {
    int nDigits := length(purportedCC)
    int sum := integer(purportedCC[nDigits-1])
    int parity := (nDigits-2) modulus 2
    for i from 0 to nDigits - 2 {
        int digit := integer(purportedCC[i])
        if i modulus 2 = parity
            digit := digit × 2
        if digit > 9
            digit := digit - 9 
        sum := sum + digit
    }
    return (sum modulus 10) = 0
}

我不知道你从什么开始,但你的看起来真的很奇怪。

I'm not sure why your code is so long. According to the wikipedia page on the algorithm in question:

function checkLuhn(string purportedCC) {
    int nDigits := length(purportedCC)
    int sum := integer(purportedCC[nDigits-1])
    int parity := (nDigits-2) modulus 2
    for i from 0 to nDigits - 2 {
        int digit := integer(purportedCC[i])
        if i modulus 2 = parity
            digit := digit × 2
        if digit > 9
            digit := digit - 9 
        sum := sum + digit
    }
    return (sum modulus 10) = 0
}

I don't know what you started with, but yours just seems really weird.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文