0

I'm working on credit in pset1 and I'm having problems with getting every other digit. I opted to use arrays and fill them using for loops (as shown below) but for whatever reason the output is messed up. I have it to print out the "every other digit"s and the "remaining" digits to help with debugging, but I can't figure out what's wrong with my code. Been working on this for forever, a fresh set of eyes might help. Anyway thanks for any help.

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

int main(void)
{
    // get and validate input
    printf("Number: ");
    long long number;
    do
    {
        number = get_long_long();
        if (number <= 0)
        {
           printf("Retry: ");
        }
    }
    while (number <= 0);

    // put every other digit to 'others'
    long digit_count = (log10(number) + 1); // counts digits
    long digits[digit_count];
    int counter = 0;
    while (number != 0)
    {
        int last = number % 10;  // puts digits in array 'digits'
        digits[counter] = last;
        number = number / 10;
        counter++;
    }

    long half = digit_count / 2;
    int others[half]; // array for every other digit

    if ((digit_count % 2) != 0) // if odd amount of digits (gets every 
other)
    {
        printf("Others:\n");
        for (int a = (digit_count - 2), b = 0; a >= 0; a = a - 2, b++)
        {
            others[b] = digits[a];
            printf("%i\n", others[b]);
        }
    }
    else // if even amount of digits (gets every other)
    {
        for (int x = (digit_count - 1), y = 0; x >= 0; x = x - 2, y++)
        {
            others[y] = digits[x];
            printf("%i\n", others[y]);
        }
    }

    // multiply 'others' by 2
    for (int i = 0; i < (half); i++)
        others[i] = others[i] * 2;

    // add the 'others' DIGITS (not the numbers themselves)
    int sum = 0;
    for (int i = 0; i < half; i++)
    {
        if (others[i] < 10)
            sum += others[i];
        else
        {
            int mod = others[i] % 10;
            int tens = others[i] / 10;
            sum += mod + tens;
        }
    }    
    printf("Sum \"others\": %i\n", sum);

    // find 'remaining' numbers
    printf("Remaining:\n");
    int remaining[half];
    if (digit_count % 2 != 0) // if odd (get all remaining)
    {
        for (int i = digit_count, j = 0; i > 0; i = i - 2, j++)
        {
            remaining[j] = digits[i];
            printf("%i\n", remaining[j]);
        }
    }
    else
    {
        for (int i = digit_count - 2, j = 0; i >= 0; i = i - 2, j++)
        {
            remaining[j] = digits[i];
            printf("%i\n", remaining [j]);
        }
    }

    // calculate sum of 'remaining'
    int sum2 = 0;
    for (int i = 0; i < half; i++)
    {
        if (remaining[i] < 10)
            sum2 += remaining[i];
        else
        {
            int mod = remaining[i] % 10;
            int tens = remaining[i] / 10;
            sum2 += mod + tens;
        }
    }
    printf("Sum remaining: %i\n", sum2);

    // calculate checksum, test card number
    int checksum = sum + sum2;
    if (checksum % 10 != 0)
    {
        printf("INVALID CARD NUMBER\n");
        return 1;
    }
    else
        return 0;

    // insert code for credit card companies
}

Here's some sample input/output:

Number: 01234567890123456789
Others:
2
4
6
8
0
2
4
6
8
Sum "others": 44
Remaining:
credit.c:79:28: runtime error: index 19 out of bounds for type 'long 
[digit_count]'
4379960
2
4
6
8
0
2
4
6
credit.c:79:13: runtime error: index 9 out of bounds for type 'int [half]'
credit.c:80:28: runtime error: index 9 out of bounds for type 'int [half]'
8
Sum remaining: 438028
INVALID CARD NUMBER

Number: 37828224631005
3
8
8
2
6
1
0
Sum "others": 29
Remaining:
7
2
2
4
3
0
5
Sum remaining: 23
INVALID CARD NUMBER

Thanks so much. Sorry for long post, wanted to be clear.

1

In case of an odd number of digits (leading zeroes are ignored when parsing as number, 20 digits would be more than a long, which here is a int64_t, could take), you have half+1 digits that should go to remaining, but only space for half.

Also, you start at index digit_count in one loop, which is invalid, you probably meant digit_count - 1.

I would try to avoid doing all those arrays, and only keep the final sum, like

int digit_count = 0;
int checksum = 0;
for (long number_copy = number; number_copy > 0; number_copy /= 10, digit_count++)
{
    int digit = number_copy % 10;
    if (digit_count % 2 == 0) {
        // easy
        checksum += digit;
    } else {
        // double digit and add digits of double
        checksum += 2 * digit / 10; // first digit
        checksum += 2 * digit % 10; // second digit
    }
}

(Yes, I'm not a big fan of log10 on integers, there might be rounding errors in conversion to double)

Additionally, I kept the first two digits in an additional variable to use it in differentiating the different types of credit cards.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .