C++: Using Recursion Transform characters - c++

I am making a Program which will convert a string using recursion.
The method replaces all occurrences of upper case characters with "1" all occurrences of "o" with 2 and all occurrences of "r" with a.
Requirement: The Recursive function should take only one Parameter that is the input string and returns the converted string.
Below is my code:
#include<iostream>
#include<conio.h>
#include<string>
#include<string.h>
using namespace std;
int count=0;
string convert(string a)
{
int b=a.length();
if(b>=count)
{
if (isupper(a[b-(b-count)]))
{
a.replace(b-(b-count),1,"1");
convert(a);
}
else if (a[b-(b-count)]=='o')
{
a.replace(b-(b-count),1,"2");
convert(a);
}
else if(a[b-(b-count)]=='r')
{
a.replace(b-(b-count),1,"a");
convert(a);
}
}
else
return a;
}
void main()
{
string a;
a="ABCrroo";
int l=a.length();
cout<<convert(a);
getch();
}

You've defined convert() as returning a std::string but there are four places inside the function where you make a recursive call and do nothing with the return value. You have to do something if you want to pass the result of each recursive call back up the call stack.
I modified your code and changed the four bare convert(a); lines to return convert(a); and it outputs "212a212a212a" which I think is the desired result.
It also looks like you are using an index one past the end of the string. The condition if(b>=count) would allow your code to use an index outside the valid range of 0..length-1. Try changing it to just if(b>count).

#include<iostream>
#include<string>
#include<string.h>
string convert1(string a, int pos);
using namespace std;
int count=0;
string convert1(string a, int pos)
{
if(pos < a.length())
{
if(isupper(a[pos])) a.replace(pos, 1, "1");
else if(a[pos]=='o') a.replace(pos, 1, "2");
else if(a[pos]=='r') a.replace(pos, 1, "a");
convert1(a, ++pos);
}
else return a;
}
int main()
{
string a="oYoroCoroSor";
cout << a << endl;
int l=a.length();
cout<< convert1(a, 0) << endl;
return 0;
}

Related

Removing a specific element from a string in C++

I was trying to remove X from a given string, the code compiles and runs but there is no output shown. I guess the problem is where I have to use the 'cout' operator.
Here is my Code:
#include<iostream>
#include<bits/stdc++.h>
#include<string.h>
using namespace std;
void removeX(char str[])
{
if(str[0]='\0')
{
cout<<str;
}
if(str[0]!='x'||str[0]!='X')
{
removeX(str+1);
}
else
{
for(int i=0;i!='\0';i++)
{
str[i]=str[i+1];
}
removeX(str+1);
}
}
int main()
{
char a[]="MALCOLM X";
removeX(a);
return 0;
}
You have a few issues in your code, the ones I can spot right away are:
if(str[0]='\0') - this is an assignment, not a comparison. Your entire string will be replaced with \0-characters - no characters will be skipped because this:
if(str[0]!='x'||str[0]!='X') is always true. Ask yourself if x is different from x (false) OR X (true). False or true = true.
The check should be implemented something like (str[0] != 'x' && str[0] != 'X').
Edit: One more issue.
The overall logic will not work (-ish). The part where you run through the string and compress it is correct enough. But you try to run to the end and then print the string, however at that point you are only holding the end of the string (the null termination), so no matter what else you have done you will only print that (aka. print nothing).
Instead, once you are done compressing the xs out of the string, you need to return to the beginning of the string and then print that. The easy way is to print in main, or you can split your function into an outer+inner function like:
void outer_removeX(str) {
removeX(str);
print(str);
}
Or you could add an extra variable to the recursion that allows you to return to the first call in the chain and then print there.
However, only printing the end will not work.
try the following code:
#include<iostream>
#include<bits/stdc++.h>
#include<string.h>
using namespace std;
void removeX(char str[],int j)
{
if(str[j]=='\0')
{
cout<<str;
}
else if(str[j]!='x' && str[j]!='X')
{
removeX(str,++j);
}
else
{
for(int i=j;str[i]!='\0';i++)
{
str[i]=str[i+1];
}
removeX(str,j);
}
}
int main()
{
char a[]="MAxLCOLM X";
removeX(a,0);
return 0;
}

Print a char string if the number of characters is even, or the middle character is removed

