
- •Introduction
- •Saving Time with This Book
- •Conventions Used in This Book
- •Part II: Working with the Pre-Processor
- •Part III: Types
- •Part IV: Classes
- •Part V: Arrays and Templates
- •Part VI: Input and Output
- •Part VII: Using the Built-in Functionality
- •Part VIII: Utilities
- •Part IX: Debugging C++ Applications
- •Part X: The Scary (or Fun!) Stuff
- •Icons Used in This Book
- •Creating and Implementing an Encapsulated Class
- •Creating a Mailing-List Application
- •Testing the Mailing-List Application
- •Customizing a Class with Polymorphism
- •Testing the Virtual Function Code
- •Why Do the Destructors Work?
- •Delayed Construction
- •The cDate Class
- •Testing the cDate Class
- •Creating the Header File
- •Testing the Header File
- •The Assert Problem
- •Fixing the Assert Problem
- •Using the const Construct
- •Identifying the Errors
- •Fixing the Errors
- •Fixing What Went Wrong with the Macro
- •Using Macros Appropriately
- •Using the sizeof Function
- •Evaluating the Results
- •Using sizeof with Pointers
- •Implementing the Range Class
- •Testing the Range Class
- •Creating the Matrix Class
- •Matrix Operations
- •Multiplying a Matrix by a Scalar Value
- •Multiplying a Matrix by Scalar Values, Take 2
- •Testing the Matrix Class
- •Implementing the Enumeration Class
- •Testing the Enumeration Class
- •Implementing Structures
- •Interpreting the Output
- •Defining Constants
- •Testing the Constant Application
- •Using the const Keyword
- •Illustrating Scope
- •Interpreting the Output
- •Using Casts
- •Addressing the Compiler Problems
- •Testing the Changes
- •Implementing Member-Function Pointers
- •Updating Your Code with Member-Function Pointers
- •Testing the Member Pointer Code
- •Customizing Functions We Wrote Ourselves
- •Testing the Default Code
- •Fixing the Problem
- •Testing the Complete Class
- •Implementing Virtual Inheritance
- •Correcting the Code
- •Rules for Creating Overloaded Operators
- •Using Conversion Operators
- •Using Overloaded Operators
- •Testing the MyString Class
- •Rules for Implementing new and delete Handlers
- •Overloading new and delete Handlers
- •Testing the Memory Allocation Tracker
- •Implementing Properties
- •Testing the Property Class
- •Implementing Data Validation with Classes
- •Testing Your SSN Validator Class
- •Creating the Date Class
- •Testing the Date Class
- •Some Final Thoughts on the Date Class
- •Creating a Factory Class
- •Testing the Factory
- •Enhancing the Manager Class
- •Implementing Mix-In Classes
- •Testing the Template Classes
- •Implementing Function Templates
- •Creating Method Templates
- •Using the Vector Class
- •Creating the String Array Class
- •Working with Vector Algorithms
- •Creating an Array of Heterogeneous Objects
- •Creating the Column Class
- •Creating the Row Class
- •Creating the Spreadsheet Class
- •Testing Your Spreadsheet
- •Working with Streams
- •Testing the File-Reading Code
- •Creating the Test File
- •Reading Delimited Files
- •Testing the Code
- •Creating the XML Writer
- •Testing the XML Writer
- •Creating the Configuration-File Class
- •Setting Up Your Test File
- •Building the Language Files
- •Creating an Input Text File
- •Reading the International File
- •Testing the String Reader
- •Creating a Translator Class
- •Testing the Translator Class
- •Creating a Virtual File Class
- •Testing the Virtual File Class
- •Using the auto_ptr Class
- •Creating a Memory Safe Buffer Class
- •Throwing and Logging Exceptions
- •Dealing with Unhandled Exceptions
- •Re-throwing Exceptions
- •Creating the Wildcard Matching Class
- •Testing the Wildcard Matching Class
- •Creating the URL Codec Class
- •Testing the URL Codec Class
- •Testing the Rot13 Algorithm
- •Testing the XOR Algorithm
- •Implementing the transform Function to Convert Strings
- •Testing the String Conversions
- •Implementing the Serialization Interface
- •Creating the Buffer Class
- •Testing the Buffer Class
- •Creating the Multiple-Search-Path Class
- •Testing the Multiple-Search-Path Class
- •Testing the Flow Trace System
- •The assert Macro
- •Logging
- •Testing the Logger Class
- •Design by Contract
- •Adding Logging to the Application
- •Making Functions Inline
- •Avoiding Temporary Objects
- •Passing Objects by Reference
- •Choosing Initialization Instead of Assignment
- •Learning How Code Operates
- •Testing the Properties Class
- •Creating the Locking Mechanism
- •Testing the Locking Mechanism
- •Testing the File-Guardian Class
- •Implementing the Complex Class
- •Creating the Conversion Code
- •Testing the Conversion Code
- •A Sample Program
- •Componentizing
- •Restructuring
- •Specialization
- •Index

