How to loop through a string using find() C++ - c++

The loop in the program seems to execute at least once, even if there are no occurences of the substring. Why is this?
#include <iostream>
#include <string>
using namespace std;
int countSubstrings(const string& original_string, const string& substr) {
int number_of_ocurrences = 0;
int i = 0;
for (i = original_string.find(original_string, 0); i != string::npos;
i = original_string.find(substr, i)) {
number_of_ocurrences++;
i++;
}
return number_of_ocurrences;
}
int main() {
string input;
while (1) {
cout << "Enter a a line of text: ";
getline(cin, input, '\n');
cout << '\n';
cout << "Number of ocurrences of the word needle: ";
cout << countSubstrings(input, "needle") << '\n';
}
}

Initially when you set i in your for loop you have
original_string.find(original_string, 0)
So you are searching the string for itself which it will find. I believe you meant to have
original_string.find(substr, 0)

Related

Find a word in a sentence c++

This code should say if a word is present in a sentence or not. When I insert the sentence and the word where I declare the strings(for exemple: string s = "the cat is on the table" string p = "table" the program says that the word is in the sentence) the code works but, with the getline, the for cycle never begin and it always says that the word isn't in the sentence.
Please help I dont know what to do
#include <iostream>
#include <string>
using namespace std;
int main () {
string s;
string p;
string word;
bool found = false;
int sl = s.length();
int beg = 0;
int pl = p.length();
cout << "sentence: ";
getline(cin, s);
cout << "word: ";
getline(cin, p);
for(int a = 0; a<sl; a++)
{
if(s[a]== ' ')
{
word = s.substr(beg, a-beg);
if (word== p)
{
found = true;
break;
}
beg = a+1;
}
}
if (found== true)
{
cout <<"word " << p << " is in a sentence " << s;
}
else
{
word = s.substr(beg);
if (word== p)
{
found = true;
}
if(found == true)
{
cout <<"the word " << p << " is in the sentence " << s;
}
else
{
cout <<"the word " << p << " isn't in the sentence " << s;
}
}
}
after taking the input strings then use length() to find the length, otherwise you are not taking the actual size of the strings.
getline(cin, s);
getline(cin, p);
int sl = s.length();
int pl = p.length();
For splitting the words after taking the input string by getline() you can use stringstream which is a builtin c++ function, like :
#include <sstream>
#include <iostream>
using namespace std;
int main(){
string arr;
getline(cin, arr);
stringstream ss(arr);
string word;
while(ss >> word){
// your desired strings are in `word` one by one
cout << word << "\n";
}
}
Another thing is that you can declare the strings like string s, p, word;

c++ problem with reverse and count string

I'm just learning c++. I have a problem with my program. I have to write a program which reverse string and count amount word in the string. My program doesn't return amount words and reverse only last word in string. I totally don't know how to correct it. :D
#include <iostream>
using namespace std;
void reverseString(string str)
{
for (int i=str.length()-1; i>=0; i--)
{
cout << str[i];
}
}
void countString(string strg)
{
int word = 1;
for(int j = 0; strg[j] != '\0'; j++)
{
if (strg[j] == ' ')
{
word++;
}
}
}
int main(void)
{
string inputString;
cout << "Give a string: ";
cin >> inputString;
cout << "Reverse string: ";
reverseString(inputString);
cout << "\nCounts words in a string: ";
countString(inputString);
return 0;
}
If you want to read multiple words then you must use getline as >> reads only a single word.
string inputString;
cout << "Give a string: ";
getline(cin, inputString);
To return something from a function you must 1) specify the return type and 2) use a return statement to return a value and 3) do something with that return value in the calling function
Step 1
int countString(string strg) // here we say countString returns an integer
{
...
}
Step 2
int countString(string strg)
{
...
return words; // here we say the value we want to return
}
Step 3
// here we output the value returned from the function
cout << "\nCounts words in a string: " << countString(inputString) << "\n";
Knowing how to write functions that return values is absolutely fundamental C++. You should practise this. See if you can do the same with your reverseString function, instead of printing a string make it return a string.
There are some mistake in your code.In countString() function you return nothing.So it does not print anything.If you take input as a string include a space character,please use getline(cin, inputString).Here the code for you:
#include <iostream>
using namespace std;
void reverseString(string str)
{
for (int i=str.length()-1; i>=0; i--)
{
cout << str[i];
}
}
int countString(string strg)
{
int word = 0;
for(int j = 0; strg[j] != '\0'; j++)
{
word++;
}
return word;
}
int main(void)
{
string inputString;
cout << "Give a string: ";
getline(cin, inputString);
cout << "Reverse string: ";
reverseString(inputString);
cout << "\nCounts words in a string: ";
cout<<countString(inputString)<<endl;
return 0;
}

