Creating program to find repeated words in a sentence - c++

I'm having trouble with this project because when I put a sentence such as "cat is not a dog", it will not say "Didn't find repeated word" as intended. Instead, it will say "Found repeated word", as if I it was true. Also, each time it is run for the first time, the first letter is removed from the user input. Why?
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <time.h>
#include <stdio.h>
using namespace std;
int main()
{
int count = 0;
bool repeat = false;
char yn;
string input, newWord, firstword;
do
{
count = 0;
repeat = false;
cin.sync();
cout << "Please enter a sentence: ";
cin.ignore();
getline(cin, input);
while (input.at(count) != ' ')
count++;
firstword = input.substr(0, count);
input = input.substr(count++);
count = 0;
while(count < input.size() && repeat == false)
{
count++;
while (count < input.size() && input.at(count) != ' ')
count++;
newWord = input.substr(0, count);
if (firstword.compare(newWord) == 0)
input = input.substr(count++);
else
repeat = true;
}
if (repeat == true)
{
cout << "\nI found a repeated word!";
cout << "\nWould you like to try again? (y/n)";
cin >> yn;
}
else if(repeat == false)
{
cout << "\nI didn't find a repeated word.";
cout << "\nWould you like to try again? (y/n)";
cin >> yn;
}
} while (yn == 'y');
}

You program only checks if the first word is repeated annywhere else in the sentence...
Looking for a repeated word being: Each word must be checked against its immediate predecessor.
You're almost there. You forgot to reassign firstWord to newWord at te end of the parsing loop.
while(count < input.size() && repeat == false)
{
// ...
newWord = input.substr(0, count);
if (firstword.compare(newWord) == 0)
input = input.substr(count++);
else
repeat = true;
firstWord = newWord; // <-- Assign here.
}
Just an aside note, a trick of the trade, if you will.
if (repeat == true)
//...
else if(repeat == false) // <- Avoid doing that. Use plain else for booleans.
A bool can only have two values. And this kind of else if construct will bring unexpected surprises when plain ints are used for boolean equations. (if repeat was 3, which path does each cases of 0, 1, 3 follow?)
Have you tried removing the call to std::cin.sync() ?

