Recursion to find length of a string in C - c

I am trying to find the length of a string by recursion using the following code:
#include <stdio.h>
int string_length(char *s, int x);
int main(void)
{
int length = 0, x;
char string[] = "This is a string";
x = string_length(string, length);
printf("The length of the string will be: %d\n", x);
return (0);
}
int string_length(char *c, int x)
{
int a = 0;
if (*c != '\0')
{
a = a + 1;
string_length(c + 1, x + 1);
}
return (a);
}
But as I run my code, I get the following output:
The length of the string will be: 1
As it can be seen, this is not the correct length. I know that the length of a string is
16. Where did I go wrong.
I have searched for a while, and I have a hint it it has something to do with how I implemented my recursive function. How can I get around my issue?

For starters this function declaration
int string_length(char *s, int x);
does not make a great sense. The second parameter is redundant. Strings have the sentinel value '\0' that forms the basic case of the recursion.
The function always returns either 0 (for an empty string) or 1 because it returns the local variable a
int string_length(char *c, int x)
{
int a = 0;
if (*c != '\0')
{
a = a + 1;
string_length(c + 1, x + 1);
}
return (a);
}
that does not depend on the recursive call
string_length(c + 1, x + 1);
The function can be defined the following way
size_t string_length( const char *s )
{
return *s ? 1 + string_length( s + 1 ) : 0;
}
Pay attention to that the type int can be not large enough to be able to store the length of a string. You need to use the type size_t. It is the return type of the standard string function strlen. See the function declaration
size_t strlen(const char *s);
Also as the passed string is not changed within the function then the function parameter should be declared with the qualifier const.
In main you could write
size_t n = string_length( string );
printf("The length of the string will be: %zu\n", n);
Here is a demonstration program.
#include <stdio.h>
size_t string_length( const char *s )
{
return *s ? 1 + string_length( s + 1 ) : 0;
}
int main(void)
{
const char *s = "Hello World!";
printf( "The length of the string \"%s\" is %zu\n",
s, string_length( s ) );
}
The program output is
The length of the string "Hello World!" is 12

The problem is a is not a global variable.
What this means: for every depth of your recursion, a new variable a is being created, ignored, then set to 1 and returned. As a is a local variable, int a is separate across depths of your recursion.
There are two ways you can go about fixing this.
Make a a global variable. Your code could look something like this:
#include <stdio.h>
int string_length(char *s, int x);
int a = 0;
int main(void)
{
int length = 0, x;
char string[] = "This is a string";
x = string_length(string, length);
printf("The length of the string will be: %d\n", x);
return (0);
}
int string_length(char *c, int x)
{
if (*c != '\0')
{
a = a + 1;
string_length(c + 1, x + 1);
}
return (a);
}
Notice, all I did was move int a = 0 above int main(void). As a is now a global variable, its value is preserved between different calls of your recursive function, meaning they are all doing a = a + 1 on the same global variable a.
Utilize x.
I've noticed that in your function, you keep track of int x, yet never use it. int x is tracking the depth of your recursion, and you can use this to return the string length.
Your code could look something like this:
#include <stdio.h>
int string_length(char *s, int x);
int main(void)
{
int length = 0, x;
char string[] = "This is a string";
x = string_length(string, length);
printf("The length of the string will be: %d\n", x);
return (0);
}
int string_length(char *c, int x)
{
if (*c != '\0')
{
return string_length(c + 1, x + 1);
} else
{
return x;
}
}
Notice, method 2 (the method shown directly above) is mostly always preferred. This is because declaring lots of variables globally can pollute the global namespace, which is not recommended an leads to unnecessarily messy code.

Related

Unexpected problem with Bidimensional char VLA pointer

