-
Notifications
You must be signed in to change notification settings - Fork 0
/
lab9.cpp
174 lines (157 loc) · 5.18 KB
/
lab9.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
Lab 9 - Text File Word Counter
------------------------------
Create a program which will count and report on the number of occurrences of
distinct, case insensitive words in a text file.
The program should have a loop that:
1. Prompts the user to enter a file name. Terminate the loop and the program
if the user presses the Enter key only.
2. Verifies that a file with the name entered exists. If the file does
not exist, display an appropriate message and return to step 1.
3. Reads and displays the contents of the file.
4. Displays a count of the distinct words in the file.
5. Displays a sorted list of each of the distinct words in the file and the
number of occurrences of each word. Sort the list in descending order by
word count, ascending order by word.
A screen display and sample input files can be found in the Blackboard Review
folder.
Submit your�solution (main.cpp) as the file lab9_annnnnnn.cpp where annnnnnn
is your ACC student identification number.
*/
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
// Structure containing word and number of occurrences
struct WordCount {
string word; // the word
int count; // the number of occurances
WordCount(string s) {word=s; count=1;}
};
// Function Prototypes
string InputText(); // Prompt user for file name and get text
string Normalize(string); // Convert string to lowercase and remove punctuation
vector<WordCount> DistinctWords(string); // Build sorted vector of word count structures
int FindWord(string,vector<WordCount>); // Linear search for word in vector of structures
void DisplayResults(vector<WordCount>); // Display results
// Main
int main(int argc, char** argv) {
cout << "Lab 9 - Text File Word Counter" << endl;
cout << "------------------------------" << endl;
// Input text from file
string buffer = InputText();
while(buffer != "") {
// Display origonal text from file
cout << "\nThis is the text string read from the file" << endl;
cout << "------------------------------------------" << endl;
cout << buffer << endl << endl;
// Build vector of words and counts
vector<WordCount> words = DistinctWords(buffer);
// Display results
cout << "There are " << words.size() << " unique words in the above text." << endl;
cout << "--------------------------------------------" << endl << endl;
DisplayResults(words);
buffer = InputText();
}
return 0;
}
// Read contents of text file
string ReadText(string filename) {
fstream file(filename, ios::in);
string buffer = "";
if (file) {
stringstream ss;
ss << file.rdbuf();
if(!file.fail())
buffer = ss.str();
file.close();
}
return buffer;
}
// Prompt user for file name and read text
string InputText() {
string filename, buffer = "";
do {
cout << endl << "File name? ";
getline(cin, filename);
if(filename != "") {
buffer = ReadText(filename);
if(buffer == "")
cout << "File '" << filename << "' not found or empty";
}
}
while(filename != "" && buffer == "");
return buffer;
}
// Compare function used for word count structure sort
struct SortFunc {
bool operator ()(WordCount const& wc1, WordCount const& wc2) const {
bool swap = false;
// descending by count
if(wc1.count > wc2.count)
swap = true;
// ascending by word
else if(wc1.count==wc2.count && wc1.word < wc2.word)
swap = true;
return swap;
}
};
// Create and sort vector of structures of distinct words and counts
vector<WordCount> DistinctWords(string s) {
vector<WordCount> words;
istringstream ss(Normalize(s));
string word;
while (ss >> word) {
int index = FindWord(word, words);
if(index == -1) {
WordCount wc(word);
words.push_back(wc);
}
else
words[index].count += 1;
}
// Sort the vector and return
sort(words.begin(), words.end(), SortFunc());
return words;
}
// Convert string to lowercase and remove punctuation
string Normalize(string s) {
int max = s.length();
for(int i=0; i<max; i++)
s[i] = ispunct(s[i]) ? ' ' : tolower(s[i]);
return s;
}
// Perform linear search for word
int FindWord(string w, vector<WordCount> v) {
for(int i=0; i < v.size(); i ++)
if(v[i].word == w) return i;
return -1;
}
// Display column headings
void DisplayHeadings(int cols) {
for(int i = 0; i < cols; i++)
cout << setw(15) << left << "Word" << setw(5) << "Count" << "\t";
cout << endl;
for(int i = 0; i < cols; i++)
cout << "--------------------" << "\t";
cout << endl;
}
// Display results in columnar form
void DisplayResults(vector<WordCount> words) {
// Define number of columns
const int cols = 4;
// Display column headings
DisplayHeadings(cols);
// Calculate number of rows required for desired columns
int rows = words.size() / cols;
if(words.size() % cols) rows += 1;
// Display words and counts in rows of col columns
for(int row = 0; row < rows; row++) {
for(int i = row; i < words.size(); i += rows)
cout << setw(15) << left << words[i].word << setw(5) << right << words[i].count << "\t";
cout << endl;
}
}