Print your input after getline to be sure it's correctly saved. You probably don't need cin.ignore();. The first character is not saved.
An alternative sollution would be to use the following:
#include <iostream>
#include <string>
#include <fstream>
#include <map>
#include <sstream>
using namespace std;
int main()
{
int pos = 0;
string input;
cout << "Please enter a sentence: ";
getline(cin, input);
map<string, int> count_words;
stringstream ss(input);
string word;
while(getline(ss, word, ' '))
count_words[word]++;
map<string, int>::const_iterator it;
for(it = count_words.begin() ; it != count_words.end() ; ++it)
if( it->second == 2)
cout << "Found duplicate: " << it->first << endl;
return 0;
}
this answer(https://stackoverflow.com/a/236803/4388908) provides a good method to split your input.
The rest: Programming Pearls by Jon Bentley

Related

find a certain word in sentence in c++

I want to write a program that finds a word that the user entered I think my solution is right but when I Run it, the program shows nothing in the console
anybody can fix it?
int main()
{
char sen[200],del[200],maybedel[200];
cout<<"enter sentence :"<<endl;
cin.getline(sen,200);
cout<<"which word do you want to delete ?";
cin.getline(del,200);
int len = strlen(sen);
for(int i=0;i<=len;i++)
{
if(sen[i]==' ')
{
for(int j=i;j<=len;j++)
if(sen[j]==' ' || sen[j]=='\0')
for(int k=i+1,t=0;k<j;k++,t++)
maybedel[t]=sen[k];
if(maybedel==del)
cout<<maybedel;
}
}
return 0;
}
The line if(sen[i]==' '), line 12 of your code , prevents code from entering the block unless the sentence begins with (' ')!
I changed the code a bit and now it works fine.
char sen[200], del[200], maybedel[200];
cout << "enter sentence :" << endl;
cin.getline(sen, 200);
cout << "which word do you want to delete ?" << endl;
cin.getline(del, 200);
int len = strlen(sen);
int t = 0;
for(int i = 0; i <= len; i++) {
if(sen[i] == ' ' || sen[i] == '\0') {
maybedel[t] = '\0';
t = 0;
if(strcmp(del,maybedel)==0) {
cout << maybedel << endl;
}
}
else
{
maybedel[t] = sen[i];
t++;
}
}
The major reason for no output is
if (maybedel == del) // <<< this will *never* be true
cout << maybedel; // will never run
Since comparing "strings" in arrays needs help from std::strcmp(maybedel,del) == 0 would be better.
UPDATE:
Another attack method is to avoid raw loops and utilize the STL to your favor. Here's a more robust solution:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
using namespace std;
int main() {
cout << "enter sentence :\n";
string sen;
if (!getline(cin, sen)) throw std::runtime_error("Unable to read sentence");
cout << "which word do you want to delete ? ";
string del;
if (!(cin >> del)) throw std::runtime_error("Unable to read delete word");
istringstream stream_sen(sen);
vector<string> arrayofkeptwords;
remove_copy_if(istream_iterator<string>(stream_sen), istream_iterator<string>(),
back_inserter(arrayofkeptwords),
[&del](auto const &maybedel) { return maybedel == del; });
copy(begin(arrayofkeptwords), end(arrayofkeptwords),
ostream_iterator<string>(cout, " "));
cout << '\n';
}

C++ program need lines words and characters count

I have an assignment where i need to count lines, words and characters from a file. I'm having a problem counting the right amount of characters and words since if it gets doubled space it counts like a character and a word.
the output should be
Example
lines words characters filename
3 5 29 testfile
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <iomanip>
using namespace std;
int main(int argc, const char * argv[]) {
string lines, words, chars, file1, file2;
ifstream infile;
ofstream outfile;
char c;
int countLines = 0;
int countChars = 0;
int countWords = 0;
cout<< "Enter the file name" << endl;
cin >> file1;
infile.open(file1.c_str());
while(!infile.eof())
{
if(infile.peek() == 1)
break;
c = infile.get();
if(c != '\n')
countChars++;
else
countLines++;
if(c == ' '|| c =='\n')
countWords++;
}
// countChars = countChars - countWords;
cout << setw(12) << countLines << setw(12) << countWords << setw(12) << countChars << endl;
infile.close();
return 0;
}
Use getline for reading file line by line
while(getline(file,str))
{
countLines++;
countChars += str.length();
countWords += CountWords(str);
}
Which file is an iofstream object and str is a string. And for counting number of words(CountWords), you have several ways. One of them is:
#include <vector>
#include <string>
#include <boost/algorithm/string/split.hpp>
int countWords(std::string str) {
vector< std::string > result;
boost::algorithm::split_regex(result, str, regex( "\\s+" ));
return result.size();
}
I believe OP's purpose to ask this question is to find out why his/her code is not working, therefore I will answer in this perspective.
counting the right amount of words
C++ define EOF(end of file) as -1, so include a check for EOF too, or you will miss a word count.
if it gets doubled space it counts like a character and a word.
You can use a boolean test to solve this, if you encountered a space, turn on the boolean, and skip if next char is a space, too.
I suppose your character count doesn't count in punctuation? so check for c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'. If your assignment count punctuation as character count too, ignore this point.
Below is a correct version code that is modified based on your code.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <iomanip>
using namespace std;
int main(int argc, const char * argv[]) {
string lines, words, chars, file1, file2;
ifstream infile;
ofstream outfile;
char c;
bool findNextString = false;
int countLines = 0;
int countChars = 0;
int countWords = 0;
cout << "Enter the file name" << endl;
cin >> file1;
infile.open(file1.c_str());
while (!infile.eof())
{
if (infile.peek() == 1)
break;
c = infile.get();
// use the boolean to find next valid string
if (findNextString && c == ' ')
continue;
else
findNextString = false;
// there is a structure issue with your code.
// you should think of the priority of checking
// do not check by rejection, because you will count in punctuation too.
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
{
countChars++;
}
else if (c == '\n')
{
countLines++;
countWords++; // <- add word too
}
else if (c == ' ' || c == EOF)
{
countWords++;
findNextString = true;
}
}
cout << setw(12) << countLines << setw(12) << countWords << setw(12) << countChars << endl;
infile.close();
return 0;
}

Parsing out things surrounded by quotes in C++

I'm trying to make a parser that would only take text surrounded by quotes and place it in a new file I've already tried many times but can't figure it out it would have to take the original text out of a file by the way then place it in a new file I would like to do this in C++.
This is what I currently have:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char current_letter;
char quote_mark = '"';
int isquote = 0;
std::cin >> current_letter;
LOOP : do
{
if(current_letter == quote_mark) {++isquote;}
if(isquote == 1 && current_letter != quote_mark) {std::cout << current_letter;}
if(isquote == 1 && current_letter == quote_mark) {--isquote;}
if(isquote == 0) {goto LOOP;}
} while (cin >> current_letter);
if(cin != current_letter) {cout << "END" <<endl;}
return(0);
It doesn't print anything now but it used to print out random stuff or just quote marks.
You could just do something like this:
string str;
getline(cin, str);
string currStr = "";
for (int i = 0; i < str.length(); i++)
{
if (str[i] != '\"') currStr += str[i];
}
cout << currStr << "\n";
This won't work if there are double quotes within the text that you want to parse however.

Separate two inputs C++

I have made a quiz helper, but, as I want it for you to be able to input a new question without starting it, I made a do/while loop. The first run goes fine. When it asks you if you want to input another question, if you choose y, it runs the main program too at the same time, and the program registers y as a question. How do I separate this?Code:
#include <cctype>
#include <iostream>
#include <string>
#include "Quiz.h"
#include "Quiz2.h"
char choice;
int main()
{
do{
quiz();
std::cout << "Da li zelite da vam odgovorim na jos jedno pitanje?(y/n)" << std::endl;
std::cin >> choice;
} while(choice != 'n');
}
The first header file just includes the function to find words:
#ifndef QUIZ_H_INCLUDED
#define QUIZ_H_INCLUDED
bool contains_word(const std::string& sentence, const std::string& word)
{
size_t pos = 0;
while ((pos = sentence.substr(pos).find(word)) != std::string::npos) {
if (!(isalpha(sentence[pos - 1])) || !(isalpha(sentence[pos + word.size() + 1])))
return true;
}
return false;
}
#endif
And the other one contains the real code, it is partially in Serbian:
#ifndef QUIZ2_H_INCLUDED
#define QUIZ2_H_INCLUDED
int quiz()
{
std::string sentence;
std::cout << "Ukucajte pitanje ili kljucne reci: " << std::flush;
std::getline(std::cin, sentence);
std::string word ("Belgija");
std::string word2 ("regija");
std::string word3 ("Kanada");
std::string word4 ("teritorija");
std::string word5 ("Holandija");
std::string word6 ("delova");
if (contains_word(sentence, word) && contains_word(sentence, word2))
std::cout << "Odgovor je 3 regije." << std::endl;
else if (contains_word(sentence, word3) && contains_word(sentence, word4))
std::cout << "Odgovor je 3 teritorije." << std::endl;
else if (contains_word(sentence, word5) && contains_word(sentence, word6))
std::cout << "Odgovor je 3 dela." << std::endl;
else
std::cout << "Nisam mogao pronaci odgovor na to pitanje!" << std::endl;
return 0;
}
#endif
Any help is appreciated.
There is a newline character after a choice, so just add cin.ignore:
std::cin >> choice;
std::cin.ignore();
It ignores one character from input.
Alternative solution
Alternatively, you could discard all empty lines in quiz() function - substitute
std::getline(std::cin, sentence);
with
do {
std::getline(std::cin, sentence);
} while( sentence.empty() );
Other issue with the code
The contains_word function should be corrected. You shouldn't get value of sentence[pos + word.size() + 1] if it is possible for the word to be at the very end of sentence (subscript past the end of array).
Similar error in sentence[pos - 1] - what if pos is 0? You get some random stuff before the string.
You have to rework the condition also - certainly if( !(...) || !(...) ) is not what you wanted.
Should be something like this:
bool contains_word(const std::string& sentence, const std::string& word)
{
size_t pos = 0;
while ((pos = sentence.substr(pos).find(word)) != std::string::npos) {
if( (pos == 0 || isalpha(sentence[pos - 1])) &&
(pos + word.size() == sentence.size() || isalpha(sentence[pos + word.size()])) )
return true;
}
return false;
}
getline() and cin don't play well together. After a cin operation there is typically a newline left in the input stream that the getline reads and immediately concludes it is done. You can "solve" the problem by calling getline twice and ignoring the first result. However note that this only happens AFTER a call to cin, so the first time thru you should NOT use getline twice. This is why I say they "don't play well together".

Removing words between < and > signs in a string c++

I'm not sure where to go from here. I know something needs to go after ifstr.get(c). It copies the exact words that I have in my text file called project.txt but I just need to remove any words that have the chars < or >?
Any help would be great. Thanks:)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
string line;
char c;
ifstream ifstr("project.txt");
ofstream ofstr("past.txt");
if(ifstr.fail()){
cout<<"error!"<<endl;
} // if
ifstr.get(c);
while(!ifstr.eof()) {
cout<<c;
ifstr.get(c);
ofstr<<line<<endl;
} // while
cout<<endl<<"copy complete"<<endl;
ifstr.close();
ofstr.close();
system ("pause");
return 0;
} // main
Pseudo-code (iostream-esque conditions) for the question in title (also removes the angle brackets):
char c;
while (read_char_succeeded(&c))
if (c == '<')
while (read_char_succeeded(&c) && c != '>')
;
else
write_char(c);
Just another shot in the dark:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream ifstr("project.txt");
ofstream ofstr("past.txt");
if(ifstr.fail()){
cout << "error!" << endl;
} // if
bool skipOutput = false;
do
{
string word;
ifstr >> word;
if(!word.empty() && word[0] == '<')
{
skipOutput = true;
}
if(!skipOutput)
{
ofstr << word << " ";
// replicate the output to stdout
cout << word;
}
if(word[word.length()-1] != '>')
{
skipOutput = false;
}
} while(!ifstr.eof());
cout << endl << "copy complete" << endl;
ifstr.close();
ofstr.close();
//system ("pause"); Doesn't compile with my system
return 0;
} // main
If you're really just want to filter out words enclosed within '<' and '>' characters this should be sufficient. If you have more complex parsing rules for your <> tags you should elaborate your question.
I'm not sure, that this is what you wanted. Please take a look at the code!
//we create a boolean value, to know if we started skipping
bool skipStarted = false;
while(ifstr.get(c))
{
//if its a '<' and we havent started skipping jet,
//then we start skipping, and continue to the next char.
if(c=='<' && !skipStarted)
{
skipStarted = true;
continue;
}
//if its a '>' and we started skipping,
//then we finish skipping, and continue to the next char.
if(c=='>' && skipStarted)
{
skipStared = false;
ifstr.get(c);
if(c==' ')
continue;
}
//if we are skipping, then we go to the next char.
if(skipStarted)
continue;
//otherwise we simply output the character.
ofstr<<c;
}