I have to make a console program that will print:
If the string is even, all the characters - let's say I have rain, it will print rain.
If the string is odd, it will remove the middle character, and then print the remaining ones - let's say I have telephone, it will remove p, and print telehone.
I've searched the StackOverflow forum for 3 hours but I couldn't solve this. This is my try:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
char s[21], x[21];
int j;
int main()
{
cin.get(s, 21);
if(strlen(s) % 2 == 0)
strcpy(x, s);
cout << x;
return 0;
}
string removeMiddle(const string)
{
int str = strlen(s);
bool isOdd;
if(str % 2 != 0)
isOdd == true;
if(isOdd == true)
{
j = str / 2;
}
s.erase (j+1, 1);
cout << s;
}
I've tried a lot of snippets and this is the best I can do. Thanks guys!
In your code you never called the removeMiddle function and removeMiddle functions is not returning anything even though its return type is string.
Here's the right code:
#include<bits/stdc++.h>
using namespace std;
int main(){
string str;
cin>>str;
if(str.length()%2==0){
cout<<str;
}
else{
int r = str.length()/2;
str.erase(r,1); //string& string ::erase (idx,len);
//Erases at most, len characters starting from index idx;
cout<<str;
}
return 0;
}
We first checked if the length of the string is even, then print the string, else we used the erase function to remove the middle character.

Why the function is not returning the string?

#include<iostream>
#include<string.h>
using namespace std;
string revString(string s,string copy,int i,int j)
{
if(i==s.length())
return copy;//if 'i' reaches to the length of the string it returns the copied value
else{
copy[i]=s[j];//copying the string s into copy
return revString(s,copy,++i,--j);// calling recursively
}
}
int main()
{
string s,copy;
cout<<"Enter a string without entering spaces\n";
cin>>s;
int i=0,j=s.length()-1;
cout<<revString(s,copy,i,j);//function for reversing the string
return 0;
}
here i am trying to copy the string 's' into the string 'copy' by using recursion but the function isn't returning anything.
Because you have not allocated memory to your copy variable, but trying to assign values to it. I would suggest you to read more about memory allocation in C++ string class.
With minimum alterations to your code, you can make it work by adding the following snippet just before calling your revString() function:
copy.resize(s.size());
your approch was good but imagine you have 100 chars then it will iterate 100 times. instead what you can do reverse first half with second half of string and you don't even have to pass too many arguments.
this is my approch
#include<iostream>
#include<string.h>
using namespace std;
string revString(string s, int i = 0)
{
if((int)(s.length() / 2) == i)
return s;
else{
char t;
t = s[i];
s[i] = s[s.length() - 1 - i];
s[s.length() - 1 - i]=t;
return revString(s, ++i);// calling recursively
}
}
int main()
{
string s;
cout<<"Enter a string without entering spaces\n";
cin>>s;;
cout<<revString(s);//function for reversing the string
return 0;
}

Debug my reimplementation of strtok and split

