Simple recursive C++ code keeps crashing - c++

So I'm teaching myself C++ and I'm struggling to understand why this code keeps crashing. I've identified that this line: string str = to_string(n) is probably incorrect. But I'm not seeing the other errors for why it's crashing.
#include <iostream>
#include <string>
using namespace std;
void write_vertically(int n)
{
string str = to_string(n);
if (str.length()>=0)
{
cout<<stoi(str.substr(0,1))<<endl;
write_vertically(stoi(str.substr(1,str.length())));
}
}
int main( )
{
write_vertically(1234567890);
return 0;
}

You are having a Stack Overflow! And you're on the perfect website to find a solution to that.
In the line string str = to_string(n);
No matter the value of n, to_string is going to return a non-empty string, which could be "0", "6" or "1653", whatever.
The end condition for your recursion is if (str.length() >= 0) is false.
However, as stated above that is never false.
What did you intend the end condition of your recursion to be? Maybe we can help you with that.
Edit: It turns out that the code should crash before going into a stack overflow, because it would end up calling stoi with an empty string, which makes it throw an std::invalid_argument. However, there was still an infinite recursion problem, so I will keep my answer up.

You are calling stoi("") at the end
#include <iostream>
#include <string>
using namespace std;
void write_vertically(int n){
string str = to_string(n);
cout<<stoi(str.substr(0,1))<<endl;
if (str.length()>1)
write_vertically(stoi(str.substr(1,str.length())));
}
int main( ) {
write_vertically(1234567890);
return 0;
}
https://ideone.com/YfYhZw

You are doing a lot of (unnecessary) type conversion. Here's a way to accomplish your goal without using strings.
#include <iostream>
using namespace std;
void write_vertically( unsigned int n ) {
unsigned int d = n % 10;
n /= 10;
if( n )
write_vertically( n );
cout << d << endl;
}
int main() {
write_vertically(1234567890);
return 0;
}

You have to change your recursion condition as follows:
if (str.length()> 0) {
cout<<stoi(str.substr(0,1))<<endl;
if(str.length() > 1)
write_vertically(stoi(str.substr(1,str.length())));
}
}
Demo: http://coliru.stacked-crooked.com/a/ecd26e57c45cea2b

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

Questions regarding C++ string

phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isdigit), phrase.end());
In the above code, why do I have to use :: even though I used using namespace std?
#include "Palindrome.h"
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
Palindrome::Palindrome (string Phrase){
phrase=Phrase;
}
void Palindrome::removeNonLetters()
{
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isdigit), phrase.end());
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::ispunct), phrase.end());
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isspace), phrase.end());
}
void Palindrome::lowerCase()
{
for (int i=0; i<phrase.length(); i++)
{
phrase[i] = tolower(phrase[i]);
}
}
bool Palindrome::isPalindrome()
{
int length=phrase.length();
int a=0;
for (int i=0;i<length/2;i++)
{
if(phrase[i] != phrase[length-a-1])
{
return false;
break;
}
a++;
}
return true;
}
The above code is to check if the string is a Palindrome. I don't understand why I need to use the first part which is
Palindrome::Palindrome (string Phrase){
phrase=Phrase;
}
I will always get "yes" if I deleted the above part.
The test code in main is
if(test.Palindrome::isPalindrome() == 1){
cout<<"Yes"<<endl;
}
else {
cout<<"No"<<endl;
}
One more question. I try to change the lowercase of above code, I got error. Do anyone know what happen with it? The new code was from https://www.geeksforgeeks.org/conversion-whole-string-uppercase-lowercase-using-stl-c/
Before
void Palindrome::lowerCase()
{
for (int i=0; i<phrase.length(); i++)
{
phrase[i] = tolower(phrase[i]);
}
}
After
void Palindrome::lowerCase(){
transform(phrase.begin(), phrase.end(), phrase.begin, ::tolower);
}
Can anyone explain it to me? Many thanks!
There are multiple isdigit, ispunct, and isspace functions - ones in the global namespace in the <ctype.h> header, and several in the std namespace in the <cctype> and <clocale> headers. Prefixing them with :: says you want to use the ones from the global namespace.
You need to use <string> instead of <string.h> in order to use the std::string class.
Assuming test is a Palindrome object, then test.Palindrome::isPalindrome() should be just test.isPalindrome().
If you omit the Palindrome constructor, then the phrase member remains blank, and your isPalindrome() implementation returns true for a blank phrase (length is 0) because there is nothing for the for loop to check. Which is technically correct - a blank string is a palindrome.
The :: indicates that you're using isdigit and the others from the global namespace. The isdigit is a part of other header files, such as <ctype.h>.

Section Numbers with Recursion