I did a simple program that splits a string in substrings, using the whitespace as a split reference. The program was working as expected, so I've decided to put this code inside a function that is called "substring_whitespace".This function return a size_t value which is the number of substring's. The function arguments are char* buffer[] and char* string. Both are pointers, the first will store the substring's, and the second is the string that'll be splited.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
size_t substring_whitespace(char* buffer[],char* string) {
size_t initial_string_size = strlen(string) + 1;
char actual_string[initial_string_size];
char strings[initial_string_size][initial_string_size];
strcpy(actual_string,string);
size_t c = 0;
for(; c<initial_string_size; c++) {
size_t first_whitespace_index = strcspn(actual_string," ");
char substring[first_whitespace_index];
for(size_t d = 0; d<=first_whitespace_index; d++) {
if(d == first_whitespace_index)
substring[first_whitespace_index] = 0;
else
substring[d] = actual_string[d];
}
size_t actual_string_length = strlen(actual_string);
size_t new_actual_string_length = (actual_string_length - first_whitespace_index) + 1;
char new_actual_string[new_actual_string_length];
for(size_t d = 0,i = first_whitespace_index + 1; i<=actual_string_length + 1; i++,d++) {
if(i == actual_string_length)
new_actual_string[d] = 0;
else
new_actual_string[d] = actual_string[i];
}
strcpy(actual_string,new_actual_string);
strcpy(strings[c],substring);
buffer[c] = strings[c];
if(new_actual_string_length == 1)
break;
}
return ++c;\
}
int main() {
char string[1000];
fgets(string,sizeof(string)/sizeof(string[0]),stdin);
string[strcspn(string,"\n")] = 0;
char* buffer[strlen(string) + 1];
size_t buffer_length = substring_whitespace(buffer,string);
for(int d = 0; d<buffer_length; d++) {
printf("\n%s",buffer[d]);
}
}
After I test, the results were not as expected, so during my debug I detect that the char were being changed after get off the function by pointer. This behavior is only detectable if I try to print the buffer strings in the main.
strings is a local variable whose lifetime ends when the function returns. The easiest fix is to copy the string when assigning a value buffer[c]:
buffer[c] = strdup(strings[c]);
Another option is to change the design and return an array of ranges relative to your input string. For example struct range { char *s; size_t len; };, and if string is "hello world" the function could return [{string, 5}, {string+6, 5}].

exercise 9.7 Kochan. strange output

