1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#include <iostream>
#include <string>
#include <stdexcept>
#include <cctype>
// not empty, all alpha, no spaces
bool valid_name( const std::string& str )
{
if( str.empty() ) return false ;
for( char c : str ) if( !std::isalpha(c) ) return false ;
return true ;
}
// not empty, all alpha, may contain embedded '-', no spaces
bool valid_surname( const std::string& str )
{
if( str.empty() ) return false ;
if( str.front() == '-' || str.back() == '-' ) return false ;
for( char c : str ) if( !std::isalpha(c) && c != '-' ) return false ;
// note: check for two consecutive '-' elided for brevity
return true ;
}
// not empty, all alpha, may contain embedded '-', ',' or '.', no spaces
bool valid_place( const std::string& str )
{
static const auto is_special = [] ( char c ) { return c == '-' || c == ',' || c == '.' ; };
if( str.empty() ) return false ;
if( is_special( str.front() ) ) return false ;
if( is_special( str.back() ) ) return false ;
for( char c : str ) if( !std::isalpha(c) && !is_special(c) ) return false ;
// note: check for two consecutive special characters elided for brevity
return true ;
}
struct person_info // not default constructible
{
person_info( std::string surname, std::string name, std::string place_of_birth,
int age, int tel = 0 ) ; // constructor
std::string surname;
std::string name;
std::string place_of_birth;
int tel = 0 ; // default member initialiser
int age = 0 ;
bool valid() const ; // class invariant ;
};
bool person_info::valid() const
{
// if any field is present, all fields must be present and valid
return valid_name(name) && valid_surname(surname) && valid_place(place_of_birth) &&
age >= 0 && age < 200 && tel >= 0 ;
}
person_info::person_info( std::string surname, std::string name, std::string place_of_birth,
int age, int tel )
: surname(surname), name(name), place_of_birth(place_of_birth), tel(tel), age(age)
{ if( !valid() ) throw std::invalid_argument( "bad constructor arg" ) ; }
// write person info to an output stream. ( operator<< ? )
std::ostream& put_person_info( std::ostream& stm, const person_info& pinfo )
{
return stm << pinfo.name << ' ' << pinfo.surname << ' ' << pinfo.place_of_birth
<< ' ' << pinfo.age << ' ' << pinfo.tel << '\n' ;
}
int main()
{
// either:
{
std::string surname, name, place_of_birth ;
int age, tel ;
std::cout << "surname? " && std::cin >> surname ;
std::cout << "name? " && std::cin >> name ;
std::cout << "place_of_birth? " && std::cin >> place_of_birth ;
std::cout << "age? " && std::cin >> age ;
std::cout << "tel? " && std::cin >> tel ;
try
{
person_info pinfo( surname, name, place_of_birth, age, tel ) ;
put_person_info( std::cout << "ok: ", pinfo ) ;
}
catch( const std::invalid_argument& )
{
std::cerr << "*** error: invalid input\n" ;
}
}
// or, with more accurate error reporting and recovery:
{
std::string surname, name, place_of_birth ;
int age, tel ;
while( std::cout << "surname? " && std::cin >> surname && !valid_surname(surname) )
std::cout << "inavid surname. try again\n" ;
while( std::cout << "name? " && std::cin >> name && !valid_name(name) )
std::cout << "inavid name. try again\n" ;
while( std::cout << "place_of_birth? " && std::cin >> place_of_birth && !valid_place(place_of_birth) )
std::cout << "inavid place_of_birth. try again\n" ;
while( std::cout << "age? " && std::cin >> age && ( age < 0 || age > 199 ) )
{
std::cout << "inavid age. try again\n" ;
std::cin.clear() ;
std::cin.ignore( 1000, '\n' ) ;
}
while( std::cout << "phone? " && std::cin >> tel && tel < 0 )
{
std::cout << "inavid phone number. try again\n" ;
std::cin.clear() ;
std::cin.ignore( 1000, '\n' ) ;
}
person_info pinfo( surname, name, place_of_birth, age, tel ) ;
put_person_info( std::cout << "ok: ", pinfo ) ;
}
}
|