Recursive function to calculate successor of a numeric string - c

I want to write a recursive function which calculates Succ(‘2468’) = '2469'. ‘2468’ is a numeric string.
The exercice give me some predefined function such as last(ch), which returns the last caracter of a string, start(ch), returns ch without the last caracter, addEnd(ch, c), adds c at the end of ch and ask me to return a string as final result (i.e., suc("123")="124")
I tried this code but it works only for a string with 2 characters. If the length of my string is > 2, it doesn't work:
int successor (char*ch)
{
if (strlen (ch)==1)
return (int(*ch))+1);
else
return ((int(*ch))*10+successor(ch+1));}

There seems to be no need for multiplication or use of powers. Given the extra predefined functions you indicated were provided, I think the intention here was for a recursive way to express long addition with carry. I don't know C but here's an illustration in JavaScript that has very close syntax. I hope this helps.
function successor(s){
if (s.length == 1){
if (s == '9'){
return '10';
} else {
// Return the successor character,
// not sure how this looks in C.
return String.fromCharCode(
s.charCodeAt(0) + 1);
}
}
let rightmost = successor(last(s));
// No carry so just return
// the string with the last
// character incremented
if (rightmost != '10'){
return addEnd(start(s), rightmost);
// We have a carry so
// continue the recursion
} else {
return addEnd(successor(start(s)), '0');
}
}
function last(s){
return s.substr(-1);
}
function start(s){
return s.substr(0, s.length - 1);
}
function addEnd(s, c){
return s + c;
}
console.log(successor('2999'));

A key problem is this logic:
(int(*ch))*10+successor(ch+1)
the multiplication by 10 is insufficient for larger numbers. We need to multiply by a power of 10 and we already calculated that power but didn't hang onto it:
strlen (ch)
or more specifically:
strlen(ch) - 1
A complete solution:
#include <math.h>
#include <stdio.h>
#include <string.h>
#define digit(c) (c - '0')
int successor(char *string)
{
size_t power = strlen(string) - 1;
if (power == 0)
{
return digit(*string) + 1;
}
return digit(*string) * pow(10, power) + successor(string + 1);
}
int main() {
printf("%d\n", successor("2999"));
return 0;
}
OUTPUT
> ./a.out
3000
>
TODO
What happens if successor() is passed an empty string:
printf("%d\n", successor(""));
How can you modify the code to fix this? First decide what the function should return in this situation. What happens if successor() is passed a string that represents a number too large to be contained in an int:
printf("%d\n", successor("8589934592"));
How can you modify the code to fix this? Again, first decide what the function should return in this situation.

Related

Program printing wrong output