Check if string contain only letters

I have a trouble with a search through a string, if I enter a word with only letters, it's work as needs, I though, the code works, but when I add a number in work, the code work also, the question that, is possible to accept only if my var contains only letters, and if it will find a number or symbol, to go at begining of code?
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
label:
string var1 = "";
cout << "Enter a word: ";
cin >> var1;
for (int i = 0; i < var1.size (); i++)
{
int uppercaseCHar = toupper (var1[i]);
if (uppercaseCHar < 'A' || uppercaseCHar > 'Z')
{
goto endloop;
cout << endl;
} else
goto label;
cout << endl;
}
endloop:
cout << "Yout word contains only letters";
}
Output:
Enter a word: work
Enter a word: wro1
Enter a word: 123
Yout word contains only letters
Here is a solution that uses std::all_of:
#include <iostream>
#include <string>
#include <cctype>
#include <algorithm>
int main()
{
bool isAllLetters = false;
do
{
std::string var1;
std::cout << "Enter a word: ";
std::cin >> var1;
// check if all characters are letters
isAllLetters = std::all_of(var1.begin(), var1.end(), [](char ch)
{ return std::isalpha(static_cast<unsigned char>(ch));});
if ( isAllLetters )
std::cout << "Your word contains only letters\n";
else
std::cout << "Your word contains stuff other than letters\n"
} while ( !isAllLetters );
}
Simple and efficient (C++17):
#include <algorithm>
#include <cctype>
#include <string_view>
bool all_of_alpha(std::string_view s)
{
return std::all_of(s.begin(), s.end(), [](unsigned char c) { return std::isalpha(c); });
}
Avoid using goto as it will complicate debugging code in larger program , here's another way :
int main()
{
while (true) {
bool flag = false; // to check for numeric entry
string var1; // not req to initialize
cout << "Enter a word (press exit to end): ";
cin >> var1;
for (int i = 0; i < var1.size(); i++)
{
int uppercaseCHar = toupper(var1[i]);
if (!std::isalpha(uppercaseCHar))
{
flag = true;
break;
}
}
if (var1.compare("exit") == 0) break;
if (flag) {
cout << "Your word contains number";
cout << endl;
}
else
{
cout << "Your word contains only alphabets";
cout << endl;
}
}
}
You can also use regular expressions which will simplify the code further.
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main () {
regex reg_obj("^[A-Z]+$");
string var;
start_label:
cout << "Enter a word: ";
getline(cin, var);
if(regex_match(var, reg_obj))
goto endlabel;
else goto start_label;
endlabel:
cout << "your word contains only letters\n";
return 0;
};
Allow me to offer a more modern idiomatic version and assuming you only care about detecting alphabetic characters in the ASCII character set.
#include <iostream>
#include <algorithm>
#include <string>
int main()
{
std::string a = "abcdefgh";
std::string b = "abcd3fgh";
std::string c = "abcdefg0";
auto is_alpha = [](unsigned char c){ return std::isalpha(c); };
bool aContainsAlphas = std::all_of(a.begin(), a.end(), is_alpha);
bool bContainsAlphas = std::all_of(b.begin(), b.end(), is_alpha);
bool cContainsAlphas = std::all_of(c.begin(), c.end(), is_alpha);
std::cout << std::boolalpha;
std::cout << "A: " << aContainsAlphas << '\n'; // true
std::cout << "B: " << bContainsAlphas << '\n'; // false
std::cout << "C: " << cContainsAlphas << '\n'; // false
}
This defines a lambda which is passed as an argument to std::all_of, which uses it to test each character:
auto is_alpha = [](unsigned char c){ return std::isalpha(c); };
This invokes is_alpha on each element between a.begin() and a.end(). If the end is reached without any mismatch for is_alpha, then true is returned.
bool aContainsAlphas = std::all_of(a.begin(), a.end(), is_alpha) != a.end();

How can I count alphabet characters efficiently?