I am working to learn C using Kochan's Programming in C 4th edition. problem 9.7 the goal is to insert a string of characters into another array. I am supposed to write a function to accomplish this. I have two problems.
When I have the algorithm print the result as it goes through the if statements, it produces the desired output, however when I change it to an %s, I only get a partial output. My hunch is that a null character is being placed where i do not want it, but I simply cannot see it.
To see what was happening, I added a printf that would track the letter and the array space it was occupying. I was surprised to see that the first letter was not 0, but was blank, and the next letter was assigned the 0. Any insight into this would be appreciated.
The funtion of interest is "insertString".
#include <stdio.h>
#include <stdbool.h>
char x[] = {"the wrong son was shot that day"};
char text[] = {"per"};
int countString (char x[])
{
int counter, z;
for (counter = 0; x[counter] != '\0'; ++counter)
z = counter+1;
return z;
}
void insertString (char text[],char x[],int n) //source, text to input, where
{
int count, clock, i = countString(text), q = countString(x);
int counter = 0;
char y[i + q];
for(count = 0; x[count] != '\0'; ++count){
if (count < n){
y[count] = x[count];
printf("%c %i", y[count], count); //The integer call is just to put a number next to the
//letter. This is where my second issue is shown.
}
else if (counter <= i){
y[count] = text[counter];
++counter;
printf("%c", y[count]);
}
else{
y[count]= x[count - counter];
printf("%c", y[count]);
}
}
printf("\n\n");
y[count-counter] = '\0';
printf("%s", y);
}
int main (void)
{
void insertString(char text[], char x[], int i);
int countString(char x[]);
int i;
insertString(text, x, 10);
return 0;
}
10 out of 10 times I post here it is because im doing something dumb, so I use SO as an absolute last resort if i am getting into the territory of just randomly trying stuff with no methodology. Thanks for your patience in advance.
Your condition is wrong in the for. It should be x[count - counter] != '\0'
In the second condition use just < to avoid overindexing. (else if (counter < i))
You put the terminating NULL char at wrong place. You should do this: y[count] = '\0'
printf inside a string routine like this is fine for debugging, but it's a poor way to write a general-purpose function because it makes it impossible to use its output for further programmatic manipulation. It can also make it difficult to reason about how the state of the function interacts in unpredictable ways with the state of the printed data.
I assume you haven't learned about dynamic memory allocation which is a prerequisite to returning strings from functions. You can inline the function logic into main or printf only at the end of the function in the meantime.
Adding to this point, a void function would need to reallocate space in the string to insert into and would be in-place. This seems likely less generally useful than allocating a new string to hold the result.
Using global variables like char x[] when there's no need is poor practice. It's better to put those strings scoped to main. Since your function can access these variables in addition to its parameters, confusion can ensue when scope and encapsulation is breached.
Use consistent formatting and avoid variable names like q that mean virtually nothing. Instead of adding comments to explain poor var names:
void insertString (char text[],char x[],int n) //source, text to input, where
You can simply name the variables exactly what they represent:
void insertString(char *dest, char *source, int add_index)
Also, now that you've mastered countString, you can abstract this by calling the builtin strlen.
Be sure to allocate enough space in buffers: char y[i + q]; should be y[i+q+1] to allow room for the null terminator '\0'.
As for the logic, I think it's easier to break into three loops without conditions instead of one loop with conditions. This makes it easier to break the problem down into the three constituent steps:
Add everything up until add_index from the dest string to the result.
Add everything in the source string to the result.
Add everything after add_index from the dest string to the result.
Using this approach, all that's left is figuring out how to map the indexes appropriately. Here it is in code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *insert_string(char *dest, char *source, int add_index) {
int source_len = strlen(source);
int dest_len = strlen(dest);
int result_size = source_len + dest_len + 1;
char *result = malloc(result_size);
for (int i = 0; i < add_index; i++) {
result[i] = dest[i];
}
for (int i = 0; i < source_len; i++) {
result[i+add_index] = source[i];
}
for (int i = add_index; i < dest_len; i++) {
result[i+add_index] = dest[i];
}
result[result_size-1] = '\0';
return result;
}
int main(void) {
char *result = insert_string("hello world", "cruel ", 6);
printf("%s\n", result);
free(result);
return 0;
}
Although this is likely for instructional purposes, these operations can be abstracted further using builtin string functions like strncpy and sprintf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *insert_string(char *dest, char *source, int add_index) {
int result_size = strlen(dest) + strlen(source) + 1;
char *result = malloc(result_size);
char pre[add_index+1];
pre[add_index] = '\0';
strncpy(pre, dest, add_index);
sprintf(result, "%s%s%s", pre, source, dest + add_index);
return result;
}
int main(void) {
char *result = insert_string("hello world", "cruel ", 6);
printf("%s\n", result);
free(result);
return 0;
}
Doing this in-place is more straightforward. Since the result already has the prefix, you can copy the destination postfix to create a source-sized gap in the middle and then overwrite the gap using the source string. It's up to the caller to make sure that the destination buffer is large enough to hold the insertion.
#include <stdio.h>
#include <string.h>
void insert_string(char *dest, char *source, int add_index) {
int source_len = strlen(source);
int dest_len = strlen(dest);
for (int i = add_index; i < dest_len; i++) {
dest[i+add_index] = dest[i];
}
for (int i = 0; i < source_len; i++) {
dest[i+add_index] = source[i];
}
}
int main(void) {
// allocate extra space in the string to hold the insertion
char greeting[32] = "hello world";
insert_string(greeting, "cruel ", 6);
printf("%s\n", greeting);
return 0;
}
A note of caution: none of these functions handle errors at all, so they're unsafe. Correct functions should check that the add_index falls within the bounds of the dest string. This is an exercise for the reader.
The original exercise is here:
Your function is not doing it. You need to insert the string into another string not to create a new one with both mixed. You can do it this way of course and then copy it into the original one - but it is the most uneficient way to archive it (memory & timewise).
Use the correct types.
size_t mystrlen(const char *str)
{
const char *end = str;
while(*end++);
return end - str - 1;
}
char *strinsert(char *dest, size_t pos, const char *istr)
{
char *temp = dest, *work;
size_t ilen = mystrlen(istr);
size_t nmove;
while(*temp) temp++;
nmove = temp - dest - pos + 1;
work = temp;
temp += ilen;
while(nmove--) *temp-- = *work--;
work = dest + pos;
while(*istr) *work++ = *istr++;
return dest;
}
int main()
{
char dest[128] = "0123456789012345678901234567890123456789";
printf("%s", strinsert(dest, 7, "ABCD"));
}
https://godbolt.org/z/KMnLU2

