C++ Find word in sentence - c++

I've got a task to find the word "EYE" in a sentence (more like just line of chars) such as: EYEYECARASDFG. As you can see, the word "EYE" is there twice, overlapping each other. I am suppose to cout how many times the word "EYE" occurs in the sentence. I wrote some code that looks like this:
#include <iostream>
#include <string>
using namespace std;
string sentence;
int main()
{
int i = 0;
cin >> sentence;
while()
{
if (std::string::npos != sentence.find("EYE"))
{
i++;
}
}
cout << i;
}
Now without the while loop, it finds the EYE in the sentence and it kinda works. So I though, to count with the overlapping and make the code running until it hits the end, I need to loop it. So I though the while loop would be the best, but I don't know how to loop it, what to put into the brackets for while loop

First of all condition in while is required. If you want infinite loop use true as your statement. As a first draft, try to make it with "brute force". Just check every 3 letters substring of your sentence if equals "EYE". It will be one loop and 3 conditions or 2 loops and 1 condition. Then read about some text search algorithm e.g KMP.
If you just want to make this code run use following coed:
int pos = 0;
while(true) {
pos = sentence.find("EYE", ++pos);
if (pos != std::string::npos) {
i++;
} else break;
}

You can do this using a finite-state machine. (Google it.) That is efficient and easy to understand. As you read the characters, there are three states to distinguish, i.e., 1) when the most recent letter seen was an "E", 2) when the last two seen were "EY" in that order, and 3) everything else. As you go through a character at at time, increase the "found"-count by one whenever you are in state 2 and find another "E".
See if you can take it from there with no more hints.
The idea can be extended to arbitrary strings besides "EYE", and you can write a compiler of sorts to generate the finite-state machines for those strings. But that is a more advanced assignment.

