diff --git a/README.md b/README.md index 7370226b..abbcf4e6 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ - [Chapter 4. Expressions](ch04/README.md) - [Chapter 5. Statements](ch05/README.md) - [Chapter 6. Functions](ch06/README.md) - - [Chapter 7. Classes](ch07) - - [Chapter 8. The IO Library](ch08) + - [Chapter 7. Classes](ch07/README.md) - Part II: The C++ Library + - [Chapter 8. The IO Library](ch08/README.md) - [Chapter 9. Sequential Containers](ch09) - [Chapter 10. Generic Algorithms](ch10) - [Chapter 11. Associative Containers](ch11) diff --git a/ch08/README.md b/ch08/README.md new file mode 100644 index 00000000..c136c5a8 --- /dev/null +++ b/ch08/README.md @@ -0,0 +1,47 @@ +# Chapter 8. The IO Library + +## Exercise 8.1: +>Write a function that takes and returns an istream&. The function should read the stream until it hits end-of-file. The function should print what it reads to the standard output. Reset the stream so that it is valid before returning the stream. + +```cpp +istream& func(istream &is) +{ + std::string buf; + while (is >> buf) + std::cout << buf << std::endl; + is.clear(); + return is; +} +``` + +## [Exercise 8.2](ex8_02.cpp) + +## Exercise 8.3: +>What causes the following while to terminate? +```cpp +while (cin >> i) /* ... */ +``` + +putting `cin` in an error state cause to terminate. such as `eofbit`, `failbit` and `badbit`. + +## [Exercise 8.4](ex8_04.cpp) +## [Exercise 8.5](ex8_05.cpp) +## [Exercise 8.6](ex8_06.cpp) +## [Exercise 8.7](ex8_07.cpp) +## [Exercise 8.8](ex8_08.cpp) +## [Exercise 8.9](ex8_09.cpp) +## [Exercise 8.10](ex8_10.cpp) +## [Exercise 8.11](ex8_11.cpp) + +## Exercise 8.12: +>Why didn’t we use in-class initializers in PersonInfo? + +Cause we need a aggregate class here. so it should have no in-class initializers. + +## [Exercise 8.13](ex8_13.cpp) + +## Exercise 8.14: +>Why did we declare entry and nums as const auto &? + +- cause they are all class type, not the built-in type. so **reference** more effective. +- output shouldn't change their values. so we added the `const`. diff --git a/ch08/ex8.13.14/main.cpp b/ch08/ex8.13.14/main.cpp deleted file mode 100644 index 51c1d9f5..00000000 --- a/ch08/ex8.13.14/main.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/*************************************************************************** -* @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/ch08/ex8_02.cpp b/ch08/ex8_02.cpp new file mode 100644 index 00000000..35e78dfd --- /dev/null +++ b/ch08/ex8_02.cpp @@ -0,0 +1,27 @@ +// +// ex8_02.cpp +// Exercise 8.2 +// +// Created by pezy on 11/27/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Test your function by calling it, passing cin as an argument + +#include +using std::istream; + +istream& func(istream &is) +{ + std::string buf; + while (is >> buf) + std::cout << buf << std::endl; + is.clear(); + return is; +} + +int main() +{ + istream& is = func(std::cin); + std::cout << is.rdstate() << std::endl; + return 0; +} diff --git a/ch08/ex8_04.cpp b/ch08/ex8_04.cpp new file mode 100644 index 00000000..01430f04 --- /dev/null +++ b/ch08/ex8_04.cpp @@ -0,0 +1,37 @@ +// +// ex8_04.cpp +// Exercise 8.4 +// +// Created by pezy on 11/9/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Write a function to open a file for input and read its contents into a vector of strings, +// storing each line as a separate element in the vector. + +#include +#include +#include +#include + +using std::vector; using std::string; using std::ifstream; using std::cout; using std::endl; + +void ReadFileToVec(const string& fileName, vector& vec) +{ + ifstream ifs(fileName); + if (ifs) + { + string buf; + while (std::getline(ifs, buf)) + vec.push_back(buf); + } +} + +int main() +{ + vector vec; + ReadFileToVec("../data/book.txt", vec); + for (const auto &str : vec) + cout << str << endl; + return 0; +} + diff --git a/ch08/ex8_05.cpp b/ch08/ex8_05.cpp new file mode 100644 index 00000000..b54658e3 --- /dev/null +++ b/ch08/ex8_05.cpp @@ -0,0 +1,37 @@ +// +// ex8_05.cpp +// Exercise 8.5 +// +// Created by pezy on 11/9/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Rewrite the previous program to store each word in a separate element. +// @See ex8_04.cpp + +#include +#include +#include +#include + +using std::vector; using std::string; using std::ifstream; using std::cout; using std::endl; + +void ReadFileToVec(const string& fileName, vector& vec) +{ + ifstream ifs(fileName); + if (ifs) + { + string buf; + while (ifs >> buf) + vec.push_back(buf); + } +} + +int main() +{ + vector vec; + ReadFileToVec("../data/book.txt", vec); + for (const auto &str : vec) + cout << str << endl; + return 0; +} + diff --git a/ch08/ex8_06.cpp b/ch08/ex8_06.cpp new file mode 100644 index 00000000..afd0023c --- /dev/null +++ b/ch08/ex8_06.cpp @@ -0,0 +1,47 @@ +// +// ex8_06.cpp +// Exercise 8.6 +// +// Created by pezy on 11/27/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Rewrite the bookstore program from ¡ì7.1.1 (p.256) to read its transactions from a file. +// Pass the name of the file as an argument to main (¡ì6.2.5, p.218). +// @See ex7_26.h (use the Sales_data) +// @Run give a parameter: "../data/book.txt" +// @Output 0-201-78345-X 5 110 +// 0-201-78346-X 9 839.2 + +#include +#include + +#include "../ch07/ex7_26.h" +using std::ifstream; using std::cout; using std::endl; using std::cerr; + +int main(int argc, char **argv) +{ + ifstream input(argv[1]); + + Sales_data total; + if (read(input, total)) + { + Sales_data trans; + while (read(input, trans)) + { + if (total.isbn() == trans.isbn()) + total.combine(trans); + else + { + print(cout, total) << endl; + total = trans; + } + } + print(cout, total) << endl; + } + else + { + cerr << "No data?!" << endl; + } + + return 0; +} diff --git a/ch08/ex8_07.cpp b/ch08/ex8_07.cpp new file mode 100644 index 00000000..d9fa3939 --- /dev/null +++ b/ch08/ex8_07.cpp @@ -0,0 +1,46 @@ +// +// ex8_07.cpp +// Exercise 8.7 +// +// Created by pezy on 11/28/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Revise the bookstore program from the previous section to write its output to a file. +// Pass the name of that file as a second argument to main. +// @See ex8_06.cpp +// @Run give a parameter: "../data/book.txt ../data/out.txt" + +#include +#include + +#include "../ch07/ex7_26.h" +using std::ifstream; using std::ofstream; using std::endl; using std::cerr; + +int main(int argc, char **argv) +{ + ifstream input(argv[1]); + ofstream output(argv[2]); + + Sales_data total; + if (read(input, total)) + { + Sales_data trans; + while (read(input, trans)) + { + if (total.isbn() == trans.isbn()) + total.combine(trans); + else + { + print(output, total) << endl; + total = trans; + } + } + print(output, total) << endl; + } + else + { + cerr << "No data?!" << endl; + } + + return 0; +} diff --git a/ch08/ex8_08.cpp b/ch08/ex8_08.cpp new file mode 100644 index 00000000..3747ddd4 --- /dev/null +++ b/ch08/ex8_08.cpp @@ -0,0 +1,46 @@ +// +// ex8_08.cpp +// Exercise 8.8 +// +// Created by pezy on 11/28/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Revise the program from the previous exercise to append its output to its given file. +// Run the program on the same output file at least twice to ensure that the data are preserved +// @See ex8_07.cpp +// @Run give a parameter: "../data/book.txt ../data/out.txt" + +#include +#include + +#include "../ch07/ex7_26.h" +using std::ifstream; using std::ofstream; using std::endl; using std::cerr; + +int main(int argc, char **argv) +{ + ifstream input(argv[1]); + ofstream output(argv[2], ofstream::app); + + Sales_data total; + if (read(input, total)) + { + Sales_data trans; + while (read(input, trans)) + { + if (total.isbn() == trans.isbn()) + total.combine(trans); + else + { + print(output, total) << endl; + total = trans; + } + } + print(output, total) << endl; + } + else + { + cerr << "No data?!" << endl; + } + + return 0; +} diff --git a/ch08/ex8_09.cpp b/ch08/ex8_09.cpp new file mode 100644 index 00000000..2926d5dd --- /dev/null +++ b/ch08/ex8_09.cpp @@ -0,0 +1,29 @@ +// +// ex8_09.cpp +// Exercise 8.9 +// +// Created by pezy on 11/29/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Use the function you wrote for the first exercise in § 8.1.2 (p.314) to print the contents of an istringstream object. +// @See Exercise 8.1 + +#include +#include +using std::istream; + +istream& func(istream &is) +{ + std::string buf; + while (is >> buf) + std::cout << buf << std::endl; + is.clear(); + return is; +} + +int main() +{ + std::istringstream iss("hello"); + func(iss); + return 0; +} diff --git a/ch08/ex8_10.cpp b/ch08/ex8_10.cpp index 56a0b2f2..6b1a9f04 100644 --- a/ch08/ex8_10.cpp +++ b/ch08/ex8_10.cpp @@ -1,83 +1,42 @@ -//! @Alan -//! -//! Exercise 8.10: -//! Write a program to store each line from a file in a vector. -//! Now use an istringstream to read each element from the vector a word at a time. -//! -//! - +// +// ex8_10.cpp +// Exercise 8.10 +// +// Created by pezy on 11/29/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Write a program to store each line from a file in a vector. +// Now use an istringstream to read each element from the vector a word at a time. #include -#include #include #include #include +#include +using std::vector; using std::string; using std::ifstream; using std::istringstream; using std::cout; using std::endl; using std::cerr; -std::vector &ex84(const std::string &fn, std::vector &v); -std::vector &ex85(const std::string &fn, std::vector &v); - -//! Exercise 8.10 int main() { - std::vector v; - v = ex84("test.txt", v); - for (std::vector::iterator it = v.begin(); it != v.end(); ++it) - { - std::istringstream sfin(*it); - std::string s; - while(sfin>>s) - { - std::cout< &ex85(const std::string &fn, std::vector &v) -{ - std::string word; - std::ifstream fin(fn); - - if(fin.is_open()) - { - std::cout<<"opened\n"; - } - else - { - std::cout<<"failed\n"; - } - - while(fin>>word) - { - v.push_back(word); - } - - return v; -} - - -std::vector &ex84(const std::string &fn, std::vector &v) -{ - std::string line; - std::ifstream fin(fn); - - if(fin.is_open()) - { - std::cout<<"opened\n"; - } - else + ifstream ifs("../data/book.txt"); + if (!ifs) { - std::cout<<"failed\n"; + cerr << "No data?" << endl; + return -1; } - - while(std::getline(fin,line)) + + vector vecLine; + string line; + while (getline(ifs, line)) + vecLine.push_back(line); + + for (auto &s : vecLine) { - v.push_back(line); + istringstream iss(s); + string word; + while (iss >> word) + cout << word << endl; } - - return v; + + return 0; } - - diff --git a/ch08/ex8_11.cpp b/ch08/ex8_11.cpp new file mode 100644 index 00000000..56f545c3 --- /dev/null +++ b/ch08/ex8_11.cpp @@ -0,0 +1,48 @@ +// +// ex8_11.cpp +// Exercise 8.11 +// +// Created by pezy on 11/29/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief The program in this section defined its istringstream object inside the outer while loop. +// What changes would you need to make if record were defined outside that loop? +// Rewrite the program, moving the definition of record outside the while, and see whether you thought of all the changes that are needed. + +#include +#include +#include +#include +using std::vector; using std::string; using std::cin; using std::istringstream; + +struct PersonInfo { + string name; + vector phones; +}; + +int main() +{ + string line, word; + vector people; + istringstream record; + while (getline(cin, line)) + { + PersonInfo info; + record.clear(); + record.str(line); + record >> info.name; + while (record >> word) + info.phones.push_back(word); + people.push_back(info); + } + + for (auto &p : people) + { + std::cout << p.name << " "; + for (auto &s : p.phones) + std::cout << s << " "; + std::cout << std::endl; + } + + return 0; +} diff --git a/ch08/ex8_13.cpp b/ch08/ex8_13.cpp new file mode 100644 index 00000000..5844ae62 --- /dev/null +++ b/ch08/ex8_13.cpp @@ -0,0 +1,73 @@ +// +// ex8_13.cpp +// Exercise 8.13 +// +// Created by pezy on 11/29/14. +// Copyright (c) 2014 pezy. All rights reserved. +// +// @Brief Rewrite the phone number program from this section to read from +// a named file rather than from cin. +// @See ex8_11.cpp + +#include +#include +#include +#include +#include + +using std::vector; using std::string; using std::cin; using std::istringstream; +using std::ostringstream; using std::ifstream; using std::cerr; using std::cout; using std::endl; + +struct PersonInfo { + string name; + vector phones; +}; + +bool valid(const string& str) +{ + return isnumber(str[0]); +} + +string format(const string& str) +{ + return str.substr(0,3) + "-" + str.substr(3,3) + "-" + str.substr(6); +} + +int main() +{ + ifstream ifs("../data/phonenumbers.txt"); + if (!ifs) + { + cerr << "no phone numbers?" << endl; + return -1; + } + + string line, word; + vector people; + istringstream record; + while (getline(ifs, line)) + { + PersonInfo info; + record.clear(); + record.str(line); + record >> info.name; + while (record >> word) + info.phones.push_back(word); + people.push_back(info); + } + + for (const auto &entry : people) + { + ostringstream formatted, badNums; + for (const auto &nums : entry.phones) + if (!valid(nums)) badNums << " " << nums; + else formatted << " " << format(nums); + if (badNums.str().empty()) + cout << entry.name << " " << formatted.str() << endl; + else + cerr << "input error: " << entry.name + << " invalid number(s) " << badNums.str() << endl; + } + + return 0; +} diff --git a/ch08/ex8_4_5.cpp b/ch08/ex8_4_5.cpp deleted file mode 100644 index 737fd761..00000000 --- a/ch08/ex8_4_5.cpp +++ /dev/null @@ -1,83 +0,0 @@ -//! @Alan -//! -//! Exercise 8.4: -//! Write a function to open a file for input and read its contents into a vector -//! of strings, storing each line as a separate element in the vector. -// Note: the txt file must be placed at the folder of the exe file rather than the -// source file. -//! -//! Exercise 8.5: -//! Rewrite the previous program to store each word in a separate element. -//! -#include -#include -#include -#include - -std::vector &ex84(const std::string &fn, std::vector &v); -std::vector &ex85(const std::string &fn, std::vector &v); - -int main() -{ - std::vector v; - ex84("test.txt",v); - std::cout << v[0] < w; - w = ex85("test.txt",w); - - for (std::vector::iterator it = w.begin(); it != w.end(); ++it) - { - std::cout<<*it; - } - - return 0; -} - -std::vector &ex85(const std::string &fn, std::vector &v) -{ - std::string word; - std::ifstream fin(fn); - - if(fin.is_open()) - { - std::cout<<"opened\n"; - } - else - { - std::cout<<"failed\n"; - } - - while(fin>>word) - { - v.push_back(word); - } - - return v; -} - - -std::vector &ex84(const std::string &fn, std::vector &v) -{ - std::string line; - std::ifstream fin(fn); - - if(fin.is_open()) - { - std::cout<<"opened\n"; - } - else - { - std::cout<<"failed\n"; - } - - while(std::getline(fin,line)) - { - v.push_back(line); - } - - return v; -} - - diff --git a/ch08/ex8.13.14/data/record.txt b/data/phonenumbers.txt similarity index 100% rename from ch08/ex8.13.14/data/record.txt rename to data/phonenumbers.txt