0

We've been asked to code a program which validate GTIN-8 codes. The valdation is as follows:

  1. Multiply the first 7 digits alternately by 3 then 1

  2. Add them up

  3. Subtract that number from the equal or higher multiple of 10

  4. The resulting number is the eighth digit

Here's my code:

def validgtin():  

    gtin = input("Enter the 8 digits of GTIN-8 product code: ")   
    valid = False
    while valid == False:
        if gtin.isdigit():               
            gtin = str(gtin)
            if len(gtin) == 8:          
                valid = True
            else:
                print("That is not correct, enter 8 digits, try again: ")       
                gtin = input("Enter the 8 digits of GTIN-8 product code: ")
        else:
            print("That is not correct, type in numbers, try again: ")
            gtin = input("Enter the 8 digits of GTIN-8 product code: ")     


    sumdigit =  3*(int(gtin[0])) + 1*(int(gtin[1])) + 3*(int(gtin[2])) + 1*(int(gtin[3])) + 3*(int(gtin[4])) + 1*(int(gtin[5])) + 3*(int(gtin[6]))  #sum of the digits

    gtin = str(gtin)  

    valid1 = False
    while not valid1:
        if sumdigit%10 == 0:    
            eightdigit = 0
        else:
            eightdigit = (((sumdigit + 10)//10)*10) - sumdigit  

        if eightdigit == (gtin[7]):
            valid1 = True
            print("Your GTIN-8 product code is valid.")

        else:
            print("Your GTIN-8 product code is not valid.")
            gtin = input("Enter the 8 digits of GTIN-8 product code: ")


    return

validgtin()

When I run this code and type an invalid GTIN-8 code it says that the code is invalid and prompts me to type in a new GTIN-8 code

BUT

After I type in a new and valid GTIN-8 code it still says it is invalid

AND

After that this happens:

Traceback (most recent call last):



File "C:\Users\Yash Dwivedi\Documents\Year 10\GCSE Computing\Assignment\Task 1 v2.py", line 29, in validgtin
    if eightdigit == (gtin[7]):
IndexError: string index out of range

I don't understand why I'll be thankful for any help.

3
  • 1
    You can try printing gtin, just before you get error Commented Jan 24, 2016 at 11:21
  • 1
    What is the point of gtin = str(gtin)? That would make some sense in Python 2 -- but then it that case you should be using raw_input. On the other hand, if this is Python 2 then gtin.isdigit() would throw a runtime error if the user had in fact entered something consisting of exclusively digits. Commented Jan 24, 2016 at 11:35
  • Please study the posting guidelines, you must extract a minimal example for posting and not that whole stuff you quoted here. There is a reason for that, too! Commented Jan 24, 2016 at 12:37

3 Answers 3

1

I would suggest to make a "is_valid_gtin" function that just checks if a GTIN is valid, without I/O. Then a simple "main()" to check the code:

def is_valid_gtin(gtin):
    if len(gtin) != 8 or not gtin.isdigit():
        return False
    sum = 0
    for i in list(gtin)[0:6:2]:
        sum += 3*int(i)
    for i in list(gtin)[1:6:2]:
        sum += int(i)
    checksum = (10 - sum % 10) % 10
    return checksum == int(gtin[7])


def main():
    while (True):
        gtin = input("Enter the 8 digits of GTIN-8 product code: ")
        if is_valid_gtin(gtin):
            print("Your GTIN-8 product code is valid.")
            break
        else:
            print("That is not correct, try again.")

if __name__ == '__main__':
    main()
Sign up to request clarification or add additional context in comments.

Comments

0

Here's my quick implementation. Sadly I don't have any test data to check it's correct!

def _round_up_ten(number):
    if number % 10 == 0:
        return number
    return 10 * (1 + (number / 10))


def validate_gtin(gtin):
    if not gtin.isdigit() or len(gtin) != 8:
        raise ValueError("GTIN must be an 8-digit number")

    digits = [int(digit) for digit in gtin[:-1]]
    check_digit = int(gtin[-1])

    multiplied_digits = (
        digits[0] * 3
        + digits[1]
        + digits[2] * 3
        + digits[3]
        + digits[4] * 3
        + digits[5]
        + digits[6] * 3
    )

    expected_check_digit = _round_up_ten(multiplied_digits) - multiplied_digits

    if check_digit!= expected_check_digit:
        raise ValueError("Incorrect check digit ({}) (expected {})".format(check_digit, expected_check_digit))

Comments

0

The bug is in the line

if eightdigit == (gtin[7]):

eightdigit is an int but gtin[7] is a string. This comparison is thus always false -- hence you are in an infinite loop (as long as you enter strings with at least 8 characters). You grow frustrated and then just hit the enter key -- which passes your code the empty string, which, lacking an eighth character, triggers the index out of range error.

Thus you would need:

if eightdigit == int(gtin[7]):

to fix that particular bug, though this would still leave you with a logical error -- since the loop at the bottom of your code doesn't validate the input and you are trying to check new candidate gtins against a checkdigit computed with a previous input. You should probably follow @JacquesSupik 's excellent idea and refactor the code so that the logic of validation is separated from the I/O logic.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.