Why am I not getting the desired output?

The problem is to write the asked fibonacci word. For example if input is 0, then f(0) = a, if 1, f(1) = b and similarly f(2) = ba, f(3) = bab, f(4) = babba and so on. I wrote the following code to find the output on Ubuntu 18.04 LTS Terminal. I am getting the right output for n=0,1,2,3. But for n=4 I am getting babb instead of babba. I have tried debugging also but could not find where the code is going wrong. Kindly help me in finding the error.
#include <stdio.h>
#include <string.h>
void fibonacci(int n);
int main()
{
int x;
printf("Enter the fibonacci nword number you want to see:(f(x), f(0) is the starting element.):\n");
scanf("%d",&x);
printf("Required Word is:\n");
fibonacci(x);
return 0;
}
void fibonacci(int n)
{
int i,j=0;
char *p,*q,*r;
if(n==0)
{
printf("a\n");
}
else if(n==1)
{
printf("b\n");
}
else
{
char str1[100] = "a";
char str2[100] = "b";
char str3[100];
p = str1;
q = str2;
r = str3;
for(i=0;i<n-1;i++)
{
*r = *q;
strcat(str2,str1);
*p = *r;
}
printf("%s\n",str2);
}
}
First answering the main question, as of "Why I'm not getting the desired output":
Because you don't know what you're doing.
You are declaring 3 char[] variables statically, assigning them to pointers of type char*, and not even using them correctly.
Let's annalyze a part of your code:
for(i=0;i<n-1;i++)
{
*r = *q;
strcat(str2,str1);
*p = *r;
}
What you're doing is basically:
assign str3[0] = 'b' (in *r = *q)
copy the contents of str1 into str2, so, "ba" in the first run
assign str1[0] = 'b' (in *p = *r)
And then, repeatedly concatenate "b" into str2, because both str1 will only contain a single "b" for now on.
Doing that, for anything above 4, you'll only get "babbbbbbbbbb"...
My advice: If you're going to statically declare some variables, stop using pointers to access them. Try accessing the str1/str2 as vectors.
Your code is obfuscated. I modified it so:
#include <stdio.h>
#include <string.h>
char*fib(int n)
{
if (0==n)
return "a";
else if (1==n)
return "b";
else
{
char static out[2000]={'b', 'a'};
int idx=2, prev=1, tmp;
n-=2;
while(n--)
{
/* invariant: all values start at the beginning of `out`.
idx: keep the length of the current object
prev: keep the size of previous object
*/
memcpy(out+idx, out, prev);
tmp=prev;
prev=idx;
idx+=tmp;
}
return out;
}
}
int main()
{
int x;
printf("Enter the fibonacci nword number you want to see:"
"(f(x), f(0) is the starting element.):\n");
scanf("%d",&x);
printf("Required Word is:\n");
printf("~~%s\n", fib(x));
return 0;
}

How to use pointer to split the string into two strings? C language

