string find method does not find first letter - c++

I am implementing a very simple c++ code to demo find method. The letters in the second string should be present in the first string:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
void solution(string str1, string str2){
int size1 = str1.size();
int size2 = str2.size();
if(size1 != size2){
cout<<"not equal";
return;
}
for (int i = 0; i <size2; i++){
if (str1.find(str2[i],0)){
cout<<"found "<<str2[i]<<endl;
}
}
}
int main(){
solution("abcd", "dacb");
return 0;
}
I always get an output like
found d
found c
found b
find() never matches the first letter of the first string (the string on which the find method is implemented).
Could anyone point the reason? I have tried looking up many sources. Am I missing anything about find() ?

std::string::find() returns the index of the character (or string) found. 'a' is located at index 0, which evaluates to false. Hence the behavior. You need to change the if statement to check if the returned index is equal to std::string::npos instead. Something like this:
if(str.find(str2[i]) != string::npos)
Note: You don't need to include stdio.h because you are not using printfs.

Related

How to process memory spaces saved in a pointer?

I've saved in a pointer an address of a word saved in a char list. I'm using strtok function to get the words delimited by the keywords I've set.
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int main() {
unsigned int i, z;
char sir[256];
cin.getline(sir, 256);
for(i = 0; i < strlen(sir); ++i){
char * p = strtok(sir, " ,.");
while(p != nullptr) {
// here i want to process the word.
p = strtok(sir, " ,.");
}
}
return 0;
}
What I want to do is to process the words like that:
Let's assume the word "StackOverflow", i want to go from the first letter which is "S" to the last letter which is "w". How can i do that?
Thank you very much, I hope it's clear what I'm asking.
Changed the input to a static value; but just switch that out.
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int main()
{
unsigned int i, z;
char sir[256] = "Thisissome ,.StackOverflow ,.sampletext";
//cin.getline(sir, 256);
char * p = strtok(sir, " ,.");
std::string word("StackOverflow");
do
{
printf ("%s\n",p);
std::string test(p);
if (word.compare(test) == 0)
{
printf("--> Found it!\n");
}
p = strtok (NULL, " ,.-");
} while(p != nullptr);
return 0;
}
strtok splits a string into a series of tokens. It shouldn't be successively called using the original character array to parse based on a delimiter. (i.e. the for(...) strtok(...) in OP).
The initial call expects a c-string for argument; and successful calls expects a nullptr. One each successive call; the next value will be returned from the c-string after the delimiter.
Once a null character is found; the function call will always return nullptr ( when nullptr is the first argument).
Since the solution is already using C++, this solution uses a std::string to show how each sequence of words will appear; and can be compared against a token word.
The value returned to p is still just a char*, so the OP can decide how to use the value returned by strtok. The example is intended to simply show to return delimited words using strtok; and a simple solution for seeing if that word is "StackOverflow"

Understanding String::Find In C++

I've been given a programming task that involves taking away certain letters in a string. I was trying out different ways to do this when I found the public member function string find. To put it short I was testing out the function via this program :
#include <iostream>
#include <string>
using namespace std;
int main()
{
string Word = "Applejuice";
cout<<Word.find("e")<<endl;
return 0;
}
So when I put in a letter such as "e" I get the number 4 which confuses me because I thought the function will count all the letters in that specific word such as apple juice. Also, when I use a letter that is not used in that word I get numbers like 18446744073709551615 for example when I put in X for e in the code above.
Could someone explain why this is happening, please?
string.find() will return the position of the first character of the first match.
If no matches were found, the function returns string::npos.
Therefore the number (18446744073709551615) you are getting is the string::npos
If you want to search for an only a single character in the string you can use the following code
#include <iostream>
#include <string>
using namespace std;
// Function that return count of the given
// character in the string
int count(string s, char c)
{
// Count variable
int res = 0;
for (int i=0;i<s.length();i++)
// checking character in string
if (s[i] == c)
res++;
return res;
}
// Driver code
int main()
{
string str= "Applejuice";
char c = 'e';
cout << count(str, c) << endl;
return 0;
}
If you want to avoid some random large values as output i.e. string::npos you can just add check for it like following:
if(Word.find("e") != string::npos)
{
...
}
Method find from class string return the position of the first character of the first match. Return type of find is size_t and since size_t is unsigned integral so if no match were found return string::nopos so you should compare the outputof find with string::nopos.
if(Word.find("e") != string::nopos)
{
...
}

