Why is my program skipping over the indices of repeated words - c++

I am having problems with my program. Basically it finds the word count of a text file, the most and least repeated word, and have the user find a word. My problem is that when I find a words, it skips the indices of the repeated words. For example, if a text file has the words:
one two one one three five
and the user searches for "three", it will output that the index is 2. It skips over the repeated words. Why is that?
Here is my code:
int main() {
int counts[ARRAY_SIZE] = { 0 };
string words[ARRAY_SIZE];
ifstream inFile;
string filename, searchWord, lowerCase;
int wordCount = 0, totalWords = 0, index = 0;
int result, mostIndex, leastIndex;
cout << "Enter a text file: ";
cin >> filename;
inFile.open(filename);
while (!inFile.is_open()) {
if (filename == "q") {
inFile.close();
return 0;
}
else if (inFile.is_open()) {
cout << filename << " is open";
}
else {
cout << "Enter a valid file or type \"q\".";
}
cout << "The file you enetered is not valid, please enter a valid file or type \"q\" to quit.";
cin >> filename;
inFile.open(filename);
}
while (!inFile.eof()) {
while (inFile >> lowerCase) {
wordCount++;
lowerCase = convertCase(lowerCase);
result = search(words, lowerCase, totalWords);
if (result == NOT_FOUND) {
words[totalWords] = lowerCase; // lowerCase is a new word, so add it to the array,
counts[totalWords] = 1; // and set it's count to 1.
totalWords++;
}
else {
counts[result]++; // The word was found, so increment the times we've seen it.
}
}
cout << endl << "Total words: " << wordCount << endl;
cout << "Search a word: ";
cin >> searchWord;
index = search(words, searchWord, totalWords);
if (index == NOT_FOUND) {
cout << "\"" << searchWord << "\"" << " was not found." << endl;
}
else {
cout << endl << "the word " << "\"" << searchWord << "\"" << " is found on at index " << index << endl;
}
mostIndex = findIndexOfMost(counts, totalWords);
leastIndex = findIndexOfLeast(counts, totalWords);
cout << "The most repeated word is \"" << words[mostIndex] << "\" and was found " << counts[mostIndex] << " time(s)." << endl;
cout << "The least repeated word is \"" << words[leastIndex] << "\" and was found " << counts[leastIndex] << " time(s)." << endl;
}
system("pause");
return 0;
}
string convertCase(string word){
for (int i = 0; i < word.length(); i++) {
word[i] = tolower(word[i]);
}
return word;
}
int search(string words[], string searchWord, int totalWords){
int index = NOT_FOUND;
for (int i = 0; i < totalWords; i++){
if (words[i] == searchWord){
index = i;
break;
}
}
return index;
}
int findIndexOfMost(int counts[], int totalWords){
int most; // assume most is first count.
int index = 0, i;
most = counts[index];
for (i = 0; i < totalWords; i++)
{
if (counts[i] > most){
most = counts[i];
index = i;
}
}
return index;
}
int findIndexOfLeast(int counts[], int totalWords) {
int least, index = 0, i;
least = counts[index];
for (i = 0; i < totalWords; i++)
{
if (counts[i] < least) {
least = counts[i];
index = i;
}
}
return index;
}

I agree with the comments on your post, but I did find your error rather quickly. I highly suggest you try the debugger in the future to follow the variables you care about and see what is happening and how they are updating, when they're not updating as you think they would. Even simply printing your array words would show you the problem.
You're only adding words to the words array when they haven't been found yet, so when you search through words, you're searching through the unique words.
if (result == NOT_FOUND) {
words[totalWords] = lowerCase; // lowerCase is a new word, so add it to the array,
counts[totalWords] = 1; // and set it's count to 1.
totalWords++;
}
else {
counts[result]++; // The word was found, so increment the times we've seen it.
}
For the file
one two one one three five
your variable words would hold
one two three five
so if you searched for 'three' in words you would get the index 2, even though it's the fifth word in your file, so you want the index 4.

