In: Computer Science
Map word scanning in C++
For some context, I've been working on a program in which I must
enter in words and clear them of any potential punctuations. If a
word has punctuation in the middle of the word, I must ignore the
letters AFTER the punctuation and delete the punctuation as well.
For example if I enter in "fish_net" I will only get "fish" back. I
must also keep track of the occurrence of each word as well as
number of words.
Here's my problem, I'm using a do while loop to continuously enter
in words and break from it when needed. When I do, my output is
supposed to be separate words, but they are getting merged with
each other and counting it as one word. For example, lets say I
enter in the words: "hello" "there" "done". The INTENDED output
should be the following: hello 1 (newline) there 1 (newline) done
1. However, the output CURRENTLY goes like this: hello 1 (newline)
hellothere 1 (newline) hellotheredone 1. Mind you that the numbers
after the words are the number of occurrences that word is
entered.
#include <iostream>
#include<map>
#include<string>
#include <algorithm>
using namespace std;
void get_words(map<string, int>&);
void print_words(const map<string, int>&);
void clean_entry(const string&, string&);
int main()
{
map<string,int>m;
get_words(m);
print_words(m);
}
void get_words(map<string, int>&m)
{
string word, cleaned_words = "";
cout << "Enter in a string of text: ";
do
{
cin >> word;
clean_entry(word,
cleaned_words);
if (cleaned_words.length() !=
0)
{
m[cleaned_words]++;//inserting clean words into map
}
} while (word != "done");
}
void print_words(const map<string, int>&m)
{
int non_empty_words = 0;
for (auto it = m.begin(); it != m.end(); it++)
{
cout << it->first <<
" " << it->second << endl;
non_empty_words +=
it->second;
}
cout << "Non-empty words: " <<
non_empty_words << endl;
cout << "Words: " << m.size();
}
void clean_entry(const string&words,
string&cleaned_words)
{
int len = words.length();
int i = 0;
while (i < len && ispunct(words[i]))
i++;//parse through initial punctuation (make sure that punctuation
is deleted while leaving word intact if in front or back)
while (i < len &&
!ispunct(words[i]))//while we come across any words with no
punctuation, we add it to cleaned words
{
cleaned_words += words[i];
i++;
}
}
Modified code:
#include <iostream>
#include<map>
#include<string>
#include <algorithm>
using namespace std;
void get_words(map<string, int>&);
void print_words(const map<string, int>&);
void clean_entry(const string&, string&);
int main() {
map<string,int>m;
get_words(m);
print_words(m);
}
void get_words(map<string, int>&m) {
string word, cleaned_words = "";
cout << "Enter in a string of text: ";
do {
cin >> word;
cleaned_words = "";
clean_entry(word, cleaned_words);
if (cleaned_words.length() != 0) {
m[cleaned_words]++;//inserting clean words into map
}
} while (word != "done");
}
void print_words(const map<string, int>&m) {
int non_empty_words = 0;
for (auto it = m.begin(); it != m.end(); it++) {
cout << it->first << " " << it->second << endl;
non_empty_words += it->second;
}
cout << "Non-empty words: " << non_empty_words << endl;
cout << "Words: " << m.size();
}
void clean_entry(const string&words, string&cleaned_words) {
int len = words.length();
int i = 0;
while (i < len && ispunct(words[i])) i++;//parse through initial punctuation (make sure that punctuation is deleted while leaving word intact if in front or back)
while (i < len && !ispunct(words[i])) { //while we come across any words with no punctuation, we add it to cleaned words
cleaned_words += words[i];
i++;
}
}
Screenshots:
Code output:
=========================
The issue was with the cleaned_words string that was passed as reference each time to clean_entry. Since it was passed by reference each time the same string, new words went on adding to it one after another.
So we need to ensure that it is empty before it is passed.
Line no. 22 does the same thing.
Also please note that, using map we can't ensure the output order to be same as input order. It will always be alphabetically arranged in sorted order.
If you still want the same order consider using another map, that stores the index of each string in the order they are entered.
============================
for any query comment.