I initialized an array of characters, to put all uppercase and lowercase alphabets.
#include <iostream>
using namespace std;
int main () {
char c;
int cnt = 0;
cout << "Enter 0 to view the results " << endl;
char arr[52] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
while (1) {
for (int i = 0; i < 100000000; i++)
{
cin >> c;
if (c == arr[i]){
cnt++;
}
else if (c == '0'){
break;
}
else{
cout << "Please enter only characters!" << endl;
}
}
if (c == '0')
break;
}
cout << cnt << endl;
return 0;
}
I know that this code is inefficient.
How to write this code without break;?
If there's a better way to do that without using array, please mention it.
OP's question is very unclear but what I have understood from the comments is OP trying to find a simpler/similar way of counting someone's input for lowercase/upperCase alphabets and keep doing so until the user enters in a 0, I looked online and i found a better way and did some adjustments, it is pretty straight forward, here it is below.
#include <algorithm>
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
int main()
{
string s = "TEST";
while(s != "0"){
cout << " Enter text: ";
getline(cin, s);
size_t count_alpha = count_if(s.begin(), s.end(),
[](unsigned char ch) { return isalpha(ch); });
cout << "Alphabets: " << ( count_alpha)<<endl ;
}
}

beginner :While loop not working as it should

I am still a beginner and I am learning from a book. There was a drill that asked me filter input based on a vector of filtered words and if it was one of them it outputs "bad word"
Here is the drill exactly as in the book.
Try This
Write a program that “bleeps” out words that you don’t like; that is, you read in words using cin and print them again on cout. If a word is among a few you have defined, you write out BLEEP instead of that word. Start with one “disliked word” such as string disliked = “Broccoli”
When that works, add a few more.;
Here is the code I wrote:
#include <D:\std_lib_facilities.h>
int main()
{
// RL: omitting actual "bad" words to protect the innocent...
vector <string> bwords { "word1", "word2", "word3" };
vector <string> words;
string input = "";
while(cin >> input)
{
words.push_back(input);
}
double counter1 = 0;
double counter2 = 0;
while(counter1 < bwords.size() && counter2 < words.size())
{
if(bwords[counter1] == words[counter2])
{
cout << " bad word ";
}
else if (counter1 == bwords.size() - 1 && counter2 != words.size() )
{
cout << " "<< words[counter2] <<" ";
counter1 = 0;
}
else
{
++counter1;
counter2 += 1 / bwords.size();
}
}
}
whenever it starts it just tests the first word and repeats its self as if just tests the first if condition.
You over-complicated your loop. Try something more like this instead:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// RL: omitting actual "bad" words to protect the innocent...
const vector <string> bwords { "word1", "word2", "word3" };
string bleepWordIfBad(const string &word)
{
if (std::find(bwords.begin(), bwords.end(), word) != bwords.end())
return "BLEEP";
else
return word;
}
int main()
{
vector <string> words;
string input;
while (cin >> input)
words.push_back(input);
for (int counter = 0; counter < words.size(); ++counter)
cout << " " << bleepWordIfBad(words[counter]) << " ";
/*
Alternatively:
for (vector<string>::iterator iter = words.begin(); iter != words.end(); ++iter)
cout << " " << bleepWordIfBad(*iter) << " ";
*/
/*
Alternatively:
for (const string &word : words)
cout << " " << bleepWordIfBad(word) << " ";
*/
return 0;
}
Or, get rid of the manual loop altogether:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// RL: omitting actual "bad" words to protect the innocent...
const vector <string> bwords { "word1", "word2", "word3" };
string bleepWordIfBad(const string &word)
{
if (std::find(bwords.begin(), bwords.end(), word) != bwords.end())
return "BLEEP";
else
return word;
}
void outputWord(const string &word)
{
cout << " " << bleepWordIfBad(word) << " ";
}
int main()
{
vector <string> words;
string input;
while (cin >> input)
words.push_back(input);
for_each(words.begin(), words.end(), outputWord);
/*
Alternatively:
for_each(words.begin(), words.end(),
[](const string &word) { cout << " " << bleepWordIfBad(word) << " "; }
);
*/
return 0;
}
Or, get rid of the input vector altogether and just filter the user's input as it is being entered:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// RL: omitting actual "bad" words to protect the innocent...
const vector <string> bwords { "word1", "word2", "word3" };
string bleepWordIfBad(const string &word)
{
if (std::find(bwords.begin(), bwords.end(), word) != bwords.end())
return "BLEEP";
else
return word;
}
int main()
{
string word;
while (cin >> word)
cout << " " << bleepWordIfBad(word) << " ";
return 0;
}