Assignment 1
Version 1.3


EAN Processor - Procedural Version



In your first assignment, you write code that processes an EAN.  For your second assignment you will convert this procedural code to object-oriented code. 


Learning Outcomes

Upon successful completion of this assignment, you will have demonstrated the abilities to

  1. design an algorithm that solves a specified problem
  2. overload a function for different signatures
  3. compile source code consisting of several modules

Background

Most bookstores use the International Article Number (EAN) system to identify the books that they sell.  EAN stood for European Article Number before being adopted internationally.  A book's EAN is the number alongside the barcode typically found on its back cover.  Publishers assign unique EANs to each edition that they publish.  An EAN, once assigned, can never be re-used by anyone.  You can find more information on this numbering system at isbn-international.org and on Wikipedia.  The GS1 organization oversees the EAN identification system.

A bookstore, when it places an order with a publisher, identifies the publication being ordered by its EAN.  The publisher prints the EAN on the cover of each copy printed.  The universal use of EANs minimizes errors due to typographical mistakes or confusions amongst similar titles. 

Structure of an EAN

The EAN system uses a barcode with thirteen characters.  The first three characters identify the application.  In the case of books these are either 978 or 979.  An EAN starting with either set of digits is called a Bookland EAN.

A Valid EAN

All of the characters in an EAN are digits between 0 and 9 inclusive.  The rightmost digit is called the check digit. 

 9780003194876

The check digit is determined as follows.  Every second digit from the second to the twelveth - counting from left to right - is multiplied by 3.  The sum of these products and the remaining digits, including the check digit, must be divisible without remainder by 10.  If there is a remainder, the number is not a valid EAN.  (Other systems that use a check digit include Social Insurance Numbers, Universal Product Codes and credit cards.)

A Registered EAN

A valid EAN may or may not be registered under GS1 organization.  A registered EAN that meets GS1 standards consists of five elements:

  1. a prefix element
  2. a registration group or area element
  3. a registrant or publisher element
  4. a publication or title element
  5. a check digit

The prefix element identifies the application area.  The GS1 Organization assigns this element.  This element consists of three (3) digits.  For example, the following are valid Bookland EANs

 978 0003194876
 978 9070002046
 978 9972000003

The group or area identifier identifies the country, region or language area participating in the EAN system.  This element consists of between one (1) and five (5) digits inclusive.  For example,

 978 0 003194876
 978 90 70002046
 978 9972 000003

The area element 0 stands for the English speaking region of the world: Australia, English Canada, Gibraltar, Ireland, (Namibia), New Zealand, Puerto Rico, South Africa, Swaziland, United Kingdom, the United States of America and Zimbabwe. 

The publisher element is the third element from the left.  GS1 publishes ranges of publisher identifiers for each area.  Each national GS1 branch assigns publisher identifiers within the range for its own area and maintains an up-to-date register of publishers and their identifiers.  This element consists of between one (1) and seven (7) digits.  For example,

 978 0 00 3194876
 978 90 70002 046
 978 9972 00 0003

The title element is the fourth element from the left and identifies the publication itself.  Publishers themselves assign a unique title identifier to each specific edition of a publication.  This component consists of between one (1) and six (6) digits.  For example,

 978 0 00 319487 6
 978 90 70002 04 6
 978 9972 00 000 3

Determining the different elements of a Bookland EAN is complicated because the number of digits in each element varies.  However, the total number of digits in the first four elements is always twelve (12). 

Finding the Elements of an EAN

Finding the elements of an EAN is an iterative process.  We start with a valid EAN supplied by a client.  We test the leftmost digits until we find an area element that is listed in the prefix table.  Once we have found the area element, we check the ranges of publisher identifiers in the same prefix table.  The upper limit of a range has the same number of digits as its lower limit.  For example, the ranges for the English speaking area of the world (area 0) are:

 00 19
 200 699
 7000 8499
 85000 89999
 900000 949999
 9500000 9999999