Related

I want this c++ program to find the the words starting with user entereed letter and print them using a new function

I want this c++ program to find the the words starting with user entereed letter and print them using a new function.but the thins is that it only finds 1st letter for the second time it runs ina loop and then , i dont know what happens ... I am a beginner please help me!
uncomment the line that are necessary
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
void getUserInput(string *filename, string *find)
{
cout << "file name : ";
cin >> *filename;
cout << "required character : ";
cin >> *find;
}
string* processFile(string fileName, string word, int *t, int *w, string found[])
{
fstream file;
int countIn = 0,
totaal = 0;
int *count = &countIn;
int *total = &totaal;
int i = 0;
string find; // the max length of the file should not exceed this value is if does please change it here.
file.open(fileName, ios::in);
if (file.is_open())
{
while (!file.eof())
{
file >> find;
totaal++;
if (word == find)
{
char a[100];
int s = find.size();
for (int j = 0; i < find.size(); j++)
{
string(1, find[i]);
}
found[i] = find;
i++;
countIn++;
}
}
}
else
cout << "!!!!invalid file name!!!!\n";
file.close();
//for (int i = 0, j = 0; i < totaal; i++)
//{
//
// cout << find[i] << '\t' << find[i][0] << endl;
//
// if (word == find[i][0])
// {
// cout << "i is " << i << endl;
// cout << "j is " << j << endl;
// cout << "Calculated i and j\n";
// found[j] = find[i];
// cout << "found[j] " << found[j] << "\nfind[i] " << find[i] << endl;
// j++;
// countIn++;
// cout << "Inside if\n";
// }
// cout << "outsidenside if\n";
//}
*t = *total;
*w = *count;
//cout << countIn << endl << totaal << endl;
//cout << *count << endl << *total<<endl;
return found;
}
void displayOutput(int total, int count, string wordlist[])
{
cout << "Total words in the file: " << total;
if (count != 0)
{
cout << "\nTotal " << count << " related words found in the file\n";
for (int i = 0; i < count; i++)
cout << i + 1 << "\t" << wordlist[i] << endl;
}
else
cout << "No matching case found\n";
}
int main()
{
string nameoffile;
string wordtofind;
string *ptr1 = &nameoffile;
string *ptr2 = &wordtofind;
string foundwords[] = { "" };
int occur = 0,
totalWords = 0;
int *occ = &occur;// occurence of the certain word
int *tot = &totalWords;// total wods in the file
getUserInput(ptr1, ptr2);
processFile(nameoffile, wordtofind, occ, tot, foundwords); //calling the processing function
displayOutput(occur, totalWords, foundwords);
return 0;
}

Finding an instance of a word or phrase in a string

