My problem is that I need to do a recursion for a string and change any e for an a. Every time I enter a word it only prints out the last letter.
My code so far:
string ReplaceEsWithAs(string s)
{
if (s.length() == 1)
{
if (s == "e")
{
s = "a";
return s;
}
else
{
return s;
}
}
else
{
return ReplaceEsWithAs(s.substr(1));
}
}
The only return statements in the function are under the condition
if (s.length() == 1)
It makes sense that the function return always returns a string with one character in it.
In the recursive part, you use:
return ReplaceEsWithAs(s.substr(1));
which calls the function with all but the first character of the string.
If you call with "abcd" from main, you call with "bcd" in the recursive call, then you call with "cd", then you call with "d", which returns "d", which is returned all the way.
You are just discarding the first character in every recursive call.
You need to use:
string ReplaceEsWithAs(string s)
{
if (s.length() == 1)
{
if (s == "e")
{
return "a";
}
// No need for an else
return s;
}
// No need for an else.
return ReplaceEsWithAs(s.substr(0,1)) + ReplaceEsWithAs(s.substr(1));
}
Here is an implementation just by looping through and mutating the string:
string ReplaceEsWithAs(string s) {
for (size_t i = 0; i < s.length(); i++) {
if (s[i] == 'e') {
s[i] = 'a';
}
}
return s;
}
You can access the individual chars in a string by index using []. This code uses a standard for loop to loop through each character. (size_t is an unsigned integer type that is generally used for indices.) For each char s[i], it checks if it's 'e', and if so, sets it to 'a'. Then it just returns the changed string.
This is better than a recursive approach because
it's easier to understand at a glance
it modifies the string in-place, meaning it doesn't have to do needless substring and concatenating (+)
it uses less memory
it won't cause the call stack to overflow for a long input string
Also, the standard library provides a function to do replace operations like this. See this answer.
Related
I found this question on Hackerrank where I have to write a method to say whether or not a given string is a pangram. A sentence is a pangram if it contains all 26 letters of the alphabet. The input will only contain characters that are alphabetical (uppercase or lowercase) and spaces.
Here's the code I've gotten so far, where I use a set to keep track of which letters are present in the string. However, the code just keeps running infinitely in the while loop below.
string pangrams(string s) {
set<char> set{};
int i=0;
while (i!=s.length()) {
if(s[i]!='\0') {
set.insert(tolower(s[i]));
}
}
if (set.size() == 27) {
return "pangram";
} else {
return "not pangram";
}
}
Your function needs a slight modification. Firstly, you aren't incrementing i which makes your function go into infinite loop. Other modification is explained in code below -
string pangrams(string s) {
set<char> set{};
int i=0;
while (i!=s.length()) {
if(s[i]!=' ') { # if character is space, ignore it
set.insert(tolower(s[i]));
}
i++; # Main reason of runtime error - you missed incrementing i
}
if (set.size() == 26) { # 26 and not 27. There may be strings without space that are pangrams. So we wont add space into our set.
return "pangram";
} else {
return "not pangram";
}
}
Also, you don't need to check s[i]!='\0' since a c++ string isn't terminated with \0 character. Only checking i!=s.length() will be enough.
Hope this clears your issue !
You're never incrementing i, so your code will run infinitely. I would recommend a for loop for (int i = 0; i < s.length(); i ++) or a for-each loop for (char c : s)
Instead of using a set, you could also try this, where each character corresponds to an index in a bool[]
bool exists[27];
for (char c : s) {
if ('a' <= c && c <= 'z') {
exists[c - 'a'] = true;
} else if ('A' <= c && c <= 'A') {
exists[c - 'A'] = true;
} else if (c == ' ') {
exists[26] = true;
}
}
for (bool b : exists) {
if (!b) return false;
}
return true;
I'm programming a hash table thing in C++, but this specific piece of code will not run properly. It should return a string of alpha characters and ' and -, but I get cases like "t" instead of "art" when I try to input "'aRT-*".
isWordChar() return a bool value depending on whether the input is a valid word character or not using isAlpha()
// Words cannot contain any digits, or special characters EXCEPT for
// hyphens (-) and apostrophes (') that occur in the middle of a
// valid word (the first and last characters of a word must be an alpha
// character). All upper case characters in the word should be convertd
// to lower case.
// For example, "can't" and "good-hearted" are considered valid words.
// "12mOnkEYs-$" will be converted to "monkeys".
// "Pa55ive" will be stripped "paive".
std::string WordCount::makeValidWord(std::string word) {
if (word.size() == 0) {
return word;
}
string r = "";
string in = "";
size_t incr = 0;
size_t decr = word.size() - 1;
while (incr < word.size() && !isWordChar(word.at(incr))) {
incr++;
}
while (0 < decr && !isWordChar(word.at(decr))) {
decr--;
}
if (incr > decr) {
return r;
}
while (incr <= decr) {
if (isWordChar(word.at(incr)) || word.at(incr) == '-' || word.at(incr) == '\'') {
in =+ word.at(incr);
}
incr++;
}
for (size_t i = 0; i < in.size(); i++) {
r += tolower(in.at(i));
}
return r;
}
Assuming you can use standard algorithms its better to rewrite your function using them. This achieves 2 goals:
code is more readable, since using algorithms shows intent along with code itself
there is less chance to make error
So it should be something like this:
std::string WordCount::makeValidWord(std::string word) {
auto first = std::find_if(word.cbegin(), word.cend(), isWordChar);
auto last = std::find_if(word.crbegin(), word.crend(), isWordChar);
std::string i;
std::copy_if(first, std::next(last), std::back_inserter(i), [](char c) {
return isWordChar(c) || c == '-' || c == '\'';
});
std::string r;
std::transform(i.cbegin(), i.cend(), std::back_inserter(r), std::tolower);
return r;
}
I am going to echo #Someprogrammerdude and say: Learn to use a debugger!
I pasted your code into Visual Studio (changed isWordChar() to isalpha()), and stepped it through with the debugger. Then it was pretty trivial to notice this happening:
First loop of while (incr <= decr) {:
Second loop:
Ooh, look at that; the variable in does not update correctly - instead of collecting a string of the correct characters it only holds the last one. How can that be?
in =+ word.at(incr); Hey, that is not right, that operator should be +=.
Many errors are that easy and effortless to find and correct if you use a debugger. Pick one up today. :)
I've got a homework assignment that requires me to use a recursive function to count the number of a's in a user given string. I don't want the answer given to me, but if someone could give me a little guidance that would be great. It correctly calls itself, but I can't figure out how to correctly count the number of a's. Here is my code.
int charCounter(string str, int counter)
{
if (str == "")
{
return counter;
}
else if (str.substr(1) == "a");
{
counter++;
return counter + charCounter(str.substr(1),counter);
}
}
First you need to know that a string is an array of chars. E.g. "hey" => ['h','e', 'u'].
When you deal with recursive functions the first thing you need is your stop condition which you stated as str == "" or when str is empty.
For each time you call you recursive function you want to check if the string is empty then return the counter, otherwise you increment counter, remove one char from your string then you call recursively your function passing along the new str and the current counter.
Make sure when you call you recursive function set counter = 0
Pseudocode
recursiveStrCounter(str, counter) {
if empty str {
return counter
}
counter++
remove one char from str
return recursiveStrCounter(str, counter)
}
print recursiveStrCounter(str, 0)
Hope it helped.
changing the function slightly will help
int countstring(string s) {
int counter = 0;
if (s.length() == 0)
return counter;
else {
if (s[0]== 'a')
counter++;
string newstring = s.substr(1);
return counter + countstring(newstring);
}
}
I am trying to solve this recursively. I am having a hard time returning the string:
string reverse(string);
int main() {
cout << reverse("1234") << endl;
} // end main
string reverse(string integer) {
if (integer == "")
return "";
else
return reverse(integer.substr(1, integer.length()));
} // end reverse
I know the function has small issue (I hope). Can you please help me fix it? Thanks,
Try this one
string reverse(string integer) {
if (integer.length() == 0)
return "";
else
return reverse(integer.substr(1, integer.length())) + integer.substr(0,1);
} // end reverse
See live demo.
Your problem is that you keep recursing on shorter strings until you reach the empty string.
Since you never do anything with the result of the recursive call, you also end up with the empty string.
If you want the first character of the string to wind up in the result, you need to use it somewhere, you can't just throw it away.
You should put the first character at the back of the result of reversing the rest of the string, like this:
string reverse(string s)
{
if (s == "")
return "";
else
return reverse(s.substr(1, s.length())) + s[0];
}
or, shorter
string reverse(string s)
{
return s.empty() ? "" : reverse(s.substr(1)) + s[0];
}
I wrote the below in arduino code language (c or c++ ?)
And i got puzled, i'm not sure if this is a limitation from C or C++.
My function should split a text string and return word number x
In my function i need to clean a string variable, that resets its contend until X is reached
For readability X is called wordcount.
How do i clean the string Wordsample make it empty again ?
On a side note, if the word isnt found then this function should also return nothing
As the results are used to make other strings from.
String GetSubString (String A,int Wordcount) //for readability start counting B from 1
{ int CounterX;
String WordSampleN;
String result ;
for (int i = 0; i < A.length(); i++)
{ // split string
WordSampleN = WordSampleN + A[i];
if ((A[i] == ' ') || (A[i] =='\n'))
{ CounterX++;
if (CounterX == Wordcount)
{ result = WordSampleN;
}
if (CounterX <> WordCount)
{ WordSampleN = ''; // <== ERROR IS HERE
}
}
}
return result;}
On a side note, if possible I would like to keep use strings of any size, not fixed strings.
There is no concept of an 'empty character'. You cannot initialize your String (object) this way. Instead, use an empty (small-"s") string "";
WordSampleN = "";
This will call the String constructor that takes a c-style string, and initialize your String object with the empty string.