Hello,
I'm working on Chapter 9, exercise 5 of "Programming: Principles and Practice Using C++" by Bjarne Stroustrup. In the exercise, I'm supposed to create a book class, with ISBN, author, title, copyright, etc. My concern lies with the ISBN check in my constructor(I haven't added the others yet)--I'm wondering if there's a better way to check it as it is. I decided to use a string to represent the ISBN because it's easier to manipulate input/output (for an end-user), rather than using a struct(easier checking)... or something I may not know or have have thought of.
Here's my code for the constructor (it works fine):
Book::Book(string ISBN) :isbn(ISBN) //will add other types later
{ //ISBN must be integer-integer-integer-digit/letter
stringstream ss(isbn); //book didn't cover stringstreams yet???
char valid='-';
char invalid=' '; //ANYTHING other than '-' is invalid...
//check the first three sections for an integer followed by a '-'
for(int index=0; index<3; index++) {
int integer=-1;
char character=invalid; //both initialized for precaution
ss >> integer >> character;
if(integer<0 || character!=valid) rpt_err("Invalid ISBN.\n");
}
string final;
ss >> final; //check the remaining character(s)???
if(final.size()!=1) rpt_err("Invalid ISBN.\n"); //only a single number/letter allowed
elseif(!isdigit(final[0]) && !isalpha(final[0])) rpt_err("Invalid ISBN.\n"); //separate check to prevent range errors
}
The problem with this is, it requires a '-' at the END of the isbn. The easiest variant (albeit maybe a bit of an overkill) would be to use regular expressions.
Yes, I'm aware that ' ' isn't just any character, but thanks... that comment was meant to show that I chose an arbitrary character to represent invalid--that literally anything else (other than '-')could have been placed there. I needed to chose something to re-initialize "character" with....
I'm not sure what you mean by "regular expressions." I'm learning on my own here... could you perhaps elaborate/demonstrate? From what I can tell, you're suggesting that I use three different integers and a character to represent the ISBN--not worrying about the dashes.
I updated my code... I noticed that it wasn't throwing for whitespace characters (see line 8). Here is the whole updated copy:
Book::Book(string ISBN) :isbn(ISBN) //will add other types later
{
//ISBN must be integer-integer-integer-digit/letter
stringstream ss(isbn);
char valid='-';
char invalid=' '; //ANYTHING other than '-' is invalid...
int printable=33;
for(int index=0; index<isbn.size(); index++) if(isbn[index]<printable) rpt_err("Invalid ISBN.\n"); //throws with whitespace
//check the first three sections for an integer followed by a '-'
for(int index=0; index<3; index++) {
int integer=-1;
char character=invalid; //both initialized for precaution
ss >> integer >> character;
if(integer<0 || character!=valid) rpt_err("Invalid ISBN.\n");
}
string final;
ss >> final; //check the remaining character(s)
if(final.size()!=1) rpt_err("Invalid ISBN.\n"); //only a single number/letter allowed
elseif(!isdigit(final[0]) && !isalpha(final[0])) rpt_err("Invalid ISBN.\n"); //separate check to prevent range errors
}