Checking a string for a valid ISBN number

Checking a string for a valid ISBN number

Rate This
  • Comments 0

Continuing the series of "things you may have done in college" this next one is all about array manipulation. Again it's one I've heard of being used in a whiteboard/tech interview situation (so worth brushing up on!). The scenario here is just the creation of a method which:

  1. Accepts a string
  2. Checks to see if that string is actually a valid 10 digit ISBN number format  (valid format - an actually valid ISBN no. is one which has been issued to a published book)

The only other stipulation is to do it in the first instance without using the built-in .NET string methods. So it would be quicker to use String.Split('-') etc... but the idea here is to test the basic knowledge, so the first effort here uses just standard array walking loops. I may add a more modern implementation later, but as  previously stated I would love if these post generated some comments, and perhaps other implementation styles in those comments.

I took the "business logic", i.e. the 10 digit ISBN rules from here: http://www.isbn.org/standards/home/isbn/international/html/usm4.htm

This is the first hastily written version:

 

 private static bool IsTenDigitISBN(string isbnString)
{
if (string.IsNullOrWhiteSpace(isbnString))
{
return false;
}

char[] isbnArray = isbnString.ToArray();

if (isbnArray[0] == '-' || isbnArray[isbnArray.Length - 1] == '-')
{
return false;
}

if (isbnArray.Length != 10 && isbnArray.Length != 13)
{
return false;
}

int dashCount = 0;
int sum = 0;
int digit=0;

//now replace the '-' chars in pos 0-9
for (int i = 0; i < isbnArray.Length-1; i++)
{
if (isbnArray[i] == '-')
{
dashCount++;
isbnArray[i]=isbnArray[i--+1];
for (int x = i + 1; x < isbnArray.Length-1; x++)
{
isbnArray[x] = isbnArray[x + 1];
}
}
}
if (dashCount != 0 && dashCount != 3)
{
return false;
}

//if array is 13 long, we must have 3 dashes, 10 long must have no dashes
if ((isbnArray.Length == 13 && dashCount !=3) && (isbnArray.Length == 10 && dashCount !=0))
{
return false;
}

for (int i=0; i < 9; i++)
{
if (ToDigit(isbnArray[i], ref digit))
{
int multiplier = 10 - i;
int val=digit*multiplier;
sum += val;
}
else
{
return false;
}
}

//now add the check digit (or 10 if it is an 'X' character)
if (isbnArray[9] == 'X' || isbnArray[9] == 'x')
{
sum += 10;
}
else
{
if (ToDigit(isbnArray[9], ref digit))
{
sum += digit;
}
else
{
return false;
}
}

//Sum of digits + check digit should have a remainder of 0 when divided by 11
int check = sum % 11;

if (check == 0)
{
return true;
}
else
{
return false;
}
}

 

 

As you can see there is one other small method called within the check method - the ToDigit() method which converts a char to an int (if the char is one of '0' - '9'). It is shown here:

 

 /// <summary>
/// An "atoi()" style function for single characters
/// </summary>
/// <param name="ch">character which should represent a digit</param>
/// <param name="digit">pass by ref int used to return the value</param>
/// <returns></returns>
private static bool ToDigit(char ch, ref int digit)
{
char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
bool found=false;

for (int i = 0; i < digits.Length; i++)
{
if (ch==digits[i])
{
digit=i;
found=true;
}
}

if (found)
{
return true;
}


return false;
}

 

 

So that's it - comments welcome. Questions which could be asked around this include the standard "which unit tests would you write". Here's some examples of strings to pass:

Valid - return true:

IsTenDigitISBN("90-70002-34-5"));
IsTenDigitISBN("0-8436-1072-7"));
IsTenDigitISBN("1590593006"));

 

Invalid - return false:

IsTenDigitISBN("-"));
IsTenDigitISBN("--1234556789--"));
IsTenDigitISBN("123-45-567-8-9"));

 

Other questions to ask then would be perhaps:

  • How to improve it/rewrite it using .NET string methods.
  • How to check for a 13 digit ISBN also - in the same method?
Blog - Comment List MSDN TechNet
  • Loading...
Leave a Comment
  • Please add 5 and 3 and type the answer here:
  • Post