234 lines
4.9 KiB
C++
234 lines
4.9 KiB
C++
#include <cstdlib>
|
|
#include <deque>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <set>
|
|
#include <sstream>
|
|
#include <stack>
|
|
#include <string>
|
|
|
|
using namespace std;
|
|
|
|
// Solve the following problems by reading a text file one line at a time
|
|
// and performing operations on each line in the appropriate data structure(s).
|
|
// Your implementations should be fast enough that even files containing
|
|
// a million lines can be processed in a few seconds.
|
|
|
|
|
|
// Read the input one line at a time and then write the lines out in
|
|
// reverse order, so that the last input line is printed first, then the
|
|
// second last input line, and so on.
|
|
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[])
|
|
{
|
|
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;
|
|
} |