Made a script on the Luhn's Alg. Unable to understand how to create and call functions clearly for revised script

Viewed 80

I am new to programming. I am currently taking online lectures quite rigorously and completed a task using Luhn's Algorithm. It is just one script that runs straight through, but for my future-self I want to learn to code more efficiently as projects get bigger.

That is where my problem comes in. I cannot seem to understand how to define or call functions correctly and unable to revise my script into something more "efficient".

(Everything is already submitted and my script completes the task perfectly, according to the bot, so I am not trying to half-arse my work here just to be clear.)

This is the completed script with only the main function that runs straight through and took me about 12-15 hours to get it working without error from the beginning. Everything is written in C

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

int main(void)
{
    // this grabs the number and verifies the correct amount of digits
    int count;
    long number = 0;
    do
    {
        number = get_long("Number: ");
        count = (number == 0) ? 1 : (log10(number) + 1);
        if (count < 13 || count == 14 || count > 16)
        {
            printf("INVALID\n"); // This is to satisfy the uni. bot command check. Need a EOF for numbers with the wrong amount of digits.
            return (0);
        }
    }
    while (count < 13 || count == 14 || count > 16);
    //printf("Digits: %i\n", count);       // test print for debugging

    //This finds the first two digits of input number

    long int two = number;
    while (two >= 100)
    {
        two = two / 10;
    }
    //printf("First two numbers: %li\n", two);      // test print for debugging

    // verifies card using mod10 (Luhn's)
    long sum = 0;
    long bigdigit = 0;
    //printf("\nLUHN Number: %li\n\n", number);     // test print for debugging
    if (count == 13 || count == 15)
    {
        count += 1;
    }
    for (int i = count; i > 0; i--)
    {
        if (i % 2 == 0)
        {
            sum += (number % 10);
        }
        else
        {
            bigdigit = (2 * (number % 10));
            sum += (bigdigit / 10 + bigdigit % 10);
        }
        number = (number / 10);
        //printf("\nI : %i\n", i);      // test print for debugging
        //printf("Sum: %li\n", sum);        // test print for debugging
        //printf("Number: %li\n", number);      // test print for debugging
    }
    if (sum % 10 == 0)
    {
        printf("VALID\n");
    }
    else
    {
        printf("INVALID\n");
        return (0);
    }

    // checks what type of card

    if (two == 34 || two == 37)
    {
        printf("AMEX\n");
        return (0);
    }
    else if (two >= 51 && two <= 55)
    {
        printf("MASTERCARD\n");
        return (0);
    }
    else if (two >= 40 && two <= 49)
    {
        printf("VISA\n");
        return (0);
    }
    else
    {
        printf("INVALID\n");
        return (0);
    }
}

I was trying to split it into 3 functions of main to call.

  • long input_number();
  • bool luhn_check();
  • void company_check();

I am stuck with the second function and not sure if the third should be a void or not.


"Revised" Script v2

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

long input_number(long CCN);
int counter(long CCN, int count);
bool luhn_check(long CCN, int count);
long firsttwo(long CCN, long two);
void card_type(long two);


int main()
{
    long CCN = 0;
    int count = 0;
    long two = 0;
    CCN = input_number(CCN);
    count = counter(CCN, count);

    //printf("CCN: %li\n", CCN); //debugging purposes
    //printf("Digits: %i\n", count); //debugging purposes
    luhn_check(CCN, count);
    two = firsttwo(CCN, two);
    //printf("First Two: %li\n", two); //debugging purposes
    card_type(two);
}


    // this grabs the number and verifies the correct amount of digits
long input_number(long CCN)
{
    int count = 0;
    do
    {
        CCN = get_long("Number: ");
        count = (CCN == 0) ? 1 : (log10(CCN) + 1);
        if (count < 13 || count == 14 || count > 16)
        {
            //printf("INVALID\n"); // This is to satisfy the uni. bot command check. Need a EOF
            //return (0);
        }
    }
    while (count < 13 || count == 14 || count > 16);   
    return (CCN);
}

int counter(long CCN, int count)
{
 do
    {
        count = (CCN == 0) ? 1 : (log10(CCN) + 1);
    }
    while (count < 13 || count == 14 || count > 16);   
    return (count);   
}

    // verifies card using mod10 (Luhn's)
bool luhn_check(long CCN, int count)
{
    long sum = 0;
    long bigdigit = 0;
    //printf("\nLUHN Number: %ld\n\n", CCN);     // test print for debugging
    if (count == 13 || count == 15)
    {
        count += 1;
    }
    for (int i = count; i > 0; i--)
    {
        if (i % 2 == 0)
        {
            sum += (CCN % 10);
        }
        else
        {
            bigdigit = (2 * (CCN % 10));
            sum += (bigdigit / 10 + bigdigit % 10);
        }
        CCN = (CCN / 10);
        //printf("\nI : %i\n", i);      // test print for debugging
        //printf("Sum: %li\n", sum);        // test print for debugging
        //printf("Number: %li\n", CCN);      // test print for debugging
    }
    if (sum % 10 == 0)
    {
        printf("VALID\n");
        return (true);
    }
    else
    {
        printf("INVALID\n");
        return (false);
    }
}

            // grabs the first two numbers
long firsttwo(long CCN, long two)
{
    two = CCN;
    //printf("TWO CCN: %li\n", two); // debugging purposes
    while (two >= 100)
    {
        two = two / 10;
    }
    return (two);
}

            // finds card type and ends
void card_type(long two)
{
    if (two == 34 || two == 37)
    {
        printf("AMEX\n");
        //return (0);
    }
    else if (two >= 51 && two <= 55)
    {
        printf("MASTERCARD\n");
        //return (0);
    }
    else if (two >= 40 && two <= 49)
    {
        printf("VISA\n");
        //return (0);
    }
    else
    {
        printf("INVALID\n");
        //return (0);
    }
}

I have completed the second version of the script with your suggestions, bar the str of input, I will try to tackle that method in the next version as I have not handled that type yet.

Besides running the program with a string rather than b, is there anything I could have done more efficiently?

1 Answers

Let me start with a few notes on your function input_number:

long input_number()
{
    // this grabs the number and verifies the correct amount of digits
    int count;
    [ .... ]

    while (count < 13 || count == 14 || count > 16);
    // Once this while loop starts, it will never terminate!
    // if count starts at 10 (which is less than 13), the body says "do nothing".
    // so count will continue to be unchanged, and the while-loop will continue to run.

    return (0);  // Code after a return statement will never be reached
                 // So your printf-statement below will NEVER happen.
                 // It also seems unlikely you want to return Zero.
                 // You probably want to return count, or some other value.

    printf("Digits: %i\n", count);       // test print for debugging
}
Related