Note that, for this particular area, the first publisher range starts with a two digit value.  Publisher identifiers such as 00, 01, 03, 10, 19 are within this range, while identifiers such as 0, 1, 2, 3, 9 are NOT within this range.  The minimum number of digits in the publisher identifiers of any range can vary from area to area. 

You can find the GS1 prefix table here.  Each record in this table describes one publisher range.  The record consists of three fields: an area element, the lowest value for the publisher range and the highest value for the publisher range.  You have permission to use this table for educational purposes only.  You must obtain written permission directly from GS1 for any other use.


Specifications

Your solution to this assignment consists of two separate modules:

  • GS1Prefix module
  • EAN module

The EAN module calls functions in the GS1Prefix module. 

GS1Prefix Module

The GS1Prefix module holds and accesses the GS1 prefix table. 

Prefix Structure

The data structure that holds the prefix table is

const int MAX = 700;

struct Prefix {
    int  no;             // number of entries
    int  area[MAX];      // area elements
    char pubLow[MAX][8]; // low end of publisher range
    char pubHgh[MAX][8]; // high end of publisher range
    int  pubLen[MAX];    // no of chars in publisher string
};

Prefix Functions

Four functions access the prefix object: 

  • A function named load() that receives the address of a C-style, null-terminated string containing the name of the file that holds the GS1 prefix data and the address of a Prefix object that will store the data.  This function opens the named file and copies its data into the object.  The function returns true if successful; false otherwise.  The code is as follows.  You will learn how to write this code later in the course:

     #include <fstream>
    
     // load copies the prefix table from filename into *p
     //
     bool load(const char* filename, Prefix* p) {
         bool rc = false;
         if (filename != nullptr) {
             std::ifstream file(filename);
             if (file.is_open()) {
                 int no = 0;
                 while (file.good()) {  // version 1.2
                     file >> prefix->area[no] >> prefix->pubLow[no]; // version 1.3
                     if (file.good()) {
                        file >> prefix->pubHgh[no]; // version 1.3
                         prefix->pubLen[no] = std::strlen(prefix->pubLow[no]);
                         no++;
                     }
                 }
                 if (no > 0) {
                     rc = true;
                     prefix->no = no;
                 }
             }
         }
         return rc;
     }
  • A function named isRegistered() that receives the address of a Prefix object and an area element.  This function checks if the area element is registered:
     bool isRegistered(const Prefix* p, int area);
    

    This function returns true if the area element is listed in the prefix table; false otherwise. 

  • A function named minNoDigits() that receives the address of a Prefix object and an area element.  This function determines the minimum number of digits in a publisher element registered under that area
     int minNoDigits(const Prefix* p, int area);
    

    This function returns the minimum number of digits in a publisher element for the area if successful; zero (0) otherwise. 

  • A function named isRegistered() that receives the address of a Prefix object, an area element, and a publisher element.  This function checks if the publisher element is within one of the ranges listed in the table under the specified area
     bool isRegistered(const Prefix* p, int area, const char* publisher);
    

    This function returns true if the area is listed and the publisher falls within one of the ranges listed in the prefix table; false otherwise.  Note that the area parameter is of int data type, while the publisher parameter receives the address of a string. 

    For example, consider the publisher ranges for area 0

     0 00 19
     0 200 699
     0 7000 8499
     0 85000 89999
     0 900000 949999
     0 9500000 9999999 
             

    The call isRegistered(fp, 0, "02") returns true
    while the call isRegistered(fp, 0, "2") returns false.

Store the structure definition and the function prototypes in a header file named GS1Prefix.h and the function definitions in an implementation file named GS1Prefix.cpp.

EAN Module

