#c #cs50 #luhn
#c #cs50 #луна
Вопрос:
Я создал некоторый код для имитации алгоритма Луна для проверки действительности кредитных карт. Он успешно распознает карты American Express (15-значные номера, начинающиеся с 34
или 37
), но когда я пытаюсь использовать Mastercard (16 цифр, начинающихся с 51
, 52
, 53
, 54
, или 55
), он их не распознает. Карты Visa имеют 13 или 16 цифр и начинаются с цифры 4
, мой код, похоже, правильно идентифицирует 16-значные регистры, но не 13-значные. Я просмотрел свой код и дважды проверил свои числовые диапазоны, и, похоже, я не могу точно определить, почему некоторые карты проходят, а другие нет. Любая помощь будет с благодарностью.
Редактировать:
Я почти исправил проблему, я изменил ее, и теперь все номера карт проверяются, но теперь он распознает недопустимый номер ( 4111111111111113
) как Visa. Вот мой обновленный код:
#include <math.h>
#include <cs50.h>
#include <stdio.h>
long long number;
int main(void)
{
long long i = 0;
long long b;
long long m = 10;
long long n = 1;
number = get_long_long("Number?n");
do
{
long long a = number % m;
b = number - a;
long long c = b % (m * 10);
long long d = c / m;
long long e = d * 2;
if (e < 9)
{
i = i e;
}
else
{
i = i (e - 10 1);
}
{
m = m * 100;
}
}
while (b > 0);
do
{
long long a = number % n;
b = number - a;
long long c = b % (n * 10);
long long d = c / n;
long long e = d;
if (e < 9)
{
i = i e;
}
else
{
i = i (e - 10 1);
}
{
n = n * 100;
}
}
while (b > 0);
int f = i % 10;
if (((f == 0) amp;amp; (number > 339999999999999) amp;amp; (number < 350000000000000)) || ((number > 369999999999999) amp;amp; (number < 380000000000000)))
{
printf("AMEXn");
}
else
if ((f == 0) amp;amp; (number > 5099999999999999) amp;amp; (number < 5600000000000000))
{
printf("MASTERCARDn");
}
else
if (((f == 0) amp;amp; ((number > 3999999999999) amp;amp; (number < 5000000000000))) || ((number > 3999999999999999) amp;amp; (number < 5000000000000000)))
{
printf("VISAn");
}
else
{
printf("INVALIDn");
}
}
Комментарии:
1. Возможно, я что-то здесь упускаю, но где / как это только удваивает каждую вторую цифру?
2. @EdmCoff Я использую m и n в качестве входных данных для операторов модуля, которые увеличиваются на * 100 на каждой итерации. Имеет ли это смысл?
3. Спасибо. Я пропустил это. Почему оба цикла удваивают цифру? (Я предполагаю, что ваш второй цикл не должен удваивать цифры). Кроме того, вы уверены, что можно начинать отсчет вторых цифр с конца номера? (например, для четного числа цифр, например, 123456, я предполагаю, что вы хотите удвоить 2/4/6, а не 5/3/1)
4. @EdmCoff Ваше наблюдение было точным — я не знаю, почему я удвоил цифру дважды. Я изменил это, и теперь он распознает все карты — однако он по-прежнему распознает недопустимую последовательность (411111111111111113) как Visa.
5. Я вижу, что вы исправили проблему с удвоением, но я не вижу изменений для учета начала с конца числа.
Ответ №1:
Я вижу, что у вас возникли проблемы при попытке проверить длину некоторых карт. Чтобы исправить это, используйте функцию, которая автоматически проверяет длину long . Вы можете использовать некоторую логику с функцией для правильного определения длины визы.
Вот функция для проверки длины длинной переменной.
int get_long_len(long value)
{
int l = 1;
while (value > 9)
{
l ;
value /= 10;
}
return l;
}
Он принимает значение long и возвращает длину.
Комментарии:
1. Сначала я был смущен тем, что вы имели в виду под «длиной длинной». Из чтения, я думаю, вы имеете в виду «количество десятичных цифр, если значение было напечатано с основанием 10». Это верно?
2. @jwd Нет в C есть переменный тип с именем long, который в основном представляет собой число, которое может содержать больше цифр. Целое число может доходить только до, я думаю, где-то около 2-3 миллионов, в то время как длинная переменная может позволить вам назначать гораздо большие числа. По сути, я говорю о «длине числовой переменной с именем long», поскольку номера кредитных карт очень длинные, было бы лучше присвоить ему значение long, потому что иногда int может его не принять.
3. Я понимаю, что тип
long
, который обычно равен 64 битам, а не 32int
. Но это двоичные числа. Их «длина» — это количество битов (по крайней мере, на мой взгляд). Но я думаю, что здесь вы говорите о «длине», как если бы они были напечатаны как «12345 …»?4. Да, я говорю о длине, так как при подсчете цифр, например, длина 096, будет равна 3. Не двоичные цифры, а просто подсчет того, что вы видите с помощью C в вашей IDE.