Source Code: #include // for regular expression support #include #include // for std::make_shared and std::shared_ptr #include #include // for C's strcmp (see below) #include //
![image text in transcribed](https://s3.amazonaws.com/si.experts.images/answers/2024/09/66dd3e54215e2_44366dd3e5393de9.jpg)
![image text in transcribed](https://s3.amazonaws.com/si.experts.images/answers/2024/09/66dd3e54b4a71_44466dd3e5473c7d.jpg)
![image text in transcribed](https://s3.amazonaws.com/si.experts.images/answers/2024/09/66dd3e5575432_44466dd3e54f136c.jpg)
![image text in transcribed](https://s3.amazonaws.com/si.experts.images/answers/2024/09/66dd3e56370c0_44566dd3e559d657.jpg)
Source Code:
#include // for regular expression support
#include
#include // for std::make_shared and std::shared_ptr
#include
#include // for C's strcmp (see below)
#include // for std::optional
#include
#include // for filesystem support
class program_input
{
public:
virtual ~program_input() { } // necessary to properly deallocate memory
virtual bool read() = 0;
};
using all_inputs_type = std::vector<:shared_ptr>>;
std::vector read_all_inputs(all_inputs_type& /*ai*/)
{
// NOTE: For now the ai function argument is commented out to avoid a compiler warning about ai being unused.
return {}; // i.e., return a default constructed std::vector
}
std::ostream& output_usage(std::ostream& os, int /*argc*/, char *argv[])
{
os ";
return os;
}
namespace fs = std::filesystem;
using namespace std;
int main() {
optional scan_directory;
for (int args_pos=1; args_pos
{
// ...
}
all_inputs_type all_inputs; // this variable will hold all discovered program input files
for (auto& entry : fs::recursive_directory_iterator(scan_directory.value()))
{
cout
}
read_all_inputs(all_inputs); // i.e., process all discovered input (files)
smatch mr; // variable to hold regex matched results
string const fname = entry.path().filename(); // only match the filename
if (regex_match(fname, mr, baby_name_file_regex))
{
// regex_match() only returns true when the match is successful
// you will be writing code in here below
// for now use the following cout to see that it actually matches...
cout
}
}
main): Determining If The Filename Has The Pattern "yobYYYY.txt Although you could write code to determine if a filename has the pattern "yobYYYY.txt", that code would likely be more complicated than simply using the portion of the standard library! So the following instructions walk you through doing this. Nicely this will not only determine if the file name has the correct pattern, but, this will extract the value of YYYY into an integer variable as well. If you've not already, then read Josuttis chapter 14 on Regular Expressions. Look at the examples and what is output. The notation that can be used in regular expressions is detailed in 14.8 Since you know the current "entry" in the loop is a regular file, write the following code in your for loop: // determine if file anme is of the form yobYYYY.txt... static regex const baby_name_file_regex( R"(yob(di4).txt)"; Writing The yob_baby_name_file Class Write a class called "yob_baby_name_file" that inherits publicly from the "program_input" class. (This inheritance is not virtual: this code will only exploit the polymorphism of virtual functions.) The "yob_baby_name_file" class is to be written as follows: It must store the file name it is associated with as a private std:string member called fname_ It must store the year it is associated with as a private unsigned member called year_ It must have a single constructor with the following prototype: o yob_baby_name file(std::string fname, unsigned year) NOTE: Its constructor must not have anything inside its body (i.e., within 0)! . It must override the read) pure virtual function in program_input. o Hint: Start by writing "bool read) override". Writing yob_baby_name_file::read0) The yob_baby_name file::read member must do the following: Output to std::cout: o "Reading yob_baby_name_file "followed by o fname followed by o "for year " followed by oyear_followed by o n' i.e., a newline character). Return true when done. Back To main): Writing The Code When The Regex Matches With the yob_baby_name_file class defined, the code can now be written when the regex matches as a single C++ statement: Call the variable "all inputs" push_back) function passing in the result of this function call: Call make_shared yob_ baby_name_file> (...) where are the arguments: o fname, i.e., the file name that was matched), and, o mr[1].str converted to an unsigned number using stoul0 NOTE 1: mr[1].str) is the string corresponding to the (d4)) match. NOTE 2: Look up stoul() at cppreference.com to see how to convert a C++ std:string to an unsigned long. Pass in nullptr for the second argument. Last Step: Writing The Code For read_all_inputs0 Earlier you were given a trivial code stub for the read_all_inputs () function (which is called in the last line in main. Now that you are actually populating the all_inputs variable with data, it makes sense to write the code for this function! Do the following in the order listed Declare a variable called "retval" of type std::vector. (This will be the returned from the function.) Invoke std:vector's "reserve()" function passing in ai.size). o ai is the argument passed to read_all_inputs (see earlier stub) o The reserve calls tells the vector to ensure enough memory has been dynamically allocated to hold ai.size() elements * Use a range for loop to iterate over all elements in ai (i.e., the argument passed to the function) and within the loop: o ASIDE: Below "" is used to refer to the current element involved with the for loop iteration o Write try block with the single line of code Invoke the push back() function on retval and pass what i->read) returns. ASIDE: i is an instance of std:shared ptr. The ->is the indirection operator which allows one to invoke the read) function on the internally stored program_input* object. o In the catch(...) handler write the single line of code Call the push back() function on retval passing in false. ASIDE: Since reserve() was used to pre-allocate all memory, push_back() should not throw. Even if push back throws, the C++ Standard guarantees that push_back) has no effect if something is thrown from it. Thus, if an exception is thrown, then it must have come from std::shared_ptr or read). Either way, you want the code to continue processing recording exactly one bool for each element in ai. Thus, this catch(...) handler calls push_back(false) to ensure there is a (false) bool added to ai when an exception is thrown Finally, return std::move (retval); main): Determining If The Filename Has The Pattern "yobYYYY.txt Although you could write code to determine if a filename has the pattern "yobYYYY.txt", that code would likely be more complicated than simply using the portion of the standard library! So the following instructions walk you through doing this. Nicely this will not only determine if the file name has the correct pattern, but, this will extract the value of YYYY into an integer variable as well. If you've not already, then read Josuttis chapter 14 on Regular Expressions. Look at the examples and what is output. The notation that can be used in regular expressions is detailed in 14.8 Since you know the current "entry" in the loop is a regular file, write the following code in your for loop: // determine if file anme is of the form yobYYYY.txt... static regex const baby_name_file_regex( R"(yob(di4).txt)"; Writing The yob_baby_name_file Class Write a class called "yob_baby_name_file" that inherits publicly from the "program_input" class. (This inheritance is not virtual: this code will only exploit the polymorphism of virtual functions.) The "yob_baby_name_file" class is to be written as follows: It must store the file name it is associated with as a private std:string member called fname_ It must store the year it is associated with as a private unsigned member called year_ It must have a single constructor with the following prototype: o yob_baby_name file(std::string fname, unsigned year) NOTE: Its constructor must not have anything inside its body (i.e., within 0)! . It must override the read) pure virtual function in program_input. o Hint: Start by writing "bool read) override". Writing yob_baby_name_file::read0) The yob_baby_name file::read member must do the following: Output to std::cout: o "Reading yob_baby_name_file "followed by o fname followed by o "for year " followed by oyear_followed by o n' i.e., a newline character). Return true when done. Back To main): Writing The Code When The Regex Matches With the yob_baby_name_file class defined, the code can now be written when the regex matches as a single C++ statement: Call the variable "all inputs" push_back) function passing in the result of this function call: Call make_shared yob_ baby_name_file> (...) where are the arguments: o fname, i.e., the file name that was matched), and, o mr[1].str converted to an unsigned number using stoul0 NOTE 1: mr[1].str) is the string corresponding to the (d4)) match. NOTE 2: Look up stoul() at cppreference.com to see how to convert a C++ std:string to an unsigned long. Pass in nullptr for the second argument. Last Step: Writing The Code For read_all_inputs0 Earlier you were given a trivial code stub for the read_all_inputs () function (which is called in the last line in main. Now that you are actually populating the all_inputs variable with data, it makes sense to write the code for this function! Do the following in the order listed Declare a variable called "retval" of type std::vector. (This will be the returned from the function.) Invoke std:vector's "reserve()" function passing in ai.size). o ai is the argument passed to read_all_inputs (see earlier stub) o The reserve calls tells the vector to ensure enough memory has been dynamically allocated to hold ai.size() elements * Use a range for loop to iterate over all elements in ai (i.e., the argument passed to the function) and within the loop: o ASIDE: Below "" is used to refer to the current element involved with the for loop iteration o Write try block with the single line of code Invoke the push back() function on retval and pass what i->read) returns. ASIDE: i is an instance of std:shared ptr. The ->is the indirection operator which allows one to invoke the read) function on the internally stored program_input* object. o In the catch(...) handler write the single line of code Call the push back() function on retval passing in false. ASIDE: Since reserve() was used to pre-allocate all memory, push_back() should not throw. Even if push back throws, the C++ Standard guarantees that push_back) has no effect if something is thrown from it. Thus, if an exception is thrown, then it must have come from std::shared_ptr or read). Either way, you want the code to continue processing recording exactly one bool for each element in ai. Thus, this catch(...) handler calls push_back(false) to ensure there is a (false) bool added to ai when an exception is thrown Finally, return std::move (retval)