26 Doing Data
Validation with
Technique Classes
Save Time By
Understanding data validation with classes
Creating a data-validation class
Testing your class
Data validation is one of the most basic and pervasive functions of a computer program. Before you can operate on a given piece of data, you need to know whether or not it is valid. It doesn’t matter
if it is a date, a time, an age, or a Social Security number; the data you accept into your program will cause problems if it is in an invalid format.
Validating a data type is a perfect form of encapsulation, which makes it a perfect task to assign to a C++ class. Because we encapsulate both the data and the rules for the data type within a class, we can move that class from project to project, anywhere that the data type is needed. This saves time in implementing the class, as well as time and effort in validating and testing the class.
When you’re writing an application, take time to identify the data types you’re using. Write classes to validate, save, and load these data types and you will save yourself endless time debugging and extending your applications.
Implementing Data Validation with Classes
Follow these steps to create your own validation classes:
1. In the code editor of your choice, create a new file to hold the code for your header file.
In this example, I call my class ch26.cpp.
2. Type the code from Listing 26-1 into your file.
Better yet, copy the code from the source file on this book’s companion Web site.

Implementing Data Validation with Classes |
143 |
LISTING 26-1: THE VALIDATION CLASS
#include <string>
//Constants used in this validation #define SSN_LENGTH 9
#define SSN_DELIMITER ‘-’
//The validator class
class SSNValidator
{
//Internal member variables private:
//This is the actual SSN. std::string _ssn;
//This is the flag indicating validity. bool _valid;
1
2
protected: |
|
bool |
IsValid(const char *strSSN); |
public:
//Constructors and destructor SSNValidator();
SSNValidator( const char *ssn ); SSNValidator( const std::string& ssn ); SSNValidator( const SSNValidator& aCopy ); virtual ~SSNValidator();
//Accessors for this class
bool |
Valid() |
{ return _valid; }; |
std::string |
SSN() { return _ssn; }; |
|
void |
setSSN( |
const char *ssn); |
// Operators for this class
SSNValidator operator=( const char *ssn ); SSNValidator operator=( const std::string& ssn ); SSNValidator operator=( const SSNValidator& aCopy ); operator const char *();
};
3. Save your code in the code editor. |
4. Type the code from Listing 26-2 into your new |
This will be the definition for our Validator |
file. |
|
|
object. This class can then be included in other |
Better yet, copy the code from the source file on |
modules to do validation of the type we are |
this book’s companion Web site. |
defining. In this example, we are validating a U.S. |
|
Social Security Number. |
|

144 Technique 26: Doing Data Validation with Classes
LISTING 26-2: SOCIAL SECURITY NUMBER VALIDATOR
#include <ctype.h>
bool SSNValidator::IsValid(const char *strSSN)
{
int i;
//No NULL values allowed. if ( strSSN == NULL )
return false;
//Copy the result into a string, removing all delimiters. std::string sSSN;
for ( i=0; i<(int)strlen(strSSN); ++i ) if ( strSSN[i] != SSN_DELIMITER )
sSSN += strSSN[i];
//Must be 9 characters.
if ( strlen(sSSN.c_str()) != SSN_LENGTH ) return false;
//Check to see whether all characters are numeric. for ( i=0; i<(int)strlen(sSSN.c_str()); ++i )
if ( !isdigit( sSSN[i] ) ) return false;
//Must be okay.
return true;
}
// Constructors and destructor SSNValidator::SSNValidator()
{
_ssn = “”; _valid = false;
}
SSNValidator::SSNValidator( const char *ssn )
{
// Only assign if valid. _valid = IsValid( ssn ); if ( _valid )
_ssn = ssn;
}
SSNValidator::SSNValidator( const std::string& ssn )
{
// Only assign if valid.
_valid = IsValid( ssn.c_str() ); if ( _valid )
_ssn = ssn;
}
SSNValidator::SSNValidator( const SSNValidator& aCopy )

Implementing Data Validation with Classes |
145 |
{
_ssn = aCopy._ssn; _valid = aCopy._valid;
}
SSNValidator::~SSNValidator()
{
}
void SSNValidator::setSSN( const char *ssn)
{
// Only assign if valid. if ( IsValid( ssn ) )
{
_valid = true; _ssn = ssn;
}
}
// Operators for this class
SSNValidator SSNValidator::operator=( const char *ssn )
{
// Only assign if valid. if ( IsValid( ssn ) )
{
_valid = true; _ssn = ssn;
}
return *this;
}
SSNValidator SSNValidator::operator=( const std::string& ssn )
{
// Only assign if valid.
if ( IsValid( ssn.c_str() ) )
{
_valid = true; _ssn = ssn;
}
return *this;
}
SSNValidator SSNValidator::operator=( const SSNValidator& aCopy )
{
_valid = aCopy._valid; _ssn = aCopy._ssn; return *this;
}
SSNValidator::operator const char *()
{
return _ssn.c_str();
}