Может кто-нибудь объяснить, почему мой алгоритм lun терпит неудачу?

#c #if-statement #cs50

#c #if-оператор #cs50

Вопрос:

 #include <math.h>
#include <stdio.h>
#include <stdbool.h>
#include <cs50.h>

short unsigned int numlen(unsigned long long n);
bool isValidCC(unsigned long long int n);
unsigned short int first_n_nums(unsigned short int n, unsigned short int x);


int main(void) 
{
    unsigned long long num = 0;
    num = get_long("Enter your card number ");
    
    if(numlen(num) == 15 amp;amp; (first_n_nums(num, 2) == 34 || first_n_nums(num, 2) == 37) amp;amp; isValidCC(num) == true)
    {
        printf("AMEXn");
    }
    else if((numlen(num) == 13 || numlen(num) == 16)  amp;amp; first_n_nums(num, 1) == 4 amp;amp; isValidCC(num) == true)
    {
        printf("VISAn");
    }
    else if(numlen(num) == 16 amp;amp; (first_n_nums(num, 2) == 51 || first_n_nums(num, 2) == 52 || first_n_nums(num, 2) == 53 || first_n_nums(num, 2) == 54 || first_n_nums(num, 2) == 55)  amp;amp; isValidCC(num) == true)
    {
        printf("MASTERCARDn");
    }
    else
    {
        printf("INVALIDn");
    }

    
}

unsigned short int first_n_nums(unsigned short int n, unsigned short int x)
{
    while(n > pow(10,x))
    {
        n /= 10;
    }
    return n;
}    
    
   

short unsigned int numlen(unsigned long long n)
{
    short unsigned int count = 0;
    while (n !=0)
    {
        n /= 10;  //removes last digit
        count  ; //counts the num of digits removed
    }
    return count;
}

bool isValidCC(unsigned long long int n)
{

    // take user input and add elements to array in reverse
     int arr1[(numlen(n))]; // declares but can't Initialize an array of n ;
     
     for (int i = 0; i < (int)sizeof(arr1)/sizeof(int) ; i  )
    {
        arr1[i] = 0;
    }
    
    for (int i = 0 ; i <(int) (sizeof(arr1)/sizeof(int)) ; i  )
    {
        arr1[i] = n % 10; //Appends last digit to an array
        n /= 10; // removes that last digit
    }
    
    
    // since arr1 = x digits long, arr2 is every second digit so its x/2 long 
     int arr2[((sizeof(arr1)/sizeof(int))*2)];
    
    //initializing garbage data to 0
    for (int i = 0; i < sizeof(arr2)/sizeof(int) ; i  )
    {
        arr2[i] = 0;
    }
    
    // multiplies, seperates, and sums arr2 elements
    int sum_of_arr2 = 0;
    for (int i = 1,  a = 0,  b = 0 ; i < (sizeof(arr1)/sizeof(int)) ; i  = 2) // sizeof(array) = n of elements * sizeof(type of n)
    {
        a = arr1[i] * 2;
        if( a > 9)
        {
            b = a % 10;
            a /= 10;
            arr2[i] = b;
            sum_of_arr2  = b;
        }
        arr2[i-1] = a; // cz i currenrly is one idex ahead
        sum_of_arr2  = a;
    }
    
    // adds other elements of arr1 to sum_of_arr2
    for (int i = 0 ; i < (sizeof(arr1)/4) ; i  = 2) // sizeof(array) = n of elements * sizeof(type of n)
    {
        sum_of_arr2  = arr1[i];
    }
    
    // returns true or false
    if (sum_of_arr2 % 10 != 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}
  

Может кто-нибудь, пожалуйста, объяснить, почему это не удается для таких значений, как:

371449635398431 — ожидаемый «AMEX n», а не «НЕДЕЙСТВИТЕЛЬНЫЙ n»

5555555555554444 — ожидаемый «MASTERCARD n», а не «НЕДЕЙСТВИТЕЛЬНЫЙ n»

5105105105105100 — ожидается «MASTERCARD n», а не «VISA n»

4111111111111111 — ожидаемый «VISA n», а не «НЕДЕЙСТВИТЕЛЬНЫЙ n»

4222222222222 — ожидаемый «VISA n», а не «НЕДЕЙСТВИТЕЛЬНЫЙ n»

Комментарии:

1. Нам нужно посмотреть, что first_n_nums , isValidCC , и numlen помочь. Этот код как есть не будет компилироваться, поэтому мы не можем даже сделать хорошее предположение. Я бы открыл отладчик и посмотрел, что возвращается для каждой функции, чтобы каждая функция выполняла то, что вы ожидаете…

2. Вместо того, чтобы допускать неточности FP, перейдите while(n > pow(10,x)) к решению на основе целых чисел.

3. Вы не должны использовать плавающую точку для всего этого. На самом деле, вам, вероятно, не следует использовать целые числа. Строки будут предоставлять более общее представление, на которое не распространяются ограничения по длине.

4. Вы могли бы return (sum_of_arr2 % 10 == 0); точно так же, что ваше обнуление массива бесполезно, потому что вы все равно будете заполнять каждую цифру…

5. Сегодня хороший день, чтобы научиться пользоваться отладчиком. Каждый день — хорошее время, чтобы научиться пользоваться отладчиком. Это также хороший день для изучения концепции модульных тестов. Вы first_n_nums делаете то, что вы хотите, чтобы он делал?

Ответ №1:

Ваша проблема в вашей функции

     unsigned short int first_n_nums(unsigned short int n, unsigned short int x)
  

Вы передаете unsigned short int вместо unsigned long long , так что вы можете просто получить максимальное значение unsigned short int вместо реального значения.

Вывод:

     371449635398431 - "AMEXn"

    5555555555554444 - "MASTERCARDn"

    5105105105105100- "MASTERCARDn"

    4111111111111111 - "INVALIDn" - Note that the output you said you were expecting is incorrect because the input length is 14 instead of 13.

    4222222222222 - "VISAn"