Weird behavior of a simple for-loop code using "find" function in C++(to increment value if a certain sub-string is found)

i made a simple code for a problem solving question but the result is weird for me
here is the code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,num;
string opr;
cin>>n;
num = 0;
for(int i = 1; i <= n; i++){
cin>>opr;
if(opr.find("++"))
{
num+=1;
}
else if(opr.find("--"))
{
num-=1;
}
}
cout<<num;
}
if i input n as number "1" it actually subtract and the result is -1
but if i inserted n as 2 or more it works fine
what is happening?
std::string::find doesn't work that way:
if(opr.find("++"))
you want:
if (opr == "++")
or if you just want to see if opr contains the substring "++":
if (opr.find("++") != std::string::npos)
The problem is that std::string::find does not return a bool -- rather it returns the index at which it found the substring or std::string::npos if it doesn't find it. Since that is a number (actually a size_t) it can be implicitly converted to a bool and thus tested, but the result is not what you want. You need something like:
if(opr.find("++") != std::string::npos)
{
num+=1;
}
else if(opr.find("--") != std::string::npos)
{
num-=1;
}
if you are looking for the existence of a substring in the input.

How to delete part of a string c++ [duplicate]

I got a string and I want to remove all the punctuations from it. How do I do that? I did some research and found that people use the ispunct() function (I tried that), but I cant seem to get it to work in my code. Anyone got any ideas?
#include <string>
int main() {
string text = "this. is my string. it's here."
if (ispunct(text))
text.erase();
return 0;
}
Using algorithm remove_copy_if :-
string text,result;
std::remove_copy_if(text.begin(), text.end(),
std::back_inserter(result), //Store output
std::ptr_fun<int, int>(&std::ispunct)
);
POW already has a good answer if you need the result as a new string. This answer is how to handle it if you want an in-place update.
The first part of the recipe is std::remove_if, which can remove the punctuation efficiently, packing all the non-punctuation as it goes.
std::remove_if (text.begin (), text.end (), ispunct)
Unfortunately, std::remove_if doesn't shrink the string to the new size. It can't because it has no access to the container itself. Therefore, there's junk characters left in the string after the packed result.
To handle this, std::remove_if returns an iterator that indicates the part of the string that's still needed. This can be used with strings erase method, leading to the following idiom...
text.erase (std::remove_if (text.begin (), text.end (), ispunct), text.end ());
I call this an idiom because it's a common technique that works in many situations. Other types than string provide suitable erase methods, and std::remove (and probably some other algorithm library functions I've forgotten for the moment) take this approach of closing the gaps for items they remove, but leaving the container-resizing to the caller.
#include <string>
#include <iostream>
#include <cctype>
int main() {
std::string text = "this. is my string. it's here.";
for (int i = 0, len = text.size(); i < len; i++)
{
if (ispunct(text[i]))
{
text.erase(i--, 1);
len = text.size();
}
}
std::cout << text;
return 0;
}
Output
this is my string its here
When you delete a character, the size of the string changes. It has to be updated whenever deletion occurs. And, you deleted the current character, so the next character becomes the current character. If you don't decrement the loop counter, the character next to the punctuation character will not be checked.
ispunct takes a char value not a string.
you can do like
for (auto c : string)
if (ispunct(c)) text.erase(text.find_first_of(c));
This will work but it is a slow algorithm.
Pretty good answer by Steve314.
I would like to add a small change :
text.erase (std::remove_if (text.begin (), text.end (), ::ispunct), text.end ());
Adding the :: before the function ispunct takes care of overloading .
The problem here is that ispunct() takes one argument being a character, while you are trying to send a string. You should loop over the elements of the string and erase each character if it is a punctuation like here:
for(size_t i = 0; i<text.length(); ++i)
if(ispunct(text[i]))
text.erase(i--, 1);
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str = "this. is my string. it's here.";
transform(str.begin(), str.end(), str.begin(), [](char ch)
{
if( ispunct(ch) )
return '\0';
return ch;
});
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;//string is defined here.
cout << "Please enter a string with punctuation's: " << endl;//Asking for users input
getline(cin, s);//reads in a single string one line at a time
/* ERROR Check: The loop didn't run at first because a semi-colon was placed at the end
of the statement. Remember not to add it for loops. */
for(auto &c : s) //loop checks every character
{
if (ispunct(c)) //to see if its a punctuation
{
c=' '; //if so it replaces it with a blank space.(delete)
}
}
cout << s << endl;
system("pause");
return 0;
}
Another way you could do this would be as follows:
#include <ctype.h> //needed for ispunct()
string onlyLetters(string str){
string retStr = "";
for(int i = 0; i < str.length(); i++){
if(!ispunct(str[i])){
retStr += str[i];
}
}
return retStr;
This ends up creating a new string instead of actually erasing the characters from the old string, but it is a little easier to wrap your head around than using some of the more complex built in functions.
I tried to apply #Steve314's answer but couldn't get it to work until I came across this note here on cppreference.com:
Notes
Like all other functions from <cctype>, the behavior of std::ispunct
is undefined if the argument's value is neither representable as
unsigned char nor equal to EOF. To use these functions safely with
plain chars (or signed chars), the argument should first be converted
to unsigned char.
By studying the example it provides, I am able to make it work like this:
#include <string>
#include <iostream>
#include <cctype>
#include <algorithm>
int main()
{
std::string text = "this. is my string. it's here.";
std::string result;
text.erase(std::remove_if(text.begin(),
text.end(),
[](unsigned char c) { return std::ispunct(c); }),
text.end());
std::cout << text << std::endl;
}
Try to use this one, it will remove all the punctuation on the string in the text file oky.
str.erase(remove_if(str.begin(), str.end(), ::ispunct), str.end());
please reply if helpful
i got it.
size_t found = text.find('.');
text.erase(found, 1);

Scanning User Input for Strings Declared in an Array

I am creating a program that scans user input for words that are listed in an array. The find() function seems like it'll work, but I can't find anything showing how to implement it for what I want to do. I'm pretty new to programming (obviously).
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
string subj [5]={"I","He","She","We","They"};
string verb [5]={" like"," hate"," sacrifice"," smell"," eat"};
string obj [5]={" bacon","s cats","s bagels","s children","s cops"};
string greeting [5]={"How are you","How's it going","Sup dude","Hey","Hello"};
string negvibe [4]={"bad","terrible","lousy","meh"};
string userfeeling;
int main()
{
srand(time(0));
int rando = rand() %5;//generates a random number between 0 and 4
int rando1 = rand() %5;
int rando2 = rand() %5;
cout << greeting [rando1] << "." << endl;
getline(std::cin,userfeeling);
if .... // What has to be done here?
find(negvibe, negvibe + 4, userfeeling) != negvibe + 4);
// Something like that?
// then ...
{
cout << subj[rando] << verb[rando1] << obj[rando2] <<"." <<endl;
}
return 0;
}
To make find work properly you should user iterators like so
if(find(std::begin(negvibe), std::end(negvibe), userfeeling) != std::end(negvibe)){
//code you want to happen if your word is found
}
Also in your current code, the if statement doesnt actually do anything since you end it with a semicolon and not {} or leave it blank if its one line. You can see an example of the if statement as well
Below is a link to find and iterators
http://www.cplusplus.com/reference/algorithm/find/
That find function will find some element of the negvibe array that is equal to userfeeling. If you are checking whether any element of negvibe is a substring of userfeeling, you should loop through negvibe and use the std::string::find method.
bool found_negvibe = false;
for (int i = 0; i < sizeof(negvibe) / sizeof(*negvibe); i++) {
found_negvibe = found_negvibe || userfeeling.find(negvibe[i]) != string::npos;
}
Also, you don't need to specify the size of the negvibe array, you can write this:
string negvibe[] = {"bad","terrible","lousy","meh"};
One more thing, you might prefer to use a std::vector over an array, if only because c++'s faculties for getting the size of a vector are slightly more succinct than those for getting the size of an array.
vector negvibe = {"bad","terrible","lousy","meh"};
bool found_negvibe = false;
for (int i = 0; i < negvibe.size(); i++) {
found_negvibe = found_negvibe || userfeeling.find(negvibe[i]) != string::npos;
}