diff --git a/ch08/ex8.13.14/data/record.txt b/ch08/ex8.13.14/data/record.txt new file mode 100644 index 00000000..805973dd --- /dev/null +++ b/ch08/ex8.13.14/data/record.txt @@ -0,0 +1,3 @@ +morgan 2015552368 8625550123 +drew 9735550130 +lee 6095550132 2015550175 8005550000 \ No newline at end of file diff --git a/ch08/ex8.13.14/main.cpp b/ch08/ex8.13.14/main.cpp new file mode 100644 index 00000000..51c1d9f5 --- /dev/null +++ b/ch08/ex8.13.14/main.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** +* @file main.cpp +* @author Queequeg +* @date 26 Nov 2014 +* @remark This code is for the exercises from C++ Primer 5th Edition +* @note +***************************************************************************/ +//! +//! Exercise 8.13 +//! Rewrite the phone number program from this section to read from a named +//! file rather than from cin. + +//! +//! Exercise 8.14 +//! Why did we declare entry and nums as const auto &? +//! We don't expect to modify the original data. + +#include +using std::cerr; +using std::cout; +using std::cin; +using std::endl; +using std::istream; +using std::ostream; + +#include +using std::ifstream; +using std::ofstream; + +#include +using std::istringstream; +using std::ostringstream; + +#include +using std::string; + +#include +using std::vector; + +struct PersonInfo { + string name; + vector phones; +}; + +bool read_record(istream& is, vector& people); +void format_record(ostream& os, const vector& people); + +//! fake functions that make the program compile +bool valid(const string &num){ return true; } +string format(const string &num){ return num; } + +int main() +{ + vector people; + + string filename; + cout << "Please input a record file name: "; + cin >> filename; + cout << endl; + ifstream fin(filename); + + if (read_record(fin, people)) + { + ofstream fout("data\\result.txt", ofstream::trunc); + format_record(fout, people); + } + else + { + cout << "Fail to open file " << filename << endl; + } + + return 0; +} + +bool read_record(istream& is, vector& people) +{ + if (is) + { + string line, word; // will hold a line and word from input, respectively + // read the input a line at a time until cin hits end-of-file (or another error) + while (getline(is, line)) + { + PersonInfo info; // create an object to hold this record's data + istringstream record(line); // bind record to the line we just read + record >> info.name; // read the name + while (record >> word) // read the phone numbers + info.phones.push_back(word); // and store them + people.push_back(info); // append this record to people + } + return true; + } + else + return false; +} + +void format_record(ostream& os, const vector& people) +{ + for (const auto &entry : people) + { + // for each entry in people + ostringstream formatted, badNums; // objects created on each loop + for (const auto &nums : entry.phones) + { + // for each number + if (!valid(nums)) + { + badNums << " " << nums; // string in badNums + } + else + // "writes" to formatted's string + formatted << " " << format(nums); + } + if (badNums.str().empty()) // there were no bad numbers + os << entry.name << " " // print the name + << formatted.str() << endl; // and reformatted numbers + else // otherwise, print the name and bad numbers + cerr << "input error: " << entry.name + << " invalid number(s) " << badNums.str() << endl; + } +} \ No newline at end of file diff --git a/ch11/ex11_3_4.cpp b/ch11/ex11_3_4.cpp index 05f19ca2..c2e1e473 100644 --- a/ch11/ex11_3_4.cpp +++ b/ch11/ex11_3_4.cpp @@ -17,10 +17,14 @@ //! Exercise 11.4 void word_count_pro(std::map &m) { - for(std::string word; std::cin >> word; /* */) + std::string word; + while(std::cin >> word) { - for(auto& ch : word) + for(auto& ch : word) ch = std::tolower(ch); + //! According to the erase-remove idiom. + //! For more information about the erase-remove idiom, please refer to + //! http://en.wikipedia.org/wiki/Erase-remove_idiom word.erase(std::remove_if(word.begin(), word.end(), ispunct), word.end()); ++m[word]; } @@ -32,7 +36,8 @@ void word_count_pro(std::map &m) void ex11_3() { std::map word_count; - for(std::string word; std::cin >> word; /* */) + std::string word; + while(std::cin >> word) { ++word_count[word]; for (const auto &elem : word_count) diff --git a/ch17/ex17.14.15.16/main.cpp b/ch17/ex17.14.15.16/main.cpp index f409cf1f..ebc80d94 100644 --- a/ch17/ex17.14.15.16/main.cpp +++ b/ch17/ex17.14.15.16/main.cpp @@ -3,7 +3,9 @@ * @author Queequeg * @date 19 Nov 2014 * @remark This code is for the exercises from C++ Primer 5th Edition - * @note + * @note There are some bugs in gcc(include the latest version 4.9.2) + * to handle regular expression.To compile this program, please + * turn to other compilers such as msvs2013 and clang. ***************************************************************************/ //! //! Exercise 17.14 @@ -21,9 +23,6 @@ //! initialized with "[^c]ei"? Test your program using that pattern to see //! whether your expectations were correct. -//! Note: There are some bugs in gcc(include the latest version 4.9.2) to handle -//! regular expression.To compile this program, please turn to other -//! compilers such as msvs2013 and clang. #include using std::cout; diff --git a/ch17/ex17.17.18/main.cpp b/ch17/ex17.17.18/main.cpp new file mode 100644 index 00000000..37f684de --- /dev/null +++ b/ch17/ex17.17.18/main.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** +* @file main.cpp +* @author Queequeg +* @date 25 Nov 2014 +* @remark This code is for the exercises from C++ Primer 5th Edition +* @note There are some bugs in gcc(include the latest version 4.9.2) +* to handle regular expression.To compile this program, please +* turn to other compilers such as msvs2013 and clang. +***************************************************************************/ +//! +//! Exercise 17.17 +//! Update your program so that it finds all the words in an input sequence +//! that violiate the "ei" grammar rule. + +//! +//! Exercise 17.18 +//! Revise your program to ignore words that contain "ei" but are not +//! misspellings, such as "albeit" and "neighbor." + +#include +using std::cout; +using std::cin; +using std::endl; + +#include +using std::string; + +#include +using std::regex; +using std::sregex_iterator; + +int main() +{ + string s; + cout << "Please input a sequence of words:" << endl; + getline(cin, s); + cout << endl; + cout << "Word(s) that violiate the \"ei\" grammar rule:" << endl; + string pattern("[^c]ei"); + pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*"; + regex r(pattern, regex::icase); + for (sregex_iterator it(s.begin(), s.end(), r), end_it; + it != end_it; ++it) + cout << it->str() << endl; + + return 0; +} \ No newline at end of file diff --git a/ch17/ex17.19.20/main.cpp b/ch17/ex17.19.20/main.cpp new file mode 100644 index 00000000..93e12cbc --- /dev/null +++ b/ch17/ex17.19.20/main.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** +* @file main.cpp +* @author Queequeg +* @date 26 Nov 2014 +* @remark This code is for the exercises from C++ Primer 5th Edition +* @note There are some bugs in gcc(include the latest version 4.9.2) +* to handle regular expression.To compile this program, please +* turn to other compilers such as msvs2013 and clang. +***************************************************************************/ +//! +//! Exercise 17.19 +//! Why is it okay to call m[4].str() without first checking whether m[4] +//! was matched? +//! We expect that the two delimiters in m[4] and m[6] are the same. +//! If m[4](or m[6]) is mismatched, m[4].str()(or m[6].str() respectively) +//! returns an empty string which can also be compared with the other +//! delimiter. + +//! +//! Exercise 17.20 +//! Write your own version of the program to validate phone numbers. + +#include +using std::cout; +using std::cin; +using std::endl; + +#include +using std::string; + +#include +using std::regex; +using std::sregex_iterator; +using std::smatch; + +bool valid(const smatch& m); + +int main() +{ + string phone = + "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})"; + regex r(phone); + smatch m; + string s; + bool valid_record; + //! read each record from the input file + while (getline(cin, s)) + { + valid_record = false; + + //! for each matching phone number + for (sregex_iterator it(s.begin(), s.end(), r), end_it; + it != end_it; ++it) + { + valid_record = true; + //! check whether the number's formatting is valid + if (valid(*it)) + cout << "valid phone number: " << it->str() << endl; + else + cout << "invalid phone number: " << it->str() << endl; + } + + if (!valid_record) + cout << "invalid record!" << endl; + } + return 0; +} + +bool valid(const smatch& m) +{ + //! if there is an open parenthesis before the area code + if (m[1].matched) + //! the area code must be followed by a close parenthesis + //! and followed immediately by the rest of the number or a space + return m[3].matched + && (m[4].matched == 0 || m[4].str() == " "); + else + //! then there can't be a close after the area code + //! the delimiters between the other two components must match + return !m[3].matched + && m[4].str() == m[6].str(); +} \ No newline at end of file diff --git a/ch17/ex17.21/data/record.txt b/ch17/ex17.21/data/record.txt new file mode 100644 index 00000000..f86d4228 --- /dev/null +++ b/ch17/ex17.21/data/record.txt @@ -0,0 +1,4 @@ +green (9998886666 9996668888 +morgan 2015552368 8625550123 +drew 9735550130 +lee 6095550132 2015550175 8005550000 diff --git a/ch17/ex17.21/main.cpp b/ch17/ex17.21/main.cpp new file mode 100644 index 00000000..74440429 --- /dev/null +++ b/ch17/ex17.21/main.cpp @@ -0,0 +1,145 @@ +/*************************************************************************** +* @file main.cpp +* @author Queequeg +* @date 26 Nov 2014 +* @remark This code is for the exercises from C++ Primer 5th Edition +* @note +***************************************************************************/ +//! +//! Exercise 17.21 +//! Rewrite your phone number program from 8.3.2 (p. 323) to use the +//! valid function defined in this section. + +#include +using std::cerr; +using std::cout; +using std::cin; +using std::endl; +using std::istream; +using std::ostream; + +#include +using std::ifstream; +using std::ofstream; + +#include +using std::istringstream; +using std::ostringstream; + +#include +using std::string; + +#include +using std::vector; + +#include +using std::regex; +using std::sregex_iterator; +using std::smatch; + +struct PersonInfo { + string name; + vector phones; +}; + +bool valid(const smatch& m); +bool read_record(istream& is, vector& people); +void format_record(ostream& os, const vector& people); + +//! fake function that makes the program compile +string format(const string &num){ return num; } + +int main() +{ + vector people; + + string filename; + cout << "Please input a record file name: "; + cin >> filename; + cout << endl; + ifstream fin(filename); + + if (read_record(fin, people)) + { + ofstream fout("data\\result.txt", ofstream::trunc); + format_record(fout, people); + } + else + { + cout << "Fail to open file " << filename << endl; + } + + return 0; +} + +bool valid(const smatch& m) +{ + //! if there is an open parenthesis before the area code + if (m[1].matched) + //! the area code must be followed by a close parenthesis + //! and followed immediately by the rest of the number or a space + return m[3].matched + && (m[4].matched == 0 || m[4].str() == " "); + else + //! then there can't be a close after the area code + //! the delimiters between the other two components must match + return !m[3].matched + && m[4].str() == m[6].str(); +} + +bool read_record(istream& is, vector& people) +{ + if (is) + { + string line, word; //! will hold a line and word from input, respectively + //! read the input a line at a time until cin hits end-of-file (or another error) + while (getline(is, line)) + { + PersonInfo info; //! create an object to hold this record's data + istringstream record(line); //! bind record to the line we just read + record >> info.name; //! read the name + while (record >> word) //! read the phone numbers + info.phones.push_back(word); //! and store them + people.push_back(info); //! append this record to people + } + return true; + } + else + return false; +} + +void format_record(ostream& os, const vector& people) +{ + string phone = + "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})"; + regex r(phone); + smatch m; + + for (const auto &entry : people) + { + //! for each entry in people + ostringstream formatted, badNums; //! objects created on each loop + for (const auto &nums : entry.phones) + { + for (sregex_iterator it(nums.begin(), nums.end(), r), end_it; + it != end_it; ++it) + { + //! for each number + //! check whether the number's formatting is valid + if (!valid(*it)) + //! string in badNums + badNums << " " << nums; + else + //! "writes" to formatted's string + formatted << " " << format(nums); + } + } + + if (badNums.str().empty()) //! there were no bad numbers + os << entry.name << " " //! print the name + << formatted.str() << endl; //! and reformatted numbers + else //! otherwise, print the name and bad numbers + cerr << "input error: " << entry.name + << " invalid number(s) " << badNums.str() << endl; + } +} \ No newline at end of file