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()));
}
Related
I am trying to convert a string that is only 1s and 0s to a decimal value. The variable value is initialized to 0 and is never updated. I suspect the problem is that binaryString[i] is treated as a string and therefore the athematic function doesn't work. How can I fix this?
void binaryToDec(string binaryString, int value)
{
int binaryStringLength = binaryString.length();
for (int i = 0; i < binaryStringLength; i++)
{
value += pow(2,i)+ binaryString[i];
}
}
I tried to use basic type casting like int(binaryString[i]) but that doesn't work.
Firstly binaryString[i] is a character, not an integer. To convert a digit character to an integer you can just subtract '0'.
binaryString[i] - '0'
Secondly pow(2,i) returns a floating point number, when you want an integer. This is inefficient, and even more seriously might be subject to rounding errors. Instead you should use a shift operator, which efficiently and accurately calculates integer powers of two.
1 << i
Thirdly you have + where you need *. The two terms should be multiplied not added.
Putting all that together you get
value += (1 << i) * (binaryString[i] - '0');
But the most serious error of all is that your function does not return a value. It should look like this
int binaryToDec(string binaryString)
{
int value = 0;
...
return value;
}
Your version passes value as a parameter, that's the wrong way round, binaryString is a parameter, but value should be returned from the function. Not sure why but this is a difference a lot of newbies struggle with.
You could construct a bitset from the string and then back to a ullong.
But, limiting the solution to a maximum binary string size.
[Demo]
#include <bitset>
#include <fmt/core.h>
#include <stdexcept> // out_of_range
auto binaryToDec(const std::string& binary) {
if (binary.size() > 64) {
throw std::out_of_range{ "binary string is too big" };
}
return std::bitset<64>{binary}.to_ullong();
}
int main() {
try {
std::string binary_1{"101010"};
fmt::print("binary: {}, decimal: {}\n", binary_1, binaryToDec(binary_1));
std::string binary_2{
"1111""1111""1111""1111"
"1111""1111""1111""1111"
"1111""1111""1111""1111"
"1111""1111""1111""1111"
"1"
};
fmt::print("{}\n", binaryToDec(binary_2));
} catch (const std::exception& e) {
fmt::print("Error: {}.\n", e.what());
}
}
// Outputs:
//
// binary: 101010, decimal: 42
// Error: binary string is too big.
I've been given a programming task that involves taking away certain letters in a string. I was trying out different ways to do this when I found the public member function string find. To put it short I was testing out the function via this program :
#include <iostream>
#include <string>
using namespace std;
int main()
{
string Word = "Applejuice";
cout<<Word.find("e")<<endl;
return 0;
}
So when I put in a letter such as "e" I get the number 4 which confuses me because I thought the function will count all the letters in that specific word such as apple juice. Also, when I use a letter that is not used in that word I get numbers like 18446744073709551615 for example when I put in X for e in the code above.
Could someone explain why this is happening, please?
string.find() will return the position of the first character of the first match.
If no matches were found, the function returns string::npos.
Therefore the number (18446744073709551615) you are getting is the string::npos
If you want to search for an only a single character in the string you can use the following code
#include <iostream>
#include <string>
using namespace std;
// Function that return count of the given
// character in the string
int count(string s, char c)
{
// Count variable
int res = 0;
for (int i=0;i<s.length();i++)
// checking character in string
if (s[i] == c)
res++;
return res;
}
// Driver code
int main()
{
string str= "Applejuice";
char c = 'e';
cout << count(str, c) << endl;
return 0;
}
If you want to avoid some random large values as output i.e. string::npos you can just add check for it like following:
if(Word.find("e") != string::npos)
{
...
}
Method find from class string return the position of the first character of the first match. Return type of find is size_t and since size_t is unsigned integral so if no match were found return string::nopos so you should compare the outputof find with string::nopos.
if(Word.find("e") != string::nopos)
{
...
}
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
I have a simple code wherein i am finding simple interest and compound interest. The issue I am facing is that I have to use CLI for input.
I need one int and two floats to work with. Earlier i was using cin.fail() which was doing the type checking for me and that worked perfectly but i need to take CLI such that inputs such as 1000 1? 5 are treated as invalid. Please help.
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
int p;
float r,t,ci;
p=atoi(argv[1]);
r=atof(argv[2]);
t=atof(argv[3]);
if(p<=0 || r==0 || t<=0) {
//we want p>0 t>0 and r==0 from the logic that atof will retrun 0 if r is non numeric
cout<<"Invalid Input"<<endl;
}
else {
float si=(p*r*t)/100;
cout<<"Simple interest:"<<fixed<<setprecision(2)<<si<<endl;
ci=p*pow((1+r/100),t)-p;
cout<<"Compound interest:"<<ci<<endl;
}
return 0;
}
Try adding this function to your code:
#include <ctype.h>
static bool isnumeric(char* theArgument, int maxdec)
{
int decimalpoint = 0;
while(*theArgument)
{
if (!isdigit(*theArgument))
{
if ('.' == *theArgument && maxdec <= ++decimalpoint)
{
continue;
}
return false;
}
}
return true;
}
Call it for each of your arguments, with the maximum number of decimal points the argument can allow. In your case, that would be isnumeric(argv[1],0), isnumeric(argv[2],1), isnumeric(argv[3],1). That will tell you if your numbers are in fact formatted as nonnegative decimal numbers. A little more logic (not shown here) will also tell you if they have a minus sign.
argv is character array, so it contains more characters.
Solution should be:
Explode your argv into 3 parts, separator should be space (or multiple) symbol.
Now cast it using strtol and strtod.
Validate. strtol and strtod returns zero if no success, so in case you got zero, check if input was actualy '0'.
You can use strtol and strtod instead of atoi and atof:
long int p;
double r,t;
char* endptr1;
char* endptr2;
char* endptr3;
p = strtol(argv[1], &endptr1, 10);
r = strtod(argv[2], &endptr2);
t = strtod(argv[3], &endptr3);
if (*endptr1 != 0 || *endptr2 != 0 || *endptr3 != 0)
{
cout<<"Invalid Input"<<endl;
}
else
{
...
}
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' );
^^^^
}