I'm writing a program where the user inputs a string and the user can then select from a menu to do things such as display the number of words in the string or number of spaces in the string. I have all functions working except for the one where I need to be able to find the number of instances of a specific word or phrase. Whenever I enter a word or phrase it says there are 0 occurrences. This is my entire code but again I just need help with my FindText function. Bare in mind I'm a beginner programmer.
#include <iostream>
#include <string>
using namespace std;
string user_text = " ";
string find_text = " ";
string replaced = " ";
char print_menu(char);
int GetNumOfNonWSCharacters(string);
int GetNumOfWords(string);
int FindText(string, string);
string ReplaceExclamation(string);
string ShortenSpace(string);
int main()
{
char choice = ' ';
cout << "Enter a sample text: ";
getline(cin, user_text);
choice = print_menu(choice);
while (!(choice == 'q'))
{
switch (choice)
{
case 'c': //number of non-whitespace characters
int not_space;
not_space = GetNumOfNonWSCharacters(user_text);
cout << "Number of non white space charactesr: " << not_space << endl;
choice = print_menu(choice);
break;
case 'w': //number of words
int words;
words = GetNumOfWords(user_text);
cout << "Number of words: " << words << endl;
choice = print_menu(choice);
break;
case 'f': //find text
int occurences;
cout << "Enter a word or phrase to be found: ";
cin.ignore();
getline(cin, find_text);
occurences = FindText(find_text, user_text);
cout << find_text << " instances: " << occurences << endl;
choice = print_menu(choice);
break;
case 'r': //replace all !'s
replaced = ReplaceExclamation(user_text);
cout << replaced << endl;
choice = print_menu(choice);
break;
case 's': //shorten spaces
replaced = ShortenSpace(user_text);
cout << replaced << endl;
choice == print_menu(choice);
break;
case 'q': //quit
exit(0);
break;
default:
cout << "Invalid choice please try again";
choice = print_menu(choice);
}
}
system("pause");
return 0;
}
char print_menu(char choice)
{
cout << "MENU" << endl;
cout << " c - Number of non - whitespace characters" << endl;
cout << " w - Number of words" << endl;
cout << " f - Find text" << endl;
cout << " r - Replace all !'s" << endl;
cout << " s - Shorten spaces" << endl;
cout << " q - Quit" << endl;
cout << " Choose an option ";
cin >> choice;
return choice;
}
int GetNumOfNonWSCharacters(string text)
{
int spaces = 0;
int not_spaces = text.length();
for (int i = 0; i < text.length(); i++)
{
if (isspace(text.at(i)) != false)
{
spaces += 1;
}
}
not_spaces = not_spaces - spaces;
return not_spaces;
}
int GetNumOfWords(string text)
{
int words = 0;
for (int i = 0; i < text.length(); i++)
{
if (text.at(i) == ' ')
{
words++;
}
}
return words + 1;
}
int FindText(string find, string text)
{
int count = 0;
for (int i = 0; i < text.length(); i++)
{
if (text.find(find) == true)
{
count++;
}
}
return count;
}
string ReplaceExclamation(string text)
{
for (int i = 0; i < text.length(); i++)
{
if (text.at(i) == '!')
{
text.at(i) = '.';
}
}
return text;
}
string ShortenSpace(string text)
{
for (int i = 0; i < text.length(); i++)
{
if (text.at(i) == ' ' && text.at(i + 1) == ' ')
{
text.erase(text.begin() + i);
}
}
return text;
}
string::find() returns size_type and not bool
Use an overload of find() that allows you to specify the starting position.
size_type find( const basic_string& str, size_type pos = 0 )
Once the string is found, add its length to the starting position and use find again to find the next occurrence.
You can modify your function thus:
int FindText(string find, string text)
{
int count = 0;
string::size_type start = 0;
while ((start = text.find(find, start)) != string::npos) {
++count;
start += find.length();
}
return count;
}

C++ adding extra, unwanted characters to a string

I am having a bug that I cannot find a fix for through google searching. I am attempting to make a text based version of the game Mastermind. I am using a string the is set from an array of chars as the criteria for a while loop. When the string is equal to "****" the game is supposed to tell the player that they won and exit, but for some reason a ^A is being added on to the end of the string that is being checked, even though it is not in the char array.
Here is the function that sets the char array and returns a string from that array:
string check(int guess[4], int num[4]) {
char hints[4];
cout << " ";
for (int i = 0; i < 4; i++) {
if (guess[i] == num[i]) {
hints[i] = '*';
cout << "*";
}
else {
for (int x = 0; x < 4; x++) {
if (guess[i] == num[x]) {
cout << "+";
}
}
}
if (guess[i] != num[i]) {
hints[i] = ' ';
}
}
string hint(hints);
cout << endl;
cout << hint << endl;
return hint;
}
And here is the function checking the value of the string:
while (hints.compare("****") != 0) {
if (guessCount == 5) {
break;
}
cout << "Guess?: ";
cin >> guess;
intToArray(guess, guessArr);
hints = check(guessArr, nums);
cout << hints << endl;
guessCount++;
}
if (hints.compare("****") == 0) {
cout << "You win! The number was: ";
for (int i = 0; i < 4; i++) {
cout << nums[i];
}
}
You haven't null-terminated the hints array, so you are getting extra garbage that is lying around on the stack in your string.
You could let the hint string know how long it is when you are constructing it.
string hint(hints, 4);
cout << endl;
cout << hint << endl;