The EAN module processes EAN strings.  This module includes two functions for interpreting a C-style, null-terminated string:

  • A function named isValid() that receives the address of a C-style null-terminated string and determines if the string is a valid EAN
     bool isValid(const char* str);
    

    If the string contains 13 characters, all of characters are digits and the check digit is modulo 10, this function returns true; false otherwise. 

  • A function named isRegistered() that checks if an EAN string is registered and, if so, extracts its area, publisher, and title elements
     bool isRegistered(const Prefix* p, const char* str, char area[],
      char publisher[], char title[]);
    

    This function receives the address of a Prefix object, the address of a C-style, null-terminated string containing a valid EAN, the address of a C-style null-terminated string that upon success will contain the area element, the address of a C-style, null-terminated string that upon success will contain the publisher element, and the address of a C-style, null-terminated string that upon success will contain the title element.  This function determines if the string is a registered EAN.  If the function finds that the string pointed to by the second parater is a registered EAN, the function passes the area, publisher and title elements through the parameter list and returns true; otherwise, the function does not pass any information through the parameter list and returns false

    This function contains the most complicated algorithm in this assignment.  Ask your instructor for help in constructing this algorithm.  One approach is to simulate the search that you would perform if you were to determine registration visually by examining the table without a computer.  Such an approach might involve searching the area elements in the table followed by a second search of the publisher ranges for an area that has been found in the able; that is, an iteration followed by a second iteration.  Use the functions of the GS1Prefix module to simplify each search.
     

Store your function prototypes in a header file named EAN.h and your function definitions in an implementation file named EAN.cpp.

Sample Run

You can find a client program that uses your functions here.  This client program is especially useful for debugging logic with respect to a particular EAN string.  To compile this program with your two modules, use the command:

 g++ -std=c++0x a1main.cpp GS1Prefix.cpp EAN.cpp

The output from a sample run might look something like:

 EAN Processor
 ==============

 EAN (0 to quit) : 9789070002046
  Area           : 90
  Publisher      : 70002
  Title          : 04

 EAN (0 to quit) : 9780003194875
  Invalid check digit. Try again.

 EAN (0 to quit) : 978000319487
  Incorrect number of digits. Try again.

 EAN (0 to quit) : 9780003194876
  Area           : 0
  Publisher      : 00
  Title          : 319487

 EAN (0 to quit) : 9789972000003
  Area           : 9972
  Publisher      : 00
  Title          : 000

 EAN (0 to quit) : 9789995500009
  This EAN is not registered

 EAN (0 to quit) : 0

 Signing off ...

Testing each of your functions is important and necessary work.  If your instructor has indicated that the official assignment test program (see below) will be released shortly before the due date, you should start to test your work earlier yourself.  Otherwise, you may find insufficient time to fix all of the bugs by the due date. 


Submission

A file containing a main function to test your classes is posted here.  Copy this file into your assignment directory, re-compile your class modules with this file and run the executable.

Once the executable indicates that you may submit your program, create a typescript using the following commands:

 + At the prompt, type: script a1.txt
 + At the prompt, type: whoami
 + At the prompt, type: cat GS1Prefix.h
 + At the prompt, type: cat GS1Prefix.cpp
 + At the prompt, type: cat EAN.h
 + At the prompt, type: cat EAN.cpp
 + At the prompt, type: g++ -std=c++0x a1test.cpp GS1Prefix.cpp EAN.cpp
 + At the prompt, type: a.out
 + At the prompt, type: cat a1main.cpp
 + At the prompt, type: g++ -std=c++0x a1main.cpp GS1Prefix.cpp EAN.cpp
 + At the prompt, type: a.out
 + At each input prompt, enter the data for the sample run shown above.
 + At the prompt type: exit

These commands will produce a file named a1.txt.  Submit this file according to your professor's instructions along with any other information your professor has requested.

Assignments that are submitted after the due date will attract a 10% late penalty per school day to a maximum deduction of 50%.

If you submit an assignment that does not pass all of the tests, you will be asked to fix your code and to resubmit, in which case you will receive an assignment mark no higher than 50% of the mark allocated for this assignment.

Regardless of how long it takes you to complete this assignment, you will need to submit a completed version in order to pass this course.







  Designed by Chris Szalwinski   Copying From This Site   
Logo
Creative Commons License