I'm supposed to be writing code that takes a string of comma separated values without spaces (ex. my,name,is,jack). First we had to write a function
string nextstring(string str, int start_index)
that returns a single "value" from your initial string depending on the start index. The second part of the problem was to write a function
int split(string str, string a[], int max_size)
that will identify all the values in the initial string and put them in a string array and then return the total number of values stored in the array; i.e. if you had initially input my,name,is it would return 3.
My function never returns the correct value and whatever it returns changes depending on what the length of the words are.
#include <iostream>
#include <string>
using namespace std;
string nextstring(string str, int start_index);
int split(string str, string a[], int max_size);
int main()
{
string str;
int cnt;
string a[100];
cout<< "what is your string" << endl;
getline(cin, str);
cnt= split(str, a, 100);
cout << "There are " << cnt << " values in this string" << endl;
for(int i=0; i<cnt; i++)
{
cout << a[i] << endl;
}
return 0;
}
string nextstring(string str, int start_index)
{
string ans;
if(str[start_index] == ',' || str[start_index] == '\0')
{
ans=" ";
}
else{
ans=str[start_index]+nextstring(str, start_index+1);
}
return ans;
}
int split(string str, string a[], int max_size)
{
int j=0;
int ans=0;
double k=0;
while(j<max_size)
{
a[j]= nextstring(str,k);
string check=a[j];
if(isalpha(check[0])!= 0)
{
ans++;
}
k=k+a[j].length();
j++;
}
return ans;
}
It seems that your problem is that while(j<max_size){...} leads to j being incremented up to max_size. The line a[j]= nextstring(str,k); is at some points reading values that are outside your string which is really bad!
Replacing while(j<max_size){...} by while(j<max_size && k<str.length()){...} seems to be enough to make your code work!
Apart from that:
k has no reason to be a double! It should be an int (or something similar).
Since you are already using string, you should also learn to use vector. split is better written as:
int split(string str, vector<string> &a, int max_size)
{
int ans=0;
int k=0;
while(k<str.length())
{
string next = nextstring(str,k);
if(isalpha(next[0])!= 0)
{
ans++;
a.append(next);
}
k += next.length();
}
return ans;
}
The problem in your approach is to identify the end of the string, as there is no null terminator in a c++ string. Consider to update nextstring() to look for the end of string in a different manner:
string nextstring(string str, int start_index)
{
...
if(start_index == str.size() || str[start_index] == ',' ) //<===
{
ans=" ";
}
...
}
online demo
Additional recommendation
Note that it is not very nice to return a blank string when in reality it should be empty to reflect its real value (e.g. ",,"). You have no choice because otherwise you would have no mean in the calling function, to determine that the end of string was reached. But the consequence is thar all your strings have a trailing blank.
When you call recursively the function adding char to build the return string, you risk to have a considerable overhead. You could consider avoiding this, by replacing the else part:
ans=str.substr(start_index, str.find(',', start_index+1)-start_index);
However, as you have no trailing blank anymore, you need to adapt split() so to adapt its way to count the total number of chars parsed:
k=k+a[j].length()+1; // +1 because there's no longer a trailing blank.
Online demo

Finding sub-string in a string while both of them are user inputs

I have written this program to find sub-string in a string while both of them are user inputs.This is working fine albeit approach may seems amateur to quite a few here.My problem is that when I put the string "a" and "b" as the following:"I am kamlesh" and "am" respectively.
I am NOT GETTING any output while omitting "a[t4]==' '" in the last if statement giving me output 3 and 7.
Please suggest some ways to rectify and getting the output as 3 only.
Post edit:Working fine now.
/* #include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void substring(char *a,char *b);
int main()
{
char a[80],b[80];
gets(a);
gets(b);
substring(a,b);
return 0;
}
void substring(char *a,char *b)
{
int c,d;
c=strlen(a);
d=strlen(b);
for(int t=0;t<c;t++)
{
if(a[t] && a[t]==*b)
{
int t1,t2,t3,t4;
t2=1;
t1=d-1;
t3=t+1;
while(t1 && a[t3]==b[t2] )
{
t1--;
t3++;
t2++;
t4=t2;
}
if(!t1 && a[t4]==' ') //to avoid showing "am" in kamlesh.
cout<<t+1<<endl;
}
}
} */
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void substring(char *a,char *b);
int main()
{
char a[80],b[80];
int s;
gets(a);
gets(b);
substring(a,b);
return 0;
}
void substring(char *a,char *b)
{
char *s1,*s2;
for(int t=0;a[t];t++)
{
s1=&a[t];
s2=b;
while(*s2 && *s2==*s1)
{
s1++;
s2++;
}
if(*s2 && *s1==' ')
cout<<t;
}
}
As donjuedo said, this code is very unreadable. Things that I see quickly is that a[t4] is problematic because there is no guarantee that t4 is going to be initialized before that; you don't need to walk backwards from the end of your substring (t1); and you don't need to use indexing with integers to walk around in the strings, you can move pointers around.
The code should be something as simple as:
char* p1 = (char*)str; // the string to be searched
int substrIndex = 0;
while (*p1) {
char* p1Begin = p1; // keep the pos of start of search
char* p2 = (char*)target; // pointer for the substring
while (*p1 && *p2 && *p1 == *p2) { // as long as within the boundaries, chars equal
p1++;
p2++;
}
if (!*p2) // if all chars equal, passed end of target - success
cout << substrIndex << endl;
p1 = p1Begin + 1;
substrIndex++;
}
I didn't compile, so not 100% sure it will run bug free; but you get the idea.