What is wrong with this recursive code? - c++

I am doing online work using CodeLab for C++ and am not sure what's wrong with my code. Here is the question:
Write a recursive, int-valued function, len, that accepts a string and returns the number of characters in the string.
The length of a string is:
0 if the string is the empty string ("").
1 more than the length of the rest of the string beyond the first character.
And here's my code:
int len(string s)
{
if (s.length()==0)
return 0;
else
{
return 1+(len(s)-1);
}
}
It says I have a run-time error.
Any help?
Thanks.

Well here:
return 1+(len(s)-1);
The length of the string never decreases. So you will eventually have a stackoverflow because you never hit your base case (s.length() == 0). You need to get a substring where the length of s decreases by 1:
return 1+(len(s.erase(0,1))); // erases 1 char from beginning then recurses
Hopefully this is purely academic, because std::string has a length method that will run in constant time. (Not to mention erasing from the front of a string is probably horribly inefficient-- see the other answers that work with char *)

You are never modifying s in your code, so if s is not empty you keep calling the same function and again, with the same parameter; your never stop. Your computer runs out of stack space and the program crashes.
Others have given you some ideas/options. Here's mine suggestion:
int len(const std::string &s, int start)
{
/* If we are starting at the end, there's no more length */
if(start == s.length())
return 0;
/* one plus whatever else... */
return 1 + len(s, start + 1);
}
Assuming str is the string you want to get the length of, you can call it as: len(str, 0)
If you need to use a const char * version try this:
int len(const char *s)
{
if((s == NULL) || (*s == 0))
return 0; /* we ran out of string! */
return 1 + len(s + 1);
}

len(s) will never decrease and cause a stackoverflow. I would do something like:
int len(const char * s) {
if(*s == '\0')
return 0;
else
return 1 + len(s+1);
}

Another solution:
int len(string s)
{
if (s.length()==0)
return 0;
else
{
s = s.substr(0, s.size()-1);
return 1+(len(s));
}
}

Related

Expression must have class type while using pointers

