I'm a novice in C++
. I want to do three things:
- Get the number of lines in the file
- Get the number of total words in the file
- Get each frequency of each "unique word".
Here, "unique word" is simply the same set of characters delimited by whitespace; different punctuation and casing are considered different.
I am using a linked list to achieve this.
I want to ask improvements on a number of things:
If there's a better way to get whitespace delimitation than using
getline
and converting the results to astringstream
If there's a better way to automatically add nodes to the the linked list if I haven't found a node with the matching word.
I have to initialize the linked list with a null head, and therefore have to remove it when I'm printing results. Surely there must be a better way of initialization
I realize repeated searches through the linked list is not efficient, but that is not the concern currently, I am just trying to get used to using things in C++
.
Code:
# include <iostream>
# include <fstream>
# include <sstream>
# include <string>
# include <algorithm>
using namespace std;
// Node
struct Node {
string word;
int count = 1;
Node * next;
};
// Checks if string is whitespace
bool whiteSpace(const string& str){
return (str == "\r" || str=="\n" || str ==" " || str == "" || str == "\t");
}
// Prints contents of linked list
void printList(Node* head){
Node * search = head;
while(search->next != nullptr){
cout << search->word << " : " << search->count << endl;
search = search->next;
}
}
int main(int argc, char* argv[]){
// Initiliazation of file I/O
ifstream inFile;
string fileName;
cout << "Enter file name: ";
getline(cin, fileName);
inFile.open(fileName.c_str());
string str;
int lineNum = 0;
int wordCount = 0;
// Initialization of linked list
Node * head = new Node();
head-> next = nullptr;
// For each line
while(getline(inFile, str)){
/*
###############CODE REVIEW:#################
THIS PART SEEMS OVERLY REDUNDANT AND INEFFICIENT!!
Going from a fstream to read each line, and then to convert each string into a
stringstream. Better options?
*/
stringstream ss;
ss << str;
// For each word in the line
while(ss){
string s;
ss >> s;
// Ignore whitespace as words
if (!whiteSpace(s)){
wordCount ++;
Node * search = head;
/*
###############CODE REVIEW:#################
This FOUND boolean seems inefficient!
Refer to below.
*/
bool found = false;
// Search the entire linked list
while(search->next != nullptr){
// If we've found the word in the linked list, update its count
if(search->word == s){
search->count ++;
found = true;
break;
}
search = search->next;
}
/*
###############CODE REVIEW:#################
This FOUND boolean seems inefficient!
For each word, I need to check if it's found or not -- even if it's found!
There must be a better way to increase the length of the linked list if we haven't
found a node with the appropriate data.
*/
if(!found){
Node * newNode = new Node();
search->next = newNode;
newNode->word = s;
}
}
}
// Update line number for each getline
lineNum ++;
}
cout << "Number of lines: " << lineNum << endl;
cout << "Number of words: " << wordCount << endl;
/*
###############CODE REVIEW:#################
Because I initialized with a null head, I have to start at the 2nd node instead of the first one.
*/
head = head->next;
printList(head);
inFile.close();
return 0;
}