I'm having trouble with an assignment, and probably one that's very familiar (link). It's problem 2 titled "section numbers".
Basically, it's a recursion problem that prints out a string along with a section number, defined by levels. If there's one level, it prints string1. to string9.
If there's two, string1.1. to string9.9., etc. The problem I'm having is the last detail, where the program prints out the original string by itself.
My code:
#include <iostream> // Provides cin, cout
#include <cstdlib> // Provides EXIT_SUCCESS
#include <sstream>
#include <string>
using namespace std;
void numbers(ostream& outs, const string& prefix, unsigned int levels);
int main()
{
numbers(cout, "THERBLIG", 2);
}
void numbers(ostream& outs, const string& prefix, unsigned int levels)
{
if(levels == 0)
{
cout << prefix << endl;
}
else
{
for(int i = 1; i <= 9; i++)
{
string s = (prefix + char('0' + i));
s += '.';
numbers(outs, s, levels - 1);
}
}
}
I understand that prefix is being overwritten through the recursion, so instead of the original string being printed it's string1.1. What I don't know is how to keep the original intact so that it can be printed at the end.
(I know there's already a post here with the exact same question, but I've already tried both solutions and I wasn't able to get anywhere.)
Any help is very appreciated!
Hint: use static local variables, or append using recursion.
If you're ever stuck with recursion, try use recursion for calculating factorials ( the classic example ). Most uses derrive from this.
Also, please don't post your homework here.

strncat function c++ not working

I need to write void strncat which appends the first num characters of source to destination, plus a terminating null-character. If the length of the C string in source is less than num, only the content up to the terminating null-character is copied. What am i doing wrong?
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int MAXDESTINATION = 40;
const int MAXSOURCE = 150;
int main() {
char dest[MAXDESTINATION + 1] = "It don't mean a thing";
char src[MAXSOURCE + 1] = " if it don't got the Go-Go swing!";
int a = strlen(dest);
int b = strlen(src);
strncat(dest, src, MAXDESTINATION - a) ;}
void strncat(char destination[], const char source[], int num) {
if (int strlen(source) < num) {
int begin = 0;
bool less = false;
for (int i = 0; i <num; i++) {
if (destination[i] == '\0') {
begin = i;
less = true;
}
if (less == true) {
destination[begin] = source[i];
}
}
}
I'm guessing (since you haven't provided even the full definition of strncat) your problem is that you're not incrementing begin. The way it's written right now, the same spot is overwritten each time with the value at source[i]
You maybe want to say
destination[begin++] = source[i];
or maybe you should just use i instead, as begin should probably track i exactly, as it's initialized to i and then should be incremented once every time i is.
Also, from an efficiency standpoint, you're iterating over source multiple times. Once with your call to strlen (which has to go through each letter in the string to count them) and then again in your for loop. You should look to remove the strlen.
Compile errors:
error C1075 :end of file found before the left brace '{' ...
error c4996: 'strncat': this function or variable may be unsafe. consider using strncat_s instead.

Recursive Function practice

I am studying for an upcoming exam and one of the questions on the study guide is:
Write a recursive C++ function for converting a string of digits into the integer it represents. For
example, “13531” represents the integer 13531. Your function should return the integer value.
I am able to convert the string to an integer but am having trouble on what the base case should be for the function to be recursive. Any suggestions or help would be much appreciated.
The base case is an empty string.
Each step of your recursion converts one character in the string to an integer. And the recursive step passes in the remainder of the string.
As yourself how you might "work your way" through the starting string?
My gut feel tells me from "1357" I would would start with "7", leaving "135", then "5", leaving "13", and so on. And what are you eventually left with? An empty string!
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
int convert(string x)
{
int c=x[0]-'0';//to get the numeric value of the first char in string
if(x.size()==1)//base case
return c;
//in each time return the char with "x.size()-1" digits of zero and the first digit is for the number
return c*pow(10,x.size()-1)+convert(x.substr(1));
}
int main(){
string x;
getline(cin,x);
cout<<convert(x);
}
"12345" will be returned as no=10000+2000+300+40+5
Not sure whether you mean 'edge case' by 'base case'.
The edge case should be one that doesn't need any recursion any more and thus can be worked out directly. Thus it can be when the 'string' has only one digit (return str[0]-'0';) or has zero digit (return 0;) I think. The zero digit case might be a little more general.
Just a little more about the 'base' of the number if it could be other than base-10 number.
You might have to test the base of the number first. For c++11,
decimal-literal (base 10), octal-literal (base 8) and hex-literal
(base 16) are supported, e.g. -0x123, -0123, -123. You can do
the test according to cpp_integer_literal.
What about without any usage of pow, like:
#include <iostream>
#include <string>
int str_to_int(const std::string& str)
{
if (str.size() == 0)
return 0; // base case, end recursion
else
return (str[str.size() - 1] - '0') +
10 * str_to_int(str.substr(0, str.size() - 1));
}
int main()
{
std::cout << str_to_int("1234");
}
tailed recursion edition
#include<iostream>
#include<string>
void str2int(const std::string& s, int &result, int n = 0)
{
if (n == s.size())
{
return;
}
result *= 10;
result += s[n] - '0';
return str2int(s, result, n + 1);
}
int main()
{
int n = 0;
str2int("1234", n);
std::cout << n;
}
Using iterators seems to be more elegant and has the advantage that the conversion function can be applied on sub-strings.
#include <string>
#include <stdio.h>
using namespace std;
int str2int(string::const_iterator s, string::const_iterator e)
{
if(s==e) return 0;
--e;
return str2int(s,e)*10+*e-'0';
}
int main()
{
string s="12345";
printf("%d\n",str2int(s.begin(),s.end()));
}