The function char *my(char *s, int n) takes a string s and shifts the characters of s by n places, causing the characters to wrap around the string.
For example, given the string "This is my Apple!" , a shift of n = 2 will result in
String1: "Th"
String2: "is is my Apple!"
if n<0 it will shift in negative direction.
You can just use printf to split a string. If you want the result in a char *, you have to allocate some memory and use sprintf instead.
Here is a example using sprintfand memory allocation to return a char *.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *shift(char *string, int n)
{
int len = strlen(string);
char *shiftedString = malloc(len + 1);
n %= len; // in case you shift over string length
if (n < 0) n += len; // backward shift
sprintf(shiftedString, "%s%*.*s", string + n, n, n, string);
return shiftedString;
}
int main()
{
char *result = shift("This is my Apple!", 2);
printf("shifted string : %s\n", result);
free(result);
return 0;
}
the string is actually a char-array char[]
you could use the strlen function in combination with a for loop like so.
You can put that in a function thus creating your own function that would shift letters based on input N.
#include <stdio.h>
#include <string.h>
int main()
{
char string[] = "This is my Apple!";
//Initialize "n" before initializing the string variables.
int n = 2;
int len = strlen(string);
char string1[n];
char string2[len - n];
for(int i = 0;i<len;i++){
if(i<n){
string1[i]=string[i];
}else{
string2[i-n]=string[i];
}
}
printf("string = %s\n",string);
printf("string1 = %s\n",string1);
printf("string2 = %s\n",string2);
return 0;
}

Checking how much times a character occurs in a string with a recursive function

So, I have to write down a recursive function for checking how much times a character (c) occurs in a string (array) : note that the function MUST BE recursive. To be honest this is the hardest thing I've had to face since I started, so this is taking very long :| Here is the code (language is C) :
#include <stdio.h>
#include <time.h>
#define MAX 5
int charOccur (char [], int);
int main() {
char array[MAX+1]={'a', 'x', 'c', 'f', 'r'};
charOccur (array, MAX);
return 0;
}
int charOccur (char arr[], int dim){
int i, flag=0;
if (arr[0] == 'c'){
flag = 1;
return flag;
} else {
for (i=1; i<dim; i++){
if (arr[i] == 'c'){
flag++;
charOccur (arr, dim);
}
} return flag;
}
}
int occur(char *s, char c)
{
if (!*s) // if (*s == '\0')
return (0); // s is empty, do the character we're looking for does not exist
else if (*s == c)
return (1 + occur(s + 1, c));
else
return (occur(s + 1, c));
}
In the second case, we found our character, so we count 1 plus the rest of the input fed in our recursive function.
In the third case, the character pointed by s is neither '\0' nor c, so we keep going until we reach the end of the string.
In boths case, we use pointer arithmetic (s + 1), to change the character which is being pointed.
You should read a bit on memoization (it's not a typo). This wikipedia link is a good starting point; a more practical example is this one, which says:
Memoization means recording the results of earlier calculations so that we don’t have to repeat the calculations later.
In other words, in your code you might consider passing a counter to your function to store the result of the computation, before passing it to itself for the next recursion.
The example is shown in Ruby - it will help you understand the concept, rather than copy-pasting it as a solution.
And don't forget that in order to understand recursion, you must first understand recursion.
Consider a recursion that divides by 2 in each call. It does not reduce the number of calls, but limits the call depth to O(log2(n)).
#include <stdio.h>
#include <string.h>
static size_t Occurrence_helper(const char *s, size_t length, int ch) {
if (length > 1) {
size_t left = length / 2;
size_t right = length - left;
return Occurrence_helper(s, left, ch)
+ Occurrence_helper(s + left, right, ch);
} else if (length > 0) {
return *s == ch;
} else {
return 0;
}
}
size_t Occurrence(const char *s, int ch) {
return Occurrence_helper(s, strlen(s), ch);
}
Sample
int main(void) {
int ch = 'y';
const char *s = "xyzzy";
printf("'%c' occurs %zu times in \"%s\".\n", ch, Occurrence(s, ch), s);
return 0;
}
// Ouptut
'y' occurs 2 times in "xyzzy".
// 01 ) where 'c' is a constant
int charOccur (char arr[], int dim){
if(!dim) return 0;
dim--;
return ('c'==arr[dim])+charOccur (arr,dim);
}
// 02 ) passing c as a second parameter
int charOccur (char arr[],char c , int dim){
if(!dim) return 0;
dim--;
return (c==arr[dim])+charOccur (arr,c,dim);
}

Resources