Why is the following code printing !notreblo! instead of !notrebloH? Where is the ! coming from? I am trying to write a program that reverses an array and I am using the main function to test the rev_string function.
#include <stdio.h>
int main(void)
{
char s[11] = "Holberton!";
printf("%s\n", s);
rev_string(s);
printf("%s\n", s);
return (0);
}
void rev_string(char *s)
{
char new[500];
int count, newcount;
count = 0, newcount = 0;
while (*(s + count) != '\0')
{
*(new + count) = *(s + count);
count++;
}
count--;
while (count > 0)
{
*(s + newcount) = *(new + count);
count--;
newcount++;
}
}
The second while does not copy the first character, because the last character copied is at index 1. The condition tells it so: count > 0.
Change it to count >= 0.
(+1 for the famous "one-off" error. If I got 1 cent each time, I'll be a rich person.)
Notice your second while condition: while (count > 0). You aren't including your last character - e.g. if count == 3 (3 characters to reverse), you will only iterate twice - and your third character will not be written. You need to change the condition to while (count >= 0).
As a bonus, the function you are implementing is better known as strrev - and it can be implemented without an additional buffer.
Because you should change your second while condition to while (count >= 0)

Recursive function to convert string to integer in C

I have the following working code; it accepts a string input as the function parameter and spits out the same string converted to a decimal.
I'm not going to bother accounting for negative inputs, although I understand that I can set a boolean flag to true when the first indexed character is a "-". If the flag switches to true, take the total output and multiply by -1.
Anyway, I'm pretty stuck on where to go from here; I'd like to adjust my code so that I can account for a decimal place. Multiplying by 10 and adding the next digit (after converting that digit from an ASCII value) yields an integer that is displayed in decimal in the output. This obviously won't work for numbers that are smaller than 1. I understand why (but not really how) to identify where the decimal point is and say that "for anything AFTER this string index containing a decimal point, do this differently"). Also, I know that instead of multiplying by a power of 10 and adding the next number, I have to multiply by a factor of -10, but I'm not sure how this fits into my existing code...
#include <stdio.h>
#include <string.h>
int num = 0;
int finalValue(char *string1) {
int i = 0;
if (string1[i] != '\0') {
if (string1[i]<'0' || string1[i]>'9') {
printf("Sorry, we can't convert this to an integer\n\n");
}
else {
num *= 10;
num += string1[i] - '0';
//don't bother using a 'for' loop because recursion is already sort-of a for loop
finalValue(&string1[i+1]);
}
}
return num;
}
int main(int argc, const char * argv[]) {
printf("string to integer conversion yields %i\n",(finalValue("99256")));
return 0;
}
I made some adjustments to the above code and it works, but it's a little ugly when it comes to the decimal part. For some reason, the actual integer output is always higher than the string put in...the math is wrong somewhere. I accounted for that by subtracting a static amount (and manually multiplying by another negative power of 10) from the final return value...I'd like to avoid doing that, so can anybody see where my math / control flow is going wrong?
#include <stdio.h>
#include <string.h>
//here we are setting up a boolean flag and two variables
#define TRUE 1
#define FALSE 0
double num = 0;
double dec = 0.0;
int flag = 0;
double final = 0.0;
double pow(double x, double y);
//we declare our function that will output a DOUBLE
double finalValue(char *string1) {
//we have a variable final that we will return, which is just a combination of the >1 and <1 parts of the float.
//i and j are counters
int i = 0;
int j = 0;
//this will go through the string until it comes across the null value at the very end of the string, which is always present in C.
if (string1[i] != '\0') {
//as long as the current value of i isn't 'null', this code will run. It tests to see if a flag is true. If it isn't true, skip this and keep going. Once the flag is set to TRUE in the else statement below, this code will continue to run so that we can properly convert the decimal characers to floats.
if (flag == TRUE) {
dec += ((string1[i] - '0') * pow(10,-j));
j++;
finalValue(&string1[i+1]);
}
//this will be the first code to execute. It converts the characters to the left of the decimal (greater than 1) to an integer. Then it adds it to the 'num' global variable.
else {
num *= 10;
num += string1[i] - '0';
// This else statement will continue to run until it comes across a decimal point. The code below has been written to detect the decimal point and change the boolean flag to TRUE when it finds it. This is so that we can isolate the right part of the decimal and treat it differently (mathematically speaking). The ASCII value of a '.' is 46.
//Once the flag has been set to true, this else statement will no longer execute. The control flow will return to the top of the function, and the if statement saying "if the flag is TRUE, execute this' will be the only code to run.
if (string1[i+1] == '.'){
flag = TRUE;
}
//while this code block is running (before the flag is set to true) use recursion to keep converting characters into integers
finalValue(&string1[i+1]);
}
}
else {
final = num + dec;
return final;
}
return final;
}
int main(int argc, const char * argv[]) {
printf("string to integer conversion yields %.2f\n",(finalValue("234.89")));
return 0;
}
I see that you have implemented it correctly using global variables. This works, but here is an idea on how to avoid global variables.
A pretty standard practice is adding parameters to your recursive function:
double finalValue_recursive(char *string, int flag1, int data2)
{
...
}
Then you wrap your recursive function with additional parameters into another function:
double finalValue(char *string)
{
return finalValue_recursive(string, 0, 0);
}
Using this template for code, you can implement it this way (it appears that only one additional parameter is needed):
double finalValue_recursive(char *s, int pow10)
{
if (*s == '\0') // end of line
{
return 0;
}
else if (*s == '-') // leading minus sign; I assume pow10 is 0 here
{
return -finalValue_recursive(s + 1, 0);
}
else if (*s == '.')
{
return finalValue_recursive(s + 1, -1);
}
else if (pow10 == 0) // decoding the integer part
{
int digit = *s - '0';
return finalValue_recursive(s + 1, 0) * 10 + digit;
}
else // decoding the fractional part
{
int digit = *s - '0';
return finalValue_recursive(s + 1, pow10 - 1) + digit * pow(10.0, pow10);
}
}
double finalValue(char *string)
{
return finalValue_recursive(string, 0);
}
Also keep track of the occurrence of the decimal point.
int num = 0;
const char *dp = NULL;
int dp_offset = 0;
int finalValue(const char *string1) {
int i = 0;
if (string1[i] != '\0') {
if (string1[i]<'0' || string1[i]>'9') {
if (dp == NULL && string1[i] == '.') {
dp = string1;
finalValue(&string1[i+1]);
} else {
printf("Sorry, we can't convert this to an integer\n\n");
} else {
} else {
num *= 10;
num += string1[i] - '0';
finalValue(&string1[i+1]);
}
} else if (dp) {
dp_offset = string1 - dp;
}
return num;
}
After calling finalValue() code can use the value of dp_offset to adjust the return value. Since this effort may be the beginning of a of a complete floating-point conversion, the value of dp_offset can be added to the exponent before begin applied to the significand.
Consider simplification
//int i = 0;
//if (string1[i] ...
if (*string1 ...
Note: using recursion here to find to do string to int is a questionable approach especially as it uses global variables to get the job done. A simply function would suffice. Something like untested code:
#include <stdio.h>
#include <stdlib.h>
long long fp_parse(const char *s, int *dp_offset) {
int dp = '.';
const char *dp_ptr = NULL;
long long sum = 0;
for (;;) {
if (*s >= '0' && *s <= '9') {
sum = sum * 10 + *s - '0';
} else if (*s == dp) {
dp_ptr = s;
} else if (*s) {
perror("Unexpected character");
break;
} else {
break;
}
s++;
}
*dp_offset = dp_ptr ? (s - dp_ptr -1) : 0;
return sum;
}
Figured it out:
#include <stdio.h>
#include <string.h>
//here we are setting up a boolean flag and two variables
#define TRUE 1
#define FALSE 0
double num = 0;
double dec = 0.0;
int flag = 0;
double final = 0.0;
double pow(double x, double y);
int j = 1;
//we declare our function that will output a DOUBLE
double finalValue(char *string1) {
//i is a counter
int i = 0;
//this will go through the string until it comes across the null value at the very end of the string, which is always present in C.
if (string1[i] != '\0') {
double newGuy = string1[i] - 48;
//as long as the current value of i isn't 'null', this code will run. It tests to see if a flag is true. If it isn't true, skip this and keep going. Once the flag is set to TRUE in the else statement below, this code will continue to run so that we can properly convert the decimal characers to floats.
if (flag == TRUE) {
newGuy = newGuy * pow(10,(j)*-1);
dec += newGuy;
j++;
finalValue(&string1[i+1]);
}
//this will be the first code to execute. It converts the characters to the left of the decimal (greater than 1) to an integer. Then it adds it to the 'num' global variable.
else {
num *= 10;
num += string1[i] - '0';
// This else statement will continue to run until it comes across a decimal point. The code below has been written to detect the decimal point and change the boolean flag to TRUE when it finds it. This is so that we can isolate the right part of the decimal and treat it differently (mathematically speaking). The ASCII value of a '.' is 46.
//Once the flag has been set to true, this else statement will no longer execute. The control flow will return to the top of the function, and the if statement saying "if the flag is TRUE, execute this' will be the only code to run.
if (string1[i+1] == 46){
flag = TRUE;
finalValue(&string1[i+2]);
}
//while this code block is running (before the flag is set to true) use recursion to keep converting characters into integers
finalValue(&string1[i+1]);
}
}
else {
final = num + dec;
return final;
}
return final;
}
int main(int argc, const char * argv[]) {
printf("string to integer conversion yields %.2f\n",(finalValue("234.89")));
return 0;
}

Struggling to figure out how to write a certain function

I've been trying for quite a while now to write a function in my C program which will perform a task if a given array does not contain a certain letter, otherwise if the array does contain this letter, another function is called and the program continues on elsewhere.
Here is an example of one such function I attempted:
int Asterisk(){
int v;
for(v=0; v<sizeof Mask; v++){
if(Mask[v] != '*'){
return 1;
}
else{
return 0;
}
}
}
As you can see, this function returns 1 when
Mask[0] != '*'
I can't figure out how to check every element of the array before returning a value, rather than just checking the first element.
Any help/guidance would be much appreciated!
Try the following
int Asterisk()
{
int i = 0;
while ( i < sizeof Mask && Mask[i] != '*' ) ++i;
return i == sizeof Mask;
}
Though as for me I would write the function such a way that if an asterisk is present in the array then the function returns 1.
int Asterisk()
{
int i = 0;
while ( i < sizeof Mask && Mask[i] != '*' ) ++i;
return i != sizeof Mask;
}
and in the caller use it like
if ( !Asterisk() ) { /* do something */ }
That is if an asterisk is present in the array then the function returns 1 otherwise returns 0.
If the character array contains strings then you could simply use standard C function strchr declared in header <string.h>
By array, you mean a simple string ? If it that case, you just need to write a function taking a string and the letter to find and return 0 if the string doesn't contain this letter else 1 at the first occurrence of the letter.
int Asterisk()
{
int v;
bool exists = false;
for(v=0; v<sizeof Mask; v++){
if(Mask[v] != '*'){
exists = true;
break;
}
}
return exists;
}

Recursive boolean function to check if a string is a palindrome

Write a recursive boolean function that returns 1 if a string is a palindrome and 0 if not.
bool ispalindrome(char str[])
Notes: the function must be recursive (not a wrapper for recursive function), it has to use the given (above) signature and no global or static variables are allowed, also, we can't 'destroy' the given string.
My attempt:
bool ispalindrome(char str[]){
bool res;
if (*str == 0 || *(str + 1) == 0)
return 1;
else{
res = ispalindrome(str + 1);
Now I'm stuck, I thought of making a helper function that uses dynamic arrays that would have the first and last elements from the original string removed and use that in the recursive call but I don't think that's the intended solution.
EDIT: I've made some progress, but it doesn't work:
bool ispalindrome(char str[]){
bool res;
int l = strlen(str);
char t;
if (*str == 0 || *(str + 1) == 0)
return 1;
else{
t = str[l-1];
str[l-1] = 0;
res = ispalindrome(str + 1);
if (res == 0)
return 0;
if (str[0] == str[l - 2])
res =1;
else
res=0;
str[l] = t;
return res;
}
}
So, your current code almost works. The only issues that I see is that in one case you return before you revert the changes in the string. Also, you have an off by one error in your indexing.
Let's also note some stylistic fixes:
*(str + 1) really should be str[1]. They're equivalent, but the latter is what is expected.
Since you've already calculated l = strlen(str), you could use that for your first conditional, since it's a bit more readable what that means.
You can also use longer variable names. They aren't more expensive.
Personally, I like that if you're writing the null character into a string, that you use the null character instead of 0. That is '\0'. But that's just me.
And the code:
bool ispalindrome(char str[]){
int l = strlen(str);
// Recusive Base Case
if (l == 0 || l == 1)
return true;
// Save the last character of the string
char t = str[l-1];
str[l-1] = '\0';
// Recursive call on the substring
bool res = ispalindrome(str + 1);
// Now, this is where you messed up. Before we return,
// we need to fix the string!
str[l-1] = t;
// If the recursive call thinks that it's not a palindrome,
// then we won't disagree.
if (res == false)
return res;
// Check the (current) first position of the string against the last
// You had an off by one error here.
return (str[0] == str[l - 1]);
}
Can we make a small improvement to the runtime of the code?
One annoying property of how your code works is that we will always have around strlen(str) / 2 recursive calls. Could we make the code run faster on an example like "abracadabra", where the second letter of the string causes the palindrome test to fail.
One way to speed it up would be to do the test (str[0] == str[l - 1]) before the recursive call. We could implement this fairly easily, and it might looks something like this:
bool ispalindrome(char str[]){
int length = strlen(str);
// Recursive Base Case
if (length == 0 || length == 1)
return true;
// Check our case.
// Note that this is occuring __before__ the recursive call
if (str[0] != str[length - 1])
return false;
// Save the last character of the string
char t = str[length - 1];
str[length - 1] = '\0';
// Recursive call on the substring
bool res = ispalindrome(str + 1);
// We need to fix the string
str[length - 1] = t;
return res;
}
All of this being said...
I've seen this question a couple of times on stackoverflow, and I'm always curious what the instructor is looking for. The classic version of this problem is solved by passing the string length as an additional parameter. By doing this, we save a ton of work.
Every solution posted so far (including mine) calls strlen() on every recursive call. That means that all of these solutions are at least O(n^2). If we could pass the length to the recursive call, we could easily solve the problem in O(n). This would be an extremely large reduction in work.
Additionally, you could also then write the code in a tail recursive manner. This can allow the compiler to generate code that is much nicer for the processor to execute. (Basically, it will transform the code into what a for-loop would look like). This is very helpful because you then don't have as many concerns about running out of stack space on very large strings.
But, because of the limitations that your instructor has placed, we can't do any of these things. Which is kind of lame.
without a compiler...
bool ispalindrome(char str[])
{
int len = strlen(str);
if( len <= 1)
{
return TRUE;
}
else if (str[0] != str[len - 1])
{
reutrn FALSE;
}
else
{
char *str2 = malloc(len - 1);
strncpy(str2, str + 1, len - 2);
str2[len - 2] = NULL;
BOOL result = ispalindrome(str2);
free(str2);
return result;
}
}
psuedocode (meaning, there is no thing called string in C, and I didn't try to compile it, and my imaginary library calls that are similar to real library calls could have the params in the wrong orders, etc):
bool isPalendrome(string s)
{
if (s[0] == s[strlen(s)-1]) // if the value of the first is the same as the last
{
if ((&s[strlen(s)-1] - &s[0]) < 3)// if the address of the end and the address of the start are 1, or 2, we have a palindrome of 1 or 2 chars..
{
return true;
}
s2 = alloca(strlen(s) - 1);// or VLA , -1 because -2 char, +1 for null
s2[strlen(s) - 2] = '\0';
strncpy(s+1,s2,strlen(s)-2);
return isPalendrome(s2)
}
return false;
}

Base conversion using recursion

I'm working on an assignment and have it partially solved.
Currently I'm getting the correct output, only in reverse.
Here's the helper function I've implemented:
char int2char (int radix, int value) {
char c = '?';
if ((value >= 0 && value < radix) && (radix <= 36 && radix >= 2)){
if (value < 10){
c = value + 48;
}
else if (value >= 10 && value < 36) {
c = value + 55;
}
}
return c;
}
And the actual function I'm having difficulty with looks like this thus far:
void int2str (int radix, int value) {
int result = value % radix;
int division = value / radix;
char c;
c = int2char(radix, result);
putchar(c);
while (division > 0) {
return int2str(radix, division);
}
}
The first function is used to represent the digits 10-35 in hex. So if the modulus produces an 11, for example, I'm supposed to output a 'B'.
This is working great, except backwards! And I can't figure out how to reverse it. The biggest hitch is you can only use putchar() as an output. No strings, no arrays.
To further clarify, if I enter:
int2str 16 60
The output should be '3C', instead I'm getting 'C3'.
First off, your use of while is confusing, since there's a return in it. Replace that with if. The return is unnecessary, since the function will return on its own at the end.
Once you've done that, you can reverse the output by moving the putchar after the recursive call:
if (division > 0) {
int2str(radix, division);
}
putchar(c);
As a side note, return int2str(radix, division); doesn't make sense in this function anyway, since it's a void function, so there's nothing to return. If you did want to do this (you don't in this case), you would say:
somefunction();
return;
Also, this may be more clear if you used '0' and 'A' instead of 48 and 55:
if (value < 10){
c = value + '0';
}
else if (value >= 10 && value < 36) {
c = value - 10 + 'A';
}
result is the last digit, but you're printing it first. Drop the return from the recursive call and move the putchar to the end. Also, the while loop should be an if.
void int2str(int radix, int value) {
int lastdigit = value % radix;
int firstdigits = value / radix;
if (firstdigits) {
int2str(radix, firstdigits);
}
putchar(int2char(radix, lastdigit));
}
Try this
c = int2char(radix, result);
if (division > 0)
int2str(radix, division);
putchar(c);
Last call to int2str will print first digit while first call will print last digit.

Resources