Work through exercise 1.3.

This commit is contained in:
2017-12-18 23:07:44 -08:00
parent 06d3db4370
commit 26a0563e4f
6 changed files with 565 additions and 5 deletions

View File

@@ -3,5 +3,6 @@ AM_CPPFLAGS += -Wwrite-strings -Wmissing-declarations -Wno-long-long -Werror
AM_CPPFLAGS += -Wunused-variable -std=c++14 -D_XOPEN_SOURCE -O0 -g -I.
AM_CPPFLAGS += -fno-elide-constructors -Weffc++
bin_PROGRAMS := ch01ex01
ch01ex01_SOURCES := ch01ex01.cc
bin_PROGRAMS := ch01ex01 ch01ex03
ch01ex01_SOURCES := ch01ex01.cc
ch01ex03_SOURCES := ch01ex03.cc

View File

@@ -1,7 +1,10 @@
#include <cstdlib>
#include <queue>
#include <deque>
#include <fstream>
#include <iostream>
#include <set>
#include <sstream>
#include <stack>
#include <string>
using namespace std;
@@ -18,18 +21,214 @@ using namespace std;
static void
problem1(const char *path)
{
ifstream ifs(path);
string line;
stack<string> s;
if (!ifs) {
return;
}
while (getline(ifs, line)) {
s.push(line);
}
while (!s.empty()) {
cout << s.top() << endl;
s.pop();
}
ifs.close();
return;
}
// Read the first 50 lines of input and then write them out in reverse
// order. Read the next 50 lines and then write them out in reverse
// order. Do this until there are no more lines left to read, at which
// point any remaining lines should be output in reverse order.
//
// In other words, your output will start with the 50th line, then the
// 49th, then the 48th, and so on down to the first line. This will be
// followed by the 100th line, followed by the 99th, and so on down to
// the 51st line. And so on.
//
// Your code should never have to store more than 50 lines at any given
// time.
static void
problem2(const char *path)
{
ifstream ifs(path);
string line;
stack<string> s;
bool stop = false;
if (!ifs) {
return;
}
while (!stop) {
while (s.size() < 50) {
if (getline(ifs, line)) {
s.push(line);
} else {
stop = true;
break;
}
}
while (!s.empty()) {
cout << s.top() << endl;
s.pop();
}
}
}
// Read the input one line at a time. At any point after reading the
// first 42 lines, if some line is blank (i.e., a string of length 0), then
// output the line that occured 42 lines prior to that one. For example,
// if Line 242 is blank, then your program should output line 200.
// This program should be implemented so that it never stores more
// than 43 lines of the input at any given time.
static void
problem3(const char *path)
{
ifstream ifs(path);
string line;
deque<string> q;
if (!ifs) {
return;
}
while (getline(ifs, line)) {
if (q.size() > 42) {
q.pop_back();
}
q.push_front(line);
if (line == "") {
cout << q.back() << endl;
}
}
}
// Read the input one line at a time and write each line to the output
// if it is not a duplicate of some previous input line. Take special care
// so that a file with a lot of duplicate lines does not use more memory
// than what is required for the number of unique lines.
static void
problem4(const char *path)
{
ifstream ifs(path);
string line;
set<string> set;
if (!ifs) {
return;
}
while (getline(ifs, line)) {
if (set.count(line) == 0) {
cout << line << endl;
set.insert(line);
}
}
}
// Read the input one line at a time and write each line to the output
// only if you have already read this line before. (The end result is that
// you remove the first occurrence of each line.) Take special care so
// that a file with a lot of duplicate lines does not use more memory
// than what is required for the number of unique lines.
static void
problem5(const char *path)
{
ifstream ifs(path);
string line;
set<string> set;
if (!ifs) {
return;
}
while (getline(ifs, line)) {
if (set.count(line) == 1) {
cout << line << endl;
} else {
set.insert(line);
}
}
}
// main should just execute the problems in sequence.
int
main(int argc, char *argv[])
{
if (argc != 2) {
int problem = -1;
if (argc < 2) {
cerr << "No input file specified, exiting." << endl;
exit(1);
}
if (argc == 3) {
problem = stoi(string(argv[2]));
}
if (problem > 0) {
switch (problem) {
case 1:
cout << "*** PROBLEM 1 ***" << endl;
problem1(argv[1]);
cout << endl << endl;
break;
case 2:
cout << "*** PROBLEM 2 ***" << endl;
problem2(argv[1]);
cout << endl << endl;
break;
case 3:
cout << "*** PROBLEM 3 ***" << endl;
problem3(argv[1]);
cout << endl << endl;
break;
case 4:
cout << "*** PROBLEM 4 ***" << endl;
problem4(argv[1]);
cout << endl << endl;
break;
case 5:
cout << "*** PROBLEM 5 ***" << endl;
problem5(argv[1]);
cout << endl << endl;
break;
default:
cerr << "Unknown problem " << problem << endl;
exit(1);
}
exit(0);
}
cout << "*** PROBLEM 1 ***" << endl;
problem1(argv[1]);
cout << endl << endl;
cout << "*** PROBLEM 2 ***" << endl;
problem2(argv[1]);
cout << endl << endl;
cout << "*** PROBLEM 3 ***" << endl;
problem3(argv[1]);
cout << endl << endl;
cout << "*** PROBLEM 4 ***" << endl;
problem4(argv[1]);
cout << endl << endl;
cout << "*** PROBLEM 5 ***" << endl;
problem5(argv[1]);
cout << endl << endl;
}

67
src/ch01ex03.cc Normal file
View File

@@ -0,0 +1,67 @@
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int
main(int argc, char *argv[])
{
stack<char> s;
for (int i = 1; i < argc; i++) {
string ms(argv[i]);
bool matched = true;
for (auto c : ms) {
switch (c) {
case '{':
case '(':
case '[':
s.push(c);
break;
case '}':
if (s.top() != '{') {
cerr << "Saw '" << s.top() << "' but expected '{'." << endl;
matched = false;
}
else {
s.pop();
}
break;
case ']':
if (s.top() != '[') {
cerr << "Saw '" << s.top() << "' but expected '['." << endl;
matched = false;
}
else {
s.pop();
}
break;
case ')':
if (s.top() != '(') {
cerr << "Saw '" << s.top() << "' but expected '('." << endl;
matched = false;
}
else {
s.pop();
}
break;
default:
cerr << "Invalid character in string: " << c << endl;
matched = false;
}
if (!matched) {
break;
}
}
if (!matched) {
cerr << "'" << ms << "' is not a matched string." << endl;
}
else {
cout << "'" << ms << "' is a matched string." << endl;
}
}
}