I keep getting subscript out of range don't know how to fix it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
const int MAX_NUMS = 200; // Constant for the maximum number of words.
const int MAX_GUESSES = 8;
const string LETTERS = "abcdefghijklmnopqrstuvwxyz";
char inputLetter();
int findChar(char letter, string&word);
string getGuessedWord(string&secretWord, string&lettersGuessed);
string getLettersGuessed(char letter, string&lettersGuessed, int n);
void display(string&lettersGuessed, string&wordGuessed, int num, int pos);
bool isDone(string wordGuessed);
int main()
{
string oneWord; // holds one word from input file
string secretWord; // holds secret word to be guessed
string words[MAX_NUMS]; // holds list of words from input file
int randomValue; // holds index of secret word
int count = 0; // holds number of words in the file
// Declare an ifstream object named myFile and open an input file
ifstream myFile;
myFile.open("P4Words.txt");
// Exit program if cannot open file for input
if (!myFile)
{
cout << "Error: Unable to open file for input" << endl;
return 0;
}
// Input words from a file into words array
// Add your code here ...
myFile >> oneWord;
while (!myFile.eof())
{
words[count] = oneWord;
count++;
myFile >> oneWord;
}
myFile.close();
cout << count << " words loaded." << endl;
srand(static_cast<unsigned int>(time(0)));
// Select a secret word
// Add your code here ...
secretWord = words[rand() % (count + 1) ];
// Possible useful variables the loop
string lettersGuessed = ""; // holds letters guessed so far
string wordGuessed; // holds current word guessed like �_ pp_ e�
int incorrectGuesses = 0; // holds number of incorrect guesses so far
char letter; // holds a guessed letter
bool done = false; // have not guessed the word yet
int num = 8; int pos;
cout << "Welcome to the game, Hangman V1 by Your Name!" << endl;
cout << "I am thinking of a word that is " << secretWord.length()
<< " letters long." << endl;
// Set up a loop to input guesses and process
// Add your code here ...
do
{
letter = inputLetter();
pos = findChar(letter, secretWord);
wordGuessed = letter;
lettersGuessed = getLettersGuessed(letter, lettersGuessed, 8 - num);
wordGuessed = getGuessedWord(secretWord, lettersGuessed);
display(lettersGuessed, wordGuessed, num, pos);
done = isDone(wordGuessed);
num--;
} while ((num > 1) && (done == false));
// Check for won or lost
// Add your code here ...
if (done == false)
{
cout << "sorry you lose..." << endl;
}
if (done == true)
{
cout << "congratulations! " << endl;
}
system("pause"); // stop program from closing, Windows OS only
return 0;
}
// Add function definitions here ...
char inputLetter()
{
int i;
char letter;
do
{
cout << "please guess a letter: " << endl;
cin >> letter;
for (i = 0; i < 25; i++)
{
if (letter == LETTERS[i])
{
return letter;
}
}
if (letter != LETTERS[i])
{
cout << "Oops! That is an invalid character." << endl;
}
} while (letter != LETTERS[i]);
}
int findChar(char letter, string &word)
{
int i = 0; int pos = 0; bool found = false;
do
{
if (word[pos] == letter)
{
return pos;
found = true;
}
pos++;
} while (pos<word.length() - 1);
if (found == false)
{
return -1;
}
}
string getGuessedWord(string&secretWord, string&letterGuessed)
{
string temp;
temp = secretWord;
for (size_t k = 0; k <= temp.length() - 1; k++)
{
temp[k] = '_';
}
for (size_t i = 0; i <= temp.length() - 1; i++)
{
for (size_t j = 0; j <= temp.length() - 1; j++)
{
if (letterGuessed[i] == secretWord[j])
{
temp[j] = letterGuessed[i];
}
}
}
return temp;
}
string getLettersGuessed(char letter, string&lettersGuessed, int n)
{
string temp;
temp = letter;
lettersGuessed.insert(n, temp);
return lettersGuessed;
}
void display(string&lettersGuessed, string&wordGuessed, int num, int pos)
{
if (pos != -1)
{
cout << "You have " << num << " guesses left." << endl;
cout << "Letters guessed so far: " << lettersGuessed << endl;
cout << "Good guess!: " << wordGuessed << endl;
cout << "-----------------------------------------------------" << endl;
}
if (pos == -1)
{
cout << "You have " << num << " guesses left." << endl;
cout << "Letters guessed so far: " << lettersGuessed << endl;
cout << "Oops! that letter is not my word: " << wordGuessed << endl;
cout << "-----------------------------------------------------" << endl;
}
}
bool isDone(string wordGuessed)
{
bool done = false; int k = 0;
for (size_t i = 0; i <= wordGuessed.length() - 1; i++)
{
if (wordGuessed[i] == '_')
{
k++;
}
}
if (k == 0)
{
done = true;
}
return done;
}
it says subscript is out of range I need help to fix it
let me know how to fix it please its a project that is due very soon
that's all I got so far
Change:
for (size_t i = 0; i <= temp.length() - 1; i++)
to:
for (size_t i = 0; i <= letterGuessed.length() - 1; i++)