I am trying to count in a string1 how many times string2 exists. For example:
string1 = abababd.
string2 = ab.
Result: 3.
(I must use pointers for this question)
What I have so far:
int mystr(char* s, char* t) {
int counter = 0;
int length = strlen(t);
while (*s != '\0')
{
char d[] = *s.substr(0, 2);
if (*s == *t)
counter++;
*s += length;
}
return counter;
}
I keep receiving the issue:
Expression must have class type for this line: char d[] = *s.substr(0, 2);
Can someone assist please?
substr is a method of class std::string.
You are using C pointers here (char* s), so there is no substr() to call, thus the error.
Of course, I'll leave the implementation to you, but you can get inspired by create my own substr.
Since OP is showing good faith in trying to do their own HW, let's comment on the approach so far:
int mystr(char* s, char* t) {
int counter = 0;
int length = strlen(t);
// while we haven't reach the end of string
while (*s != '\0')
{
// this is not used anywhere, and it's wrong. Why 2? You want the length of `t` there, if you would use it anyway
char d[] = *s.substr(0, 2);
// this is wrong. It will increase the counter,
// every time a character of the substring is matched with the
// current character in the string
if (*s == *t)
counter++;
// you want to read the next chunk of the string, seems good for a start
*s += length;
}
return counter;
}
So now, you should focus on how to check if the current substring is matched in the string. So, you need to change this:
if (*s == *t)
counter++;
into something that will check all the characters of t, versus the same number of characters of the string, from current position. So, you need to iterate through *s. How many times? For as much as the length of t.
In that iteration, you would need to check that the current character of string s is the compared equal to the current character of string t. When the iteration ends, and if all characters visited during that iteration where the same, then that means that you found a match! So, if that is true, then we should increment the counter.
Bonus: If you have time, and have completed the logic discussed above, think about *s += length; and this input: `s = "dabababd", t = "ab".

C++, String to Array of Characters with my professor's limitations

I'm learning C++, and I have no idea how I'm supposed to do the following.
In an assignment, we need to write a function that checks if the first two characters of a string are the same as the last two.
These are the limitations:
You cannot use std::string class or string function such as strlen. You must use either array or pointer for this function.
I tried this:
bool haveTheSameTwoChars(string str) {
char arr[] = str;
if (sizeof(arr) < 3) {
return false;
}
else if (arr[0] == arr[sizeof(arr) - 3] && arr[1] == arr[sizeof(arr) - 2]) {
return true;
}
else {
return false;
}
}
But it won't accept str into the array.
However, if I were to put something in quotes in the place of str, it accepts it just fine, despite them both being strings.
What am I doing wrong?
Well, here's the breakdown of your problem:
You need to take input as an array or a pointer. For example:
bool isMatched( const char* str )
{
// ...
}
Now, you need to calculate the length of your string yourself. Revise the loops and devise something that gives you the length of a null terminated string. C-strings are null-terminated i.e. '\0' so you can end your loop when you encounter null character. For example:
int len = 0;
while ( str[len] != '\0' ) len++;
That's just an idea. Do your own research and calculate the string length correctly.
The rest is just a comparison of first and last two characters using if. :)
I'm sure you can put things together and revise your study material a bit to solve this.
Best of luck!
Happy coding!
When you're not allowed strlen, it is a strong hint that the problem can be solved without caring about the length of the string.
Let's do that:
First, you should have the prototype (no strings allowed, right?)
bool haveTheSameTwoChars(const char* str)
Then, verify that the string has at least two characters
if (!str || !str[0] || !str[1])
return false;
Then you find the end of the string:
const char* end = str;
while (*end)
end++;
Then move back two characters, so end points to the first of the last two characters:
end -= 2;
(This is safe since we first checked that there are at least two characters.)
Then compare
return str[0] == end[0] && str[1] == end[1];
Your professor wants you to use a const char* as the function parameter, that is, model a string as a pointer to the first character in the string, where the string finishes with a 0. (We call this NUL-termination).
So your function is
bool haveTheSameTwoChars(const char* s)
You then need to roll your own version of strlen1 to calculate the number of characters in the string up to and not including the NUL:
#include <cstddef> // for std::size_t
std::size_t strlen(const char *s) {
const char *p = s;
while (*s) ++s;
return s - p;
}
After which, it's a simple case, given the length l say, of dealing with a couple of edge cases and the general case:
If l is 0 or 1, return false.
If l is 2, return true.
If l is greater than 2 then something similar to how you have it in the question will suffice, remembering that my l is one less than yours.
Note that C++ does not support variable length arrays, so char arr[] = str; is not valid C++, and sizeof is a compile-time operator so would only give you the size of an actual array type, not an array that's decayed to a pointer type.
1 No professional programmer would dream of doing that. A compiler might optimise strlen down to a machine word-based algorithm, i.e. consider multiple bytes simultaneously.
Here is some sample code for your purpose
bool haveTheSameTwoChars(const char* p) {
if(!p || !*p)
return false;
int len = -1;
while(p[++len]);
if(p[0] == p[len-2] &&
p[1] == p[len-1])
return true;
return false;
}
This will return true if the string is "ABxxxAB" and false if "ABxxxBA". Rest you can tweak according to your desire.Thanks
Another approach uses a loop and a single pointer to iterate over each line saving the first and second characters to compare against the next to last (penultimate) and last (ultimate) characters in the string.
By using simple iteration over the character array, as long as it is nul-terminated, you don't have to worry about a separate loop to find the length, you simply grab/save the first two characters, and then iterate to the end of your string saving the prev/last characters as you go. When you hit the end of your string, all you need to do is compare the first against the last and the second against the next to last, e.g.
/* function iterates pointer through chars in 'line' saving
* the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
* ultimate characters in 'prev' & 'last' and compares. returns 1 if
* 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
*/
int begmatchend (const char *line)
{
const char *p = line; /* pointer to line */
char beg = *p++, /* save for 1st char */
next = *p++, /* save for 2nd char */
prev = *p++, /* save for next to last char */
last = *p++; /* save for last char */
while (*p) { /* iterate over line setting prev/last as you go */
prev = last;
last = *p++;
}
if (beg == last && next == prev) /* test whether equal */
return 1;
return 0;
}
Then for a simple test, you can just feed your programs lines from a file calling begmatchend on each line and then output indication of which lines matched. Something simple like the following is one way:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstddef>
#define MAXC 1024
/* function iterates pointer through chars in 'line' saving
* the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
* ultimate characters in 'prev' & 'last' and compares. returns 1 if
* 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
*/
int begmatchend (const char *line)
{
const char *p = line; /* pointer to line */
char beg = *p++, /* save for 1st char */
next = *p++, /* save for 2nd char */
prev = *p++, /* save for next to last char */
last = *p++; /* save for last char */
while (*p) { /* iterate over line setting prev/last as you go */
prev = last;
last = *p++;
}
if (beg == last && next == prev) /* test whether equal */
return 1;
return 0;
}
int main (int argc, char **argv) {
char line[MAXC] = "";
size_t n = 0;
std::ifstream f (argc > 1 ? argv[1] : "/dev/stdin");
if (!f.is_open()) {
std::cerr << "error: file open failed.\n";
return 1;
}
while (f.getline (line, MAXC, '\n')) {
if (begmatchend ((const char *)line))
std::cout << "line[" << std::setw(3) << n <<
"] 1st/ultimate matched, 2nd/penultimate matched.\n";
n++;
}
return 0;
}
Example Input
$ cat dat/linesbegend.txt
all good vikings go to valhalla
be a tide that will flow and eb
a quick brown fox jumps over the lazy dog
we can find the begin and end - eew
Example Use/Output
$ ./bin/beg_end_match dat/linesbegend.txt
line[ 0] 1st/ultimate matched, 2nd/penultimate matched.
line[ 1] 1st/ultimate matched, 2nd/penultimate matched.
line[ 3] 1st/ultimate matched, 2nd/penultimate matched.
Look things over and let me know if you have any questions.

Find count of character occurrences in array using recursion

I'm pretty new with recursion. I need to write two functions. So far I wrote one, which entitles finding the length of a string. However, the second one, which is: finding the repeating character in an array is proving to be very difficult. I have scoured the web trying to find examples, I have been doing a lot of reading but nothing so far. So if you could point me in the right direction, I would really appreciate it.
Thank you
//length( ) -- this function is sent a null terminated array of characters.
//The function returns the length of the "string".
long slength (const char ntca[])
{
int length = 0;
if (ntca[length] == '\0'){
return 0;
}
else{
return slength(ntca+1)+1;
}
}
//countall( ) -- This function is sent a null terminated array of characters
//and a single character. The function returns the number of times the character
//appears in the array.
long countall (const char ntca[],char letter){
int position = 0;
int counter = 0;
long length = slength(ntca);
if (length == 0)
return 0;
else if (ntca[position]==letter)
return 1 + countall(ntca-1,letter);
else
return countall(ntca,letter);
}
You can try the below code:
long countall(const char *ptr, char letter)
{
if(!*ptr) return 0; //base case
return (*ptr == letter) + countall(ptr + 1, letter);
}
The base case of recursion is when function meets the end of the string. For an empty string and any letter the answer is 0.
If string is not empty, we add 1 to the result of recursive call on shorter string if and only if the current char matches letter.

C++ recursion scanning with strings

I have an assignment I am working on that uses recursion. I'm still having a little trouble understanding recursion, or at least how it all works, but I think I'm starting to grasp it, even though I'm not all that sure why anything works.
My assignment has two parts, but for the moment, I just need a little help with the first part. Here's what I have to do:
Write a recursive function that will return the position of the first occurence of a >character within a C String
This is what I have so far...
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
int test(string s, char x);
int main ()
{
test("lets test for the letter s", "s" );
}
int test(string s, char x)
{
if(s.length() == 0)
return 0;
else if (s[0] == x)
return 1 + test(s.substr(1, s.length()), x);
else
return test(s.substr(1, s.length()), x);
}
So i think this should work, but I'm a little confused as to how to get the function to test anything. I'm pretty sure I have the string part done correctly in my function call in main, but I can't get the char to accept a value. The way I understand it, i should enter the text I want to scan, and then the character I want to look for. Can anyone tell me what I am doing wrong, or even I'm even close with the recursive function?
You should do something like the following:
int main ()
{
test("lets test for the letter s", 's');
//should pass char constant
//not string literal for second parameter
}
int test(string s, char x)
{
if(s.length() == 0)
return 0;
else if (s[0] == x)
return 1 + test(s.substr(1, s.length()-1), x);
//^^^second parameter of substring is length
else
return test(s.substr(1, s.length()), x);
}
Character constants go in single quotes. To test your function write something like:
cout << test("lets test for the letter s", 's') << endl;
As for your recursive function, you're close. The if statements have the right tests, you just need to adjust the return statements a bit.
if (s.length() == 0)
return -1;
If the string is empty the character isn't found. I suggest returning -1 rather than 0 because a return value of 0 suggests (to me) that the character was found at position 0. -1 is the traditional return code from functions like these when a character isn't found.
else if (s[0] == x)
return 0;
Do you see why this is return 0? You found the character x at index 0, so that's what you should return: 0!
else
return 1 + test(s.substr(1, s.length() - 1), x);
The last test is the only one that needs to be recursive. Here's where you put the 1 +. And you also need to reduce length() by 1.
"s" will be treated as a char array or a string. To represent a single char you should use 's'
int main ()
{
cout << "location = " << test("lets test for the letter s", 's' );
^^^^
}

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;
}