#include<iostream>
#include<string>
using namespace std;
main()
{
string sen, sub;
int pos;
cout<<"Enter the Sentence"<<endl;
getline(cin,sen);
cout<<"Enter string to find"<<e`ndl;
cin>>sub;
for (int i=1;(pos=sen.find(sub)) != -1 ;i++)
{
sen=sen.substr(++pos);
cout<<"Found = "<<sub<<" "<<i<<" Times"<<endl;
}``
}

Code Snippet :
#include <bits/stdc++.h>
using namespace std;
int main()
{
string input, word;
getline(cin, input);
cin>>word;
int cnt=0;
size_t pos = input.find(word, 0);
while(pos != string::npos)
{
cnt++;
pos = input.find(word, pos+1);
}
cout<<cnt<<endl;
return 0;
}
Input :
Python Programming Python
Python
Output : 2

Related

What is the reason behind the debugging getting stopped abruptly in the following code?

Here is the code to find the number of matches of a string, which is input from the user, can be found in the file temp.txt. If, for example, we want love to be counted, then matches like love, lovely, beloved should be considered. We also want to count the total number of words in temp.txt file.
I am doing a line by line reading here, not word by word.
Why does the debugging stop at totalwords += counting(line)?
/*this code is not working to count the words*/
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int totalwords{0};
int counting(string line){
int wordcount{0};
if(line.empty()){
return 1;
}
if(line.find(" ")==string::npos){wordcount++;}
else{
while(line.find(" ")!=string::npos){
int index=0;
index = line.find(" ");
line.erase(0,index);
wordcount++;
}
}
return wordcount;
}
int main() {
ifstream in_file;
in_file.open("temp.txt");
if(!in_file){
cerr<<"PROBLEM OPENING THE FILE"<<endl;
}
string line{};
int counter{0};
string word {};
cout<<"ENTER THE WORD YOU WANT TO COUNT IN THE FILE: ";
cin>>word;
int n {0};
n = ( word.length() - 1 );
while(getline(in_file>>ws,line)){
totalwords += counting(line);
while(line.find(word)!=string::npos){
counter++;
int index{0};
index = line.find(word);
line.erase(0,(index+n));
}
}
cout<<endl;
cout<<counter<<endl;
cout<<totalwords;
return 0;
}
line.erase(0, index); doesn't erase the space, you need
line.erase(0, index + 1);
Your code reveals a few problems...
At very first, counting a single word for an empty line doesn't appear correct to me. Second, erasing again and again from the string is pretty inefficient, with every such operation all of the subsequent characters are copied towards the front. If you indeed wanted to do so you might rather want to search from the end of the string, avoiding that. But you can actually do so without ever modifying the string if you use the second parameter of std::string::find (which defaults to 0, so has been transparent to you...):
int index = line.find(' ' /*, 0*); // first call; 0 is default, thus implicit
index = line.find(' ', index + 1); // subsequent call
Note that using the character overload is more efficient if you search for a single character anyway. However, this variant doesn't consider other whitespace like e. g. tabulators.
Additionally, the variant as posted in the question doesn't consider more than one subsequent whitespace! In your erasing variant – which erases one character too few, by the way – you would need to skip incrementing the word count if you find the space character at index 0.
However I'd go with a totally new approach, looking at each character separately; you need a stateful loop for in that case, though, i.e. you need to remember if you already are within a word or not. It might look e. g. like this:
size_t wordCount = 0; // note: prefer an unsigned type, negative values
// are meaningless anyway
// size_t is especially fine as it is guaranteed to be
// large enough to hold any count the string might ever
// contain characters
bool inWord = false;
for(char c : line)
{
if(isspace(static_cast<unsigned char>(c)))
// you can check for *any* white space that way...
// note the cast to unsigned, which is necessary as isspace accepts
// an int and a bare char *might* be signed, thus result in negative
// values
{
// no word any more...
inWord = false;
}
else if(inWord)
{
// well, nothing to do, we already discovered a word earlier!
//
// as we actually don't do anything here you might just skip
// this block and check for the opposite: if(!inWord)
}
else
{
// OK, this is the start of a word!
// so now we need to count a new one!
++wordCount;
inWord = true;
}
}
Now you might want to break words at punctuation characters as well, so you might actually want to check for:
if(isspace(static_cast<unsigned char>(c)) || ispunct(static_cast<unsigned char>(c))
A bit shorter is the following variant:
if(/* space or punctuation */)
{
inWord = false;
}
else
{
wordCount += inWord; // adds 0 or 1 depending on the value
inWord = false;
}
Finally: All code is written freely, thus unchecked – if you find a bug, please fix yourself...
debugging getting stopped abruptly
Does debugging indeed stop at the indicated line? I observed instead that the program hangs within the while loop in counting. You may make this visible by inserting an indicator output (marked by HERE in following code):
int counting(string line){
int wordcount{0};
if(line.empty()){
return 1;
}
if(line.find(" ")==string::npos){wordcount++;}
else{
while(line.find(" ")!=string::npos){
int index=0;
index = line.find(" ");
line.erase(0,index);
cout << '.'; // <--- HERE: indicator output
wordcount++;
}
}
return wordcount;
}
As Jarod42 pointed out, the erase call you are using misses the space itself. That's why you are finding spaces and “counting words” forever.
There is also an obvious misconception about words and separators of words visible in your code:
empty lines don't contain words
consecutive spaces don't indicate words
words may be separated by non-spaces (parentheses for example)
Finally, as already mentioned: if the problem is about counting total words, it's not necessary to discuss the other parts. And after the test (see HERE) above, it also appears to be independent on file input. So your code could be reduced to something like this:
#include <iostream>
#include <string>
int counting(std::string line) {
int wordcount = 0;
if (line.empty()) {
return 1;
}
if (line.find(" ") == std::string::npos) {
wordcount++;
} else {
while (line.find(" ") != std::string::npos) {
int index = 0;
index = line.find(" ");
line.erase(0, index);
wordcount++;
}
}
return wordcount;
}
int main() {
int totalwords = counting("bla bla");
std::cout << totalwords;
return 0;
}
And in this form, it's much easier to see if it works. We expect to see a 2 as output. To get there, it's possible to try correcting your erase call, but the result would then still be wrong (1) since you are actually counting spaces. So it's better to take the time and carefully read Aconcagua's insightful answer.

Logical Issue or Syntax issue with sorting String function

I'm new to C++ and coding in general. I'm attempting to make a simple program that essentially takes in two words and will tell you if these two words are anagrams or not.I also understand that there is likely a pre-made function to sort a string, like an array however I am trying to grasp the concept itself and hence why I'm attempting to make the function.
Here is a quick snippet of the code I've written so far.
Snippet of code
The issue that I'm currently having is that when I call the function to sort the string, the string isn't sorted! Sorry if there is a simple solution to this, I'm fairly new. Is this a logical issue or syntax based? Thank you so much!
#include <iostream>
#include <string>
using namespace std;
//Function Declarations
string sortString(string user_input);
//Program Body
int main()
{
string user_input_one, user_input_two;
cout << "Welcome to Sandip's Anagram Checker! \nPlease Input two words that you'd like the check!";
sortString(user_input_one);
sortString(user_input_two);
if (user_input_one == user_input_two)
cout << "These two words are Anagrams of each other!";
else
cout << "These are not Anagrams!";
return 0;
}
//Function Definations
string sortString(string user_input)
{
string temp_string = user_input;
int i,j;
for (i = 0; i<user_input.length();i++)
{
for (j=0; j<user_input.length();j++)
{
if (user_input[i] == user_input[j])
{
temp_string[i] = user_input[j];
}
else if (user_input[i] > user_input[j])
{
temp_string[i] = user_input[j];
}
else if (user_input[i] < user_input[j])
{
temp_string[i] = user_input[i];
}
}
}
return temp_string;
}
Adding to Daniel's answer, you don't need a temporary string in the sorting function, just process the passed string and return it. Also consider supporting letter cases as well, you can use std::transform from the STL algorithm library.
#include <algorithm>
Add this before looping in your sorting function or after taking inputs in main.
transform(user_input.begin(), user_input.end(), user_input.begin(), ::tolower);
There are a couple issues. You're not actually reading any user input. You can fix this by adding cin >> user_input_one >> user_input_two;.
Your sorting also doesn't work quite right. It looks similar to selection sort, so I tweaked it to be a variation of that. For each character in the string, it goes through the rest of the string and swaps letters if the later one should be first.
string temp_string = user_input;
int i, j;
for (i = 0; i < user_input.length(); i++)
{
for (j = i + 1; j < user_input.length(); j++)
{
if (temp_string[j] < temp_string[i]) {
swap(temp_string[i], temp_string[j]);
}
}
}
return temp_string;
Lastly, as #cigien commented, you aren't using the sorted result. You can change this by replacing your lines calling sortstring() with this:
user_input_one = sortString(user_input_one);
user_input_two = sortString(user_input_two);

Keep output and input from alternating?

I am very new to coding, and have been practicing with some easy problems at codeforces.com. I was working on this problem, but it seemed to be asking for the input (all at once) yielding the output (all at once). I can only figure out how to get one output at a time.
Here are the basic instructions for the problem:
Input
The first line contains an integer n (1 ≤ n ≤ 100). Each of the following n lines contains one word. All the words consist of lowercase Latin letters and possess the lengths of from 1 to 100 characters.
Output
Print n lines. The i-th line should contain the result of replacing of the i-th word from the input data.
Examples
input
4
word
localization
internationalization
pneumonoultramicroscopicsilicovolcanoconiosis
output
word
l10n
i18n
p43s
Here is my code:
#include <iostream>
#include <string>
using namespace std;
void wordToNumbers(string word){
int midLetters = word.length();
char firstLetter = word.front();
char lastLetter = word.back();
cout <<firstLetter <<(midLetters-2) <<lastLetter <<endl;
}
int main(){
string wordInput;
string firstNum;
getline(cin,firstNum);
int i = stoi(firstNum);
for(i>=1; i--;){
getline(cin,wordInput);
if (wordInput.length() > 10){
wordToNumbers(wordInput);
} else {
cout <<wordInput <<endl;
}
}
return 0;
}
it's perfectly fine to read and print output for the lines one by one.
Exactly your solution accepted: http://codeforces.com/contest/71/submission/16659519
I'm also a beginner in c++. My idea would be to save every line first in a buffer and then write everything to std::cout.
I use a std::vector as the buffer, cause IMO it is simple to understand and very useful in many cases. Basically it is a better array. You can read more about std::vector here.
#include <iostream>
#include <string>
//for use of std::vector container
#include <vector>
using namespace std;
void wordToNumbers(string word){
int midLetters = word.length();
char firstLetter = word.front();
char lastLetter = word.back();
cout <<firstLetter <<(midLetters-2) <<lastLetter <<endl;
}
int main(){
string wordInput;
string firstNum;
//container for buffering all our strings
vector<string> bufferStrings;
getline(cin,firstNum);
int i = stoi(firstNum);
//read line by line and save every line in our buffer-container
for(i>=1; i--;){
getline(cin,wordInput);
//append the new string to our buffer
bufferStrings.push_back(wordInput);
}
//now iterate through the buffer and write everything to cout
for(int index = 0; index < bufferStrings.size(); ++index) {
if (bufferStrings[index].length() > 10){
wordToNumbers(bufferStrings[index]);
} else {
cout <<bufferStrings[index] <<endl;
}
}
return 0;
}
Probably this is not the best or most beautiful solution, but it should be easy to understand :)

How do I use the .find() in a while or for loop and have not give the same found value each time

I'm trying to build a function that goes through a while or for-loop and finds where the space is, outputs everything before the space, and then erases everything before the space including the space, and then repeats this again.
Any help is much appreciated.
int sentence()
{
string enteredSentence="";
getline(cin,enteredSentence);
string sentenceString(enteredSentence);
int sentenceLength=enteredSentence.size();
cout<<"size of sentence"<<sentenceLength<<endl;
int stringSize=sentenceString.size();
while(stringSize>0)
{
int spaceLoc = enteredSentence.find(" ");
cout<<spaceLoc;
cout<<sentenceString.substr(0,spaceLoc)<<endl;
sentenceString.substr(0,spaceLoc);
cout<<"string before string eraced"<<sentenceString<<endl;
sentenceString.erase (0,spaceLoc);
cout<<"string after string eraced"<<sentenceString<<endl;
stringSize=sentenceString.size();
cout<<"string size is"<<stringSize<<endl;
}
This is how I fixed your code:
#include <iostream>
using namespace std;
int main()
{
string enteredSentence="";
getline(cin,enteredSentence);
string sentenceString(enteredSentence);
int sentenceLength = enteredSentence.size();
cout<<"size of sentence:"<<sentenceLength<<endl;
string::size_type stringSize = sentenceString.size();
while(stringSize > 0)
{
int spaceLoc = sentenceString.find(" "); //there was incorrect var
cout<<spaceLoc<<endl;
if(spaceLoc == string::npos){
cout<<"last part:"<<sentenceString<<endl;
break;
}//check if there are no spaces left
cout<<sentenceString.substr(0,spaceLoc)<<endl;
//the substr line here was redundant
cout<<"string before string erased:"<<sentenceString<<endl;
sentenceString.erase(0, spaceLoc + 1);//also delete the space
cout<<"string after string erased:"<<sentenceString<<endl;
stringSize=sentenceString.size();
cout<<"string size:"<<stringSize<<endl<<endl;
}
return 0;
}
You could use a stringstream.
#include <sstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
string enteredSentence; // It's initialized to "" by default, by the way
getline(cin,enteredSentence);
cout<<"size of sentence: "<<enteredSentence.length()<<endl;
istringstream str_in(enteredSentence);
string word;
while(str_in >> word) {
// Do stuff with word
// I believe str_in.str() will also give you the portion that hasn't yet been processed.
}
return 0;
}
I'm not 100% sure that I understand what you want to achieve. But I can help you with find:
It has a second parameter that specifies from where on in the string the search will start:
size_t pos = 0;
while ((pos = str.find(' ', pos)) != std::string::npos) {
std::cout << "Found a space at " << pos << std::endl;
++pos;
}
Reference
With more information on what you actually want your code to do (show example input plus wanted output) I can help you clear the rest of your code.
Currently your description suggests that you want to output the entire string, but in pieces (separated by spaces).
Your code makes a (needless?) copy of your input, generates substrings only to throw them away and doesn't return an int as said in the function declaration.
If you want to tokenize your input then this question has some answers for you.

continuous input characters like strings using loop multiple times

In the following code, is it possible that I take multiple input, do some calculation (like the last character) and print at the end .. and then again take input till 5 times?
#include <iostream>
using namespace std;
int main ()
{
char name;
int i=0;
while(i != 5){
while(!(name != '<' || name != '>')){
cin>>name;
//do some calculation with the inputs
//cout<<name;
}
i++;
cout<<name;
//print the result of calculation this loop
}
}
For some reason, I am not allowed to use string, or array, or break, and no library other than iostream. Is it possible using loops? What are alternatives?
EDIT:: In above code, I want to determine what was last input. If I enter asdf> then i get >>>>>. I want it to print > and go back in the loop and ask me for another shot.
After the inner while terminates name holds either < or > and is not reset prior to the next encounter of the inner while, which terminates immediately as name is still either < or >. Just reset name prior to the inner while or slight restructure:
while (cin >> name && !(name != '<' || name != '>'))
{
}
The solution is to reset the name variable right before this line:
while (!(name != '<' || name != '>')) {
What you need to do would be this:
name = 0;
Also, I'd recommend initializing the variable before entering the first while loop.
Edit:
Alternatively, you can use '\0' instead of 0. It makes no difference internally though. The code would only make more sense to most inexperienced users.
Looks like you want to make a pointer to a character. This will behave just like an array without actually being an array, and requires nothing but #include <iostream> for the input and output.
char* name;
You could also try using a vector of characters, but this is the long way around and would break the "nothing but <iostream> rule:
#include <vector>
#include <iostream>
using namespace std;
vector<char> CharVec;
vector<char>::iterator it;
int main ()
{
char input;
int i=0;
while(i != 5){
if(input != '<'){ //this should be if, not while
CharVec.push_back(input);
}
i++;
}
//move print to outside the character entering loop
it = CharVec.begin();
while(it != CharVec.end())
{
cout << *it;
it++;
}
}