Create a histogram of the top 10 words that appear in a text file

I am trying to create a histogram of the frequency (in percentages) that the top ten words in a text appear.
It needs to be in similar format to this this:
for: --------------------20(percent and 20 dashes)
is: ---------------15
him: ----------10
war: -----5
have: -----5
hero: -----5
have: ----4
girl: -----5
angry: ----4
others: --------------------------------32
I know I need a for loop of 10, and inside it another loop with dashes going to the percent
int main()
{
string file_name;
cout << "Enter the file name, the odyssey or pride and prejudice, that you would like to analyze: ";
getline(cin,file_name);
vector<string> words; //loading words into vector called words
if(file_name == "test")
{
words = words_to_vector("test.txt"); //used a test files so it would take less time
}
else if(file_name == "pride and prejudice")
{
words = words_to_vector("pride-prejudice.txt");
}
else if (file_name == "the odyssey")
{
words = words_to_vector("the-odyssey.txt");
}
else
{
cout << "Sorry, the file name you entered is invalid.";
}
vector<word_stats> stats = get_word_stats(words); // calculating the number of words, and how many of those words are unique
cout << endl << endl << "Total words: " << words.size() << ", " << stats.size() << " unique" << endl;
sort(stats.begin(), stats.end(), compare_stats);
cout << "Most common word is '" << stats[0].word << "' occuring " << stats[0].count << " times." << endl;
int topMostCount = 10; //where I need help putting this into a histogram
//int totalWords = words.size();
int totalUniqueWords = stats.size();
//most common
for (int i=0; i<stats.size() && i<topMostCount; i++) {
cout << stats[i].word << ": " << stats[i].count << endl;
}
How about you create a method to generate dashes and output it as a const char *?
for(int i = 0; i < stats.size() && i < topMostCount; i++){
int percent = (double)stats[i].count / words.size * 100.00;
const char * dashes = genDashes(percent);
cout << stats[i].word << ": " << dashes << percent << "%";
}
And the genDashes function would be something as follow:
const char * genDashes(int n)
{
std::stringstream ss_dashes;
for(int i = 0; i < n; i++){
ss_dashes << "-";
}
std::string s_dashes = ss_dashes.str();
return s_dashes.c_str();
}