I need some help with std::regex_match because I'm trying to use in a Chapter 15 dril in PPP2

The second part of the Drill in PPP2 Chapter 15, where you have to define the struct "Person". Namely, number 7 in the specifications:

Modify the constructor to check that age is [0:150) and that name doesn’t contain any of the characters ; : " ' [ ] * & ^ % $ # @ ! . Use error() in case of error. Test.


Note: The period in "bad characters" is not included in the characters themselves and is just a closing period.

Anyway, I'll show my code for the whole drill here, and as always, the drill specifications are included in the comments at the top.

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
// Chapter 15 Class definition drill
// Drill Specifications:
/**
* 1. Define a struct Person containing a string name and an int age.
* 2. Define a variable of type Person , initialize it with “Goofy” and 63, and
* write it to the screen ( cout ).
* 3. Define an input ( >> ) and an output ( << ) operator for Person ; read in a
* Person from the keyboard ( cin ) and write it out to the screen ( cout ).
* 4. Give Person a constructor initializing name and age .
* 5. Make the representation of Person private, and provide const member
* functions name() and age() to read the name and age.
* 6. Modify >> and << to work with the redefined Person .
* 7. Modify the constructor to check that age is [0:150) and that name doesn’t
* contain any of the characters ; : " ' [ ] * & ^ % $ # @ ! . Use error() in case
* of error. Test.
* 8. Read a sequence of Person s from input ( cin ) into a vector<Person> ;
* write them out again to the screen ( cout ). Test with correct and errone-
* ous input.
* 9. Change the representation of Person to have first_name and second_name
* instead of name . Make it an error not to supply both a first and a second
* name. Be sure to fix >> and << also. Test.
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <string>
#include <regex>

struct Person
{
	Person(const std::string &name, const int age);
	Person();
	std::string name() const { return m_name; }
	int age() const { return m_age; }
private:
	std::string m_name;
	int m_age;
};

std::ostream &operator<<(std::ostream &os, const Person &person);
std::istream &operator>>(std::istream &is, Person &person);

int main()
{
	using namespace std;

	try
	{
		Person p1{ "'[]*&^%$#@!", 150 };
	}
	catch (const runtime_error &rte)
	{
		cerr << "Runtime error: " << rte.what() << '\n';
	}

	keep_window_open();
}

Person::Person(const std::string &name, const int age)
	:m_name{ name }, m_age{ age }
{
	if (age < 0 || age > 150)
	{
		error("age out of range");
	}

	if (std::regex_match(m_name, std::regex("' [ ] * & ^ % $ # @ !")))
	{
		error("name contains invalid characters");
	}
}

Person::Person()
	: m_name{}, m_age{}
{
}

std::ostream &operator<<(std::ostream &os, const Person &person)
{
	return os << person.name() << " -- age: " << person.age();
}

std::istream &operator>>(std::istream &is, Person &person)
{
	using namespace std;

	string name;
	getline(is, name, '\n');
	int age;
	is >> age;

	person = Person::Person{ name, age };

	return is;
}


It won't the desired error message in case of the name containing bad characters. I think I'm using std::regex() wrong somehow, but how? Could someone help me?

I took out the code for specifications 2 and 3 where I had to add "Goofy" and read in a Person's name and age. I had them for a while, but I didn't think I need to keep them so I took them out.
If you want to use std::regex I suggest you study chapter 23 where std::regex is introduced, otherwise I suggest you think about using some of the std::string functions like find.first_of().

Yeah, that sounds better. I'll use find() or find_first_of(), then. Thanks for the advice.

Edit: Now I need help with number 8, "Read a sequence of Persons from input (cin) into a vector<Person>; write them out again to the screen (cout). Test with correct and erroneous input."

Here's my code:
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
131
132
133
134
135
136
137
138
139
140
141
142
143
// Osman Zakir
// 6 / 23 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 15 Class definition drill
// Drill Specifications:
/**
* 1. Define a struct Person containing a string name and an int age.
* 2. Define a variable of type Person , initialize it with “Goofy” and 63, and
* write it to the screen ( cout ).
* 3. Define an input ( >> ) and an output ( << ) operator for Person ; read in a
* Person from the keyboard ( cin ) and write it out to the screen ( cout ).
* 4. Give Person a constructor initializing name and age .
* 5. Make the representation of Person private, and provide const member
* functions name() and age() to read the name and age.
* 6. Modify >> and << to work with the redefined Person .
* 7. Modify the constructor to check that age is [0:150) and that name doesn’t
* contain any of the characters ; : " ' [ ] * & ^ % $ # @ ! . Use error() in case
* of error. Test.
* 8. Read a sequence of Person s from input ( cin ) into a vector<Person> ;
* write them out again to the screen ( cout ). Test with correct and errone-
* ous input.
* 9. Change the representation of Person to have first_name and second_name
* instead of name . Make it an error not to supply both a first and a second
* name. Be sure to fix >> and << also. Test.
*/

#include "../../cust_std_lib_facilities.h"
#include <iostream>
#include <vector>
#include <string>

struct Person
{
	Person(const std::string &name, const int age);
	Person();
	std::string name() const { return m_name; }
	int age() const { return m_age; }
	void set_name(const std::string &name) { m_name = name; }
	void set_age(const int age) { m_age = age; }
private:
	std::string m_name;
	int m_age;
};

std::ostream &operator<<(std::ostream &os, const Person &person);
std::istream &operator>>(std::istream &is, Person &person);
void fill_person_v(std::vector<Person> &persons_v);
void print_person_v(const std::vector<Person> &persons_v);

int main()
{
	using namespace std;

	try
	{
		vector<Person> persons_v;
		fill_person_v(persons_v);
		print_person_v(persons_v);
	}
	catch (const runtime_error &rte)
	{
		cerr << "Runtime error: " << rte.what() << '\n';
	}
	catch (const out_of_range &oor)
	{
		cerr << "Out of range error: " << oor.what() << '\n';
	}

	keep_window_open();
}

Person::Person(const std::string &name, const int age)
	:m_name{ name }, m_age{ age }
{
	if (age < 0 || age > 150)
	{
		error("age out of range");
	}

	std::string bad_chars{ ":;''""[]*&^%$#@!" };
	for (std::size_t i = 0; i < m_name.size(); ++i)
	{
		if (m_name.find_first_of(bad_chars[i]))
		{
			error("name consists of invalid characters");
		}
	}
}

Person::Person()
	: m_name{}, m_age{}
{
}

std::ostream &operator<<(std::ostream &os, const Person &person)
{
	return os << person.name() << " -- age: " << person.age();
}

std::istream &operator>>(std::istream &is, Person &person)
{
	using namespace std;

	string name;
	getline(is, name, '\n');
	int age;
	is >> age;

	person = Person::Person{ name, age };

	return is;
}

void fill_person_v(std::vector<Person> &persons_v)
{
	using namespace std;
	cout << "Enter some people's name and age (separate name and age by 'Enter' keypress, please)\n"
		<< "end sequence of persons by entering '~'\n";
	for (Person person; cin >> person;)
	{
		char ch;
		cin.get(ch);
		if (ch != '~')
		{
			cin.putback(ch);
			persons_v.push_back(person);
		}
		else
		{
			cout << "Sequence ended\n";
			break;
		}
	}
}

void print_person_v(const std::vector<Person> &persons_v)
{
	using namespace std;
	for (std::size_t i = 0; i < persons_v.size(); ++i)
	{
		cout << persons_v.at(i) << '\n';
	}
}


I get the "invalid characters in name" error whatever name I enter. What am I doing wrong?
Last edited on
Topic archived. No new replies allowed.