Recursively find a string within a string in C++ - c++

(C++)
Given myString, I want to check if myString contains substring. Here's what I have so far, but it only returns true if the string begins with the substring.
bool find(string myString, string substring)
{
if(mystring.length() < substring.length())
{
return false;
}
if(mystring == substring)
{
return true;
}
for(int i = 0; i < substring.length() - 1 ; ++i)
{
if(mystring.at(i) == substring.at(i))
{
continue;
}
else
{
string string2 = mystring.substr(1, mystring.length() - 1);
return find(string2, substring);
}
return true;
}
return false;
}
What is wrong with this function?

Check this function, it based on your code, with removal of extra code and fix of the errors.
I also changed the signature to get const reference to improve the efficiency.
bool find(const string& myString, const string& substring)
{
if(myString.length() < substring.length()){
return false;
}
else if(myString.substr(0,substring.size()) == substring){
return true;
}
else if (myString.length() > substring.length()){
return find(myString.substr(1), substring);
}
else{
return false;
}
}

First of all the function can be written simpler. For example
bool find( const std::string &myString, const std::string &subString )
{
return
( myString.substr( 0, subString.size() ) == subString ) ||
( subString.size() < myString.size() && find( myString.substr( 1 ), subString ) );
}
Here is a demonstrative program
#include <iostream>
#include <iomanip>
#include <string>
bool find( const std::string &myString, const std::string &subString )
{
return
( myString.substr( 0, subString.size() ) == subString ) ||
( subString.size() < myString.size() && find( myString.substr( 1 ), subString ) );
}
int main()
{
std::cout << std::boolalpha << find( "Hello World", "World" ) << std::endl;
std::cout << std::boolalpha << find( "Hello C", "C++" ) << std::endl;
}
The program output is
true
false
As for your function then it will return true only in the case when the both string have the same length and are equal each other
if(myString == substring){
return true;
}
And in case when myString.length() > substring.length() the function returns nothing
else if (myString.length() > substring.length()){
int start = 1;
int end = (int) myString.length() - 1;
string string2 = myString.substr(start, end);
find(string2, substring);
}
I think you mean
return find(string2, substring);
in this code snippet.
EDIT: I see that you changed the code of the function in your post. But in any case this code snippet
for(int i = 0; i < substring.length() - 1 ; ++i)
{
if(mystring.at(i) == substring.at(i))
{
continue;
}
else
{
string string2 = mystring.substr(1, mystring.length() - 1);
return find(string2, substring);
}
return true;
}
makes no sense.

You're missing a return before the recursive call to find. As it stands it falls through to the return false at the end.
Also, if (mystring == substring) should be checking if mystring starts with substring, not exact equality.

First, this is expensive because of the memory copies in substr.
Second, you havent checked for substring length > 0.
Third, the "else if" check for mystring.length > 0 is redundant if you have done the other checks (including substring length > 0).
Now to your core logic. In the recursion your start is never moving, so you are tied to the beginning. What you need to do is start with position 1, and increment start at every recursion, and also extract using substr the substring from "start" to "start + substring.length". That way you start from the beginning, keep moving forward, and check the correct length. You could also start from the end (as you have) and move back, what you would have to do there is: find sart position (end position minus length of substring), and check that the start position is not less than zero before calling the function recursively.

You're just removing the leftmost characters of myString and then comparing the rest to your substring. Obviously, this is not going to work in a general case, when your substring is somewhere in the middle of myString.
On each iteration try comparing not the whole myString, but rather the first substring.size() characters of it. This should fix your issue.

Here's what I have so far, but it only returns true if the string
begins with the substring.
It also fails for find("foo", "f").
To see why, add some test output to the function:
bool find(string myString, string substring)
{
std::cout << myString << ", " << substring << "\n";
// ...
}
It will print:
foo, f
oo, f
o, f
You see why this cannot work? You just keep removing the first character, until only the last character is compared with the substring to be found.
But it fails even for find("foo", "o"):
foo, o
oo, o
o, o
That's because of this line:
find(string2, substring);
You don't return the result of the recursive call.
All things considered, I think you just have the wrong algorithm here. It simply cannot work the way you have written the code.
A few other observations:
int start = 1;
int end = (int) myString.length() - 1;
That's not good style. For historical reasons, a std::string's size is unsigned, and you are using a C-style cast where static_cast should be preferred. You should just use std::string::size_type here, because it's just an internal piece of implementation code and you gain nothing from casting to int.
string string2 = myString.substr(start, end);
The second argument of substr defines the length of the substring, not the index of the last character. end sounds like you use the value as the index of the last character. Have a look at http://en.cppreference.com/w/cpp/string/basic_string/substr.

Related

Finding index of needle in haystack recursively.

I am pretty close to completing my function. I need to take 2 strings, and return the index of string 2 inside of string 1. I know there is a find function for this, but I am not able to use it. It also has to be done with recursive programming.
I have the following.
int index_of(string haystack, string needle) {
int index = 0;
string test = haystack.substr(index, needle.length());
if (test == needle) {
return index;
}
else {
return 1 + index_of(haystack.substr(1), needle);
}
}
It returns the index of the needle in the haystack no problem but there are 2 things it needs to do I can not figure out.
1) If the needle is not in the haystack, then it needs to return a -1. I have done it so at the end if it does not exist, it returns a -1, but because it is recursive, it then adds the other times it returned 1. I am not sure how to just return a single value at the end without adding all the other instances on it.
2) I am suppose to use a helper function within it and I am not sure how to do that either.
Thanks for any help!
In general, you want to return the value of a recursive function unadulterated. In your case, this:
return 1 + index_of(some_parameters);
Should be this:
return index_of(some_parameters);
Now, you just need to choose parameters such that you can keep track of the index until you need to return it, or alternatively -1.
One such function might have the constructor:
index_of(string haystack, string needle, int index);
Here is a demonstrative program that shows how the function can be implemented.
#include <iostream>
#include <string>
std::string::size_type index_of( std::string haystack, const std::string &needle )
{
if ( haystack.size() < needle.size() ) return std::string::npos;
if ( haystack.compare( 0, needle.size(), needle ) == 0 ) return 0;
std::string::size_type index;
return ( index = index_of( haystack.substr( 1 ), needle ) ) == std::string::npos ? index : ++index;
}
int main()
{
std::string haystack( "asdfghjkl" );
std::string needle( "gh" );
std::string::size_type index = index_of( haystack, needle );
if ( index != std::string::npos )
{
std::cout << "string \"" << needle
<< "\" is found in string \"" << haystack
<< "\" at position " << index
<< std::endl;
}
else
{
std::cout << "string \"" << needle
<< "\" is not found in string \"" << haystack << "\""
<< std::endl;
}
}
Its output is
string "gh" is found in string "asdfghjkl" at position 4
Of course the simplest approach is to define a static variable that would keep the current position in the source string. But in this case I do not think that such a function is a "pure recursive".

Idiomatic way to match a regular expression in C++

I want to compare two strings in C++:
There is a function getName() that returns a string.
Now I can write Out << getName(); this will print the string.
However I want to print the string only if its value is arpit or arpit*N* where N is an integer. I don't want to print it if its value is arpita, arpitx, where N is something other than an integer or an empty string.
I know this can be easily done, but I want to do this in a minimal number of lines.
What I have done so far is:
char name1[] = getName();
char name2[] = "arpit";
for (int x = 0; x <= 4; x++){
if (name1[x] == name2[x]) continue;
else return ( Out << "not equal") ;
}
while(name1[x] ! = "\0"){
if(isdigit(name1[x])
x++;
else return (Out << "not equal") ;
}
Out << getName();
UPDATE 1
getName() returns a string until it encounters white space, and it will not return any line or 2 or more words.
If you have C++11:
static std::regex const matcher( "arpit\\d*" );
if ( regex_match( name, matcher ) ) {
// matches...
}
If you don't have C++11, boost::regex is practically identical.
If you don't have C++11, and you can't use boost:
if ( name1.size() >= name2.size()
&& std::equal( name2.begin(), name2.end(), name1.begin() )
&& std::find_if( name1.begin() + name2.size(),
name1.end(),
[]( unsigned char ch ) { return !isdigit( ch ); }
) == name1.end() )
// matches...
}
For the rest, your code has quite a few errors, and shouldn't
compile. In particular, there is nothing which getName()
could return which can be used to initialize a char []; the
type of a string in C++ is std::string, and your variables
should be:
std::string name1( getName() );
std::string name2( "arpit" );
(except that you need better names. The second might be
something like reference or header, for example.)
And of course, it's undefined behavior to call isdigit with
a char; you have to convert to unsigned char first.
auto s = getName();
if(s.size() >= 5 && s.substr(0,5) == "arpit")
Out << s;
std::set<std::string> m_allowed_strings;
std::string validate_string(const string & s)
{
if(m_allowed_strings.find(s) != m_allowed_strings.end())
return s;
return "";
}
cout << validate_string(getName());

String matching implementation

I wrote the below code to check whether a certin string exists in a text or no. The issue is that match() function always returns false even the pattern exists in the text.
int main(){
char *text="hello my name is plapla";
char *patt="my";
cout<<match(patt,text);
system("pause");
return 0;
}
bool match(char* patt,char* text){
int textLoc=0, pattLoc=0, textStart=0;
while(textLoc <= (int) strlen(text) && pattLoc <= (int)strlen(patt)){
if( *(patt+pattLoc) == *(text+textLoc) ){
textLoc= textLoc+1;
pattLoc= pattLoc+1;
}
else{
textStart=textStart+1;
textLoc=textStart;
pattLoc=0;
}
}
if(pattLoc > (int) strlen(patt))
return true;
else return false;
}
Try pattLoc < (int)strlen(patt) in your while loop.
Loop will stop when pattLoc == 2, so you avoid comparing the '\0' of "my" with the ' ' of "hello my name is pala", which set pattloc to 0 and return false.
Or better, use string substr.
The obvious solution is:
bool
match( std::string const& pattern, std::string const& text )
{
return std::search( text.begin(), text.end(),
pattern.begin(), pattern.end() )
!= text.end();
}
This is idiomatic C++, and the way I would expect any C++ programmer to
write it, at least in a professional environment.
If the goal is to learn how to write such a function, then of course,
the above isn't much of a solution. The solution then should be mroe
divide and conquer; there's much too much in match for you to put it
in one function. I'd recommend something like:
bool
startsWith( std::string::const_iterator begin,
std::string::const_iterator end,
std::string const& pattern )
{
return end - begin >= pattern.size()
&& std::equal( pattern.begin(), pattern.end(), begin );
}
bool
match( std::string const& pattern, std::string const& text )
{
std::string::const_iterator current = text.begin();
while ( current != text.end()
&& !startsWith( begin, text.end(), pattern ) ) {
++ current;
}
return current != text.end();
}
This can obviously be improved; for example, there's no point in
continuing in the while loop when the length of the remaining text is
less than the length of the pattern.
And if your professor insists on your using char const* (if he insists
on char*, then he's totally incompetent, and should be fired), this
can easily be rewritten to do so: just replace all calls to begin with
the pointer, and all calls to end with pointer + strlen(pointer).
I have solved the problem:
while(textLoc <= (int) strlen(text) && pattLoc <= (int)strlen(patt))
should be:
while(textLoc < (int) strlen(text) && pattLoc < (int)strlen(patt))
and
if(pattLoc > (int) strlen(patt))
to
if(pattLoc >= (int) strlen(patt))

Loop quitting for no reason

I have a question regarding C++. This is my current function:
string clarifyWord(string str) {
//Remove all spaces before string
unsigned long i = 0;
int currentASCII = 0;
while (i < str.length()) {
currentASCII = int(str[i]);
if (currentASCII == 32) {
str.erase(i);
i++;
continue;
} else {
break;
}
}
//Remove all spaces after string
i = str.length();
while (i > -1) {
currentASCII = int(str[i]);
if (currentASCII == 32) {
str.erase(i);
i--;
continue;
} else {
break;
}
}
return str;
}
Just to get the basic and obvious things out of the way, I have #include <string> and using namespace std; so I do have access to the string functions.
The thing is though that the loop is quitting and sometimes skipping the second loop. I am passing in the str to be " Cheese " and it should remove all the spaces before the string and after the string.
In the main function, I am also assigning a variable to clarifyWord(str) where str is above. It doesn't seem to print that out either using cout << str;.
Is there something I am missing with printing out strings or looping with strings? Also ASCII code 32 is Space.
Okay so the erase function you are calling looks like this:
string& erase ( size_t pos = 0, size_t n = npos );
The n parameter is the number of items to delete. The npos means, delete everything up until the end of the string, so set the second parameter to 1.
str.erase(i,1)
[EDIT]
You could change the first loop to this:
while (str.length() > 0 && str[0] == ' ')
{
str.erase(0,1);
}
and the second loop to this:
while (str.length() > 0 && str[str.length() - 1] == ' ')
{
str.erase(str.length() - 1, 1);
}
In your second loop, you can't initialize i to str.length().
str[str.length()] is going to be after the end of your string, and so is unlikely to be a space (thus triggering the break out of the second loop).
You're using erase (modifying the string) while you're in a loop checking its size. This is a dangerous way of processing the string. As you return a new string, I would recommend you first to search for the first occurrence in the string of the non-space character, and then the last one, and then returning a substring. Something along the lines of (not tested):
size_t init = str.find_first_not_of(' ');
if (init == std::string::npos)
return "";
size_t fini = std.find_last_not_of(' ');
return str.substr(init, fini - init + 1);
You see, no loops, erases, etc.
unsigned long i ... while (i > -1) Well, that's not right, is it? How would you expect that to work? The compiler will in fact convert both operands to the same type: while (i > static_cast<unsigned long>(-1)). And that's just another way to write ULONG-MAX, i.e. while (i > ULONG_MAX). In other words, while(false).
You're using erase incorrectly. It'll erase from pos to npos.
i.e. string& erase ( size_t pos = 0, size_t n = npos );
See: http://www.cplusplus.com/reference/string/string/erase/
A better way to do this is to note the position of the first non space and where the spaces occur at the end of the string. Then use either substr or erase twice.
You also don't need to go to the trouble of doing this:
currentASCII = int(str[i]);
if (currentASCII == 32) {
Instead do this:
if (str[i] == ' ') {
Which I think you'll agree is a lot easier to read.
So, you can shorten it somewhat with something like: (not tested but it shouldn't be far
off)
string clarifyWord(string str) {
int start = 0, end = str.length();
while (str[start++] == ' ');
while (str[end--] == ' ');
return str.substr(start, end);
}

Write a recursive function that reverses the input string

I've been reading the book C++ For Everyone and one of the exercises said to write a function string reverse(string str) where the return value is the reverse of str.
Can somebody write some basic code and explain it to me? I've been staring at this question since yesterday and can't figure it out. The furthest I've gotten is having the function return the first letter of str (Which I still don't know how it happened)
This is as far as I got (An hour after posting this question):
string reverse(string str)
{
string word = "";
if (str.length() <= 1)
{
return str;
}
else
{
string str_copy = str;
int n = str_copy.length() - 1;
string last_letter = str_copy.substr(n, 1);
str_copy = str_copy.substr(0, n);
word += reverse(str_copy);
return str_copy;
}
return word;
}
If I enter "Wolf", it returns Wol. Somebody help me out here
If I return word instead of return str_copy then I get a w
If I return last_letter then I get an l
I'll instead explain the recursive algorithm itself. Take the example "input" which should produce "tupni". You can reverse the string recursively by
If the string is empty or a single character, return it unchanged.
Otherwise,
Remove the first character.
Reverse the remaining string.
Add the first character above to the reversed string.
Return the new string.
Try this one
string reverse(string &s)
{
if( s.length() == 0 ) // end condtion to stop recursion
return "";
string last(1,s[s.length()-1]); // create string with last character
string reversed = reverse(s.substr(0,s.length()-1));
return last+reversed; // Make he last character first
}
A recursive function must have the following properties
It must call itself again
It must have a condition when the recursion ends. Otherwise you have a function which
will cause a stack overflow.
This recursive function does basically create a string of the last character and then call itself again with the rest of the string excluding the last character. The real switching happens at the last line where last+reversed is returned. If it would be the other way around nothing would happen.
It is very inefficient but it works to show the concept.
Just to suggest a better way of handling recursion:
String reversal using recursion in C++:
#include <iostream>
#include <string>
using namespace std;
string reverseStringRecursively(string str){
if (str.length() == 1) {
return str;
}else{
return reverseStringRecursively(str.substr(1,str.length())) + str.at(0);
}
}
int main()
{
string str;
cout<<"Enter the string to reverse : ";
cin>>str;
cout<<"The reversed string is : "<<reverseStringRecursively(str);
return 0;
}
I won't write a full-blown algorithm for you, but here's a hint:
How about swapping the two outermost characters, and then apply the same to the characters in the middle?
Oh, and if that book really proposed string reverse(string str) as an appropriate function signature for this, throw it away and buy a good book instead.
Here is my version of a recursive function that reverses the input string:
void reverse(char *s, size_t len)
{
if ( len <= 1 || !s )
{
return;
}
std::swap(s[0], s[len-1]);// swap first and last simbols
s++; // move pointer to the following char
reverse(s, len-2); // shorten len of string
}
Shortest and easiest
class Solution {
public:
string reverseString(string s) {
string str;
if(s != "\0"){
str = reverseString(s.substr(1, s.length()));
str += s.substr(0,1);
}
return str;
}
};
1-line recursive solution:
string RecursiveReverse(string str, string prev = "") {
return (str.length() == 0 ? prev : RecursiveReverse(str.substr(0, str.length()-1), prev += str[str.length()-1]));
}
You call it like this:
cout << RecursiveReverse("String to Reverse");
I know I shouldn't give a solution, but since no one mentioned this easy solution I though I should share it. I think the code literally is the algorithm so there is no need for a pseudo-code.
void c_plusplus_recursive_swap_reverse(std::string::iterator start,
std::string::iterator end)
{
if(start >= end) {
return;
}
std::iter_swap(start, end);
c_plusplus_recursive_swap_reverse(++start, --end);
}
To call it use:
c_plusplus_recursive_swap_reverse(temp.begin(), temp.end());
All existing solutions had way too much code that didn't really do anything, so, here's my take at it:
#include <iostream>
#include <string>
std::string
r(std::string s)
{
if (s.empty())
return s;
return r(s.substr(1)) + s[0];
}
int
main()
{
std::cout << r("testing") << std::endl;
}
P.S. I stumbled upon this question trying to find a C++ way for std::string of what s+1 for a char * in C is; without going the whole route of s.substr(1, s.length()-1), which looks too ugly. Turns out, there's std::string::npos, which means until the end of the string, and it's already the default value for the second argument, so, s.substr(1) is enough (plus, it also looks more efficient and on par with the simple s + 1 in C).
Note, however, that recursion in general doesn't scale as the input grows larger, unless the compiler is able to do what is known as tail-recursion optimisation. (Recursion is rarely relied upon in imperative languages.)
However, in order for the tail recursion optimisation to get activated, it is generally required that, (0), the recursion only happens within the return statement, and that, (1), no further operations are performed with the result of the recursive call back in the parent function.
E.g., in the case above, the + s[0] is logically done by the parent after the child call completes (and it probably would be so even if you go the more uglier s[s.length()-1] + route), so, it might as well prevent most compilers from doing a tail-recursion-optimisation, thus making the function very inefficient on large inputs (if not outright broken due to heap exhaustion).
(For what it's worth, I've tried writing a more tail-recursion-friendly solution (making sure to grow the return result through an argument to the function itself), but disassembly of the resulting binary seems to suggest that it's more involved than that in the imperative languages like C++, see gcc: is there no tail recursion if I return std::string in C++?.)
you can implement your own reverse similar to std::reverse.
template <typename BidirIt>
void reverse(BidirIt first, BidirIt last)
{
if((first == last) || (first == --last))
return;
std::iter_swap(first, last);
reverse(++first, last);
}
I did something like this, it did the reversal in place. I took two variables that traverse the string from two extreme end to the centre of the string and when they overlap or equal to each other then reversal terminates.
Take an example: input string str = "abcd" and call the function as
ReverseString(str,0,str.length()-1);
and increment/decrement the variable pointers recursively.
First the pointers points to 'a' and 'd' and swap them, then they point to 'b' and 'c' and swap them. Eventually i >= j which calls for the base case to be true and hence the recursion terminates. The main take away for this question is to pass input string as reference.
string ReverseString(string& str,int i,int j){
if(str.length() < 1 || str == "" || i >= j){
return "";
}
else{
char temp = str[i];
str[i] = str[j];
str[j] = temp;
ReverseString(str,i+1,j-1);
}
return str;
}
String can be reversed in-place. If we start from smallest possible string i.e. one character string, we don't need to do anything. This is where we stop or return from our recursive call and it becomes our base case.
Next, we have to think of a generic way to swap the smallest string i.e. two characters or more. Simplest logic is to swap the current character str[current_index] with character on the opposite side str[str_length-1 - current_index].
In the end, call the reverse function again for next index.
#include <iostream>
using namespace std;
void reverse_string(std::string& str, int index, int length) {
// Base case: if its a single element, no need to swap
// stop swapping as soon as we reach the mid, hence index*2
// otherwise we will reverse the already reversed string
if( (length - index*2) <= 1 ) {
return;
}
// Reverse logic and recursion:
// swap current and opposite index
std::swap(str[index], str[length-1 - index]);
// do the same for next character (index+1)
reverse_string(str, index+1, length);
}
int main() {
std::string s = "World";
reverse_string(s, 0, s.length());
std::cout << s << endl;
}
There are already some good answer but I want to add my approach with full working Recursive reversing string.
#include <iostream>
#include <string>
using namespace std;
char * reverse_s(char *, char*, int,int);
int main(int argc, char** argv) {
if(argc != 2) {
cout << "\n ERROR! Input String";
cout << "\n\t " << argv[0] << "STRING" << endl;
return 1;
}
char* str = new char[strlen(argv[1])+1];
strcpy(str,argv[1]);
char* rev_str = new char[strlen(str)+1];
cout<<"\n\nFinal Reverse of '" << str << "' is --> "<< reverse_s(str, rev_str, 0, strlen(str)) << endl;
cin.ignore();
delete rev_str, str;
return 0;
}
char* reverse_s(char* str, char* rev_str, int str_index, int rev_index ) {
if(strlen(str) == 1)
return str;
if(str[str_index] == '\0' ) {
rev_str[str_index] = '\0';
return rev_str;
}
str_index += 1;
rev_index -=1;
rev_str = reverse_s(str, rev_str, str_index, rev_index);
if(rev_index >= 0) {
cout << "\n Now the str value is " << str[str_index-1] << " -- Index " << str_in
dex << " Rev Index: " << rev_index;
rev_str[rev_index] = str[str_index-1];
cout << "\nReversed Value: " << rev_str << endl;
}
return rev_str;
}
void reverse(string &s, int &m) {
if (m == s.size()-1)
return;
int going_to = s.size() - 1 - m;
string leader = s.substr(1,going_to);
string rest = s.substr(going_to+1,s.size());
s = leader + s.substr(0,1) + rest;
reverse(s,++m);
}
int main ()
{
string y = "oprah";
int sz = 0;
reverse(y,sz);
cout << y << endl;
return 0;
}
void ClassName::strgRevese(char *str)
{
if (*str=='\0')
return;
else
strgRevese(str+1);
cout <<*str;
}
here is my 3 line string revers
std::string stringRevers(std::string s)
{
if(s.length()<=1)return s;
string word=s.at(s.length()-1)+stringRevers(s.substr(0,s.length()-1));//copy the last one at the beginning and do the same with the rest
return word;
}
The question is to write a recursive function. Here is one approach. Not a neat code, but does what is required.
/* string reversal through recursion */
#include <stdio.h>
#include <string.h>
#define size 1000
char rev(char []);
char new_line[size];
int j = 0;
int i =0;
int main ()
{
char string[]="Game On";
rev(string);
printf("Reversed rev string is %s\n",new_line);
return 0;
}
char rev(char line[])
{
while(line[i]!='\0')
{
i++;
rev(line);
i--;
new_line[j] = line[i];
j++;
return line[i];
}
return line[i];
}
It will reverse Original string recursively
void swap(string &str1, string &str2)
{
string temp = str1;
str1 = str2;
str2 = str1;
}
void ReverseOriginalString(string &str, int p, int sizeOfStr)
{
static int i = 0;
if (p == sizeOfStr)
return;
ReverseOriginalString(str, s + 1, sizeOfStr);
if (i <= p)
swap(&str[i++], &str[p])
}
int main()
{
string st = "Rizwan Haider";
ReverseOriginalString(st, 0, st.length());
std::cout << "Original String is Reversed: " << st << std::endl;
return 0;
}