Concatenating a char in a recursive function in C - c

Even though I have more experience with higher level languages, I am having a lot of troubles understanding how memory allocation and how strings really work in C.
I am trying to implement a very simple base converter that works recursively. The only thing is that it should return a char* instead of an int
Here is my code. I already tested the recursive calls and it works if I use integers. So, the problem is definitely with the string part. It gives me an infinite loop.
char* baseConversion(int num, int baseIn, int baseOut){
//convert num to base ten
int quotient = num / baseOut;
int remainder = num % baseOut;
char rem = (char)(((int)'0') + remainder);
char *result = malloc(strlen(output) + 1);
strcpy(result, rem);
if (quotient == 0)
return result;
else
return strcat(result, baseConversion(quotient, baseIn, baseOut));
}
Many thanks

Change:
strcpy(result, rem);
to:
result[0] = rem;
result[1] = 0;
This will create a single-character string containing the character in rem.
You also may need to fix:
malloc(strlen(output)+1)
as there's no variable named output in your function.

If I have understood correctly what you are saying about then what you need is the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * baseConversion( unsigned int x, unsigned int base )
{
unsigned int digit;
char *p = NULL;
size_t n = 2;
if ( base > 10 || base < 2 ) base = 10;
digit = x % base;
if ( x / base ) p = baseConversion( x / base, base );
if ( p ) n += strlen( p );
p = realloc( p, n );
*( p + n - 2 ) = digit + '0';
*( p + n - 1 ) = '\0';
return p;
}
int main(void)
{
unsigned int x = 255;
char *p = baseConversion( x, 10 );
printf( "%s\n", p );
free( p );
p = baseConversion( x, 8 );
printf( "%s\n", p );
free( p );
p = baseConversion( x, 2 );
printf( "%s\n", p );
free( p );
return 0;
}
The output is
255
377
11111111
P.S. It is funny when one answer is marked as the best but the code will be used from other answer.:)

Related

C string is empty after assignment

I was trying to solve a coding problem to covert an integer to a string using C. e.g. if there is an integer 321, then the function should return a string "321". My character assignment seems to be successful based on the output during the assignment. However, once the assignment is complete, my string is completely empty. Not sure why this would be happening. I am guessing it has something to do with the null terminating character?
char * solution(int X) {
printf("x is %d\n", X);
int len = len_num (X); //Returns correct length as tested.
printf("Length is %d\n", len);
char * str = (char*)malloc( (++len * sizeof(char)) ); //one extra space for '\0'
str[len] = '\0'; //Assigning the last character as null terminating character '\0'
int i = len - 1 ;
do
{
int n = X%10;
str[i] = '0' + n;
printf("str[%i]:%c, n:%d.\n", i, str[i], n);
X = X / 10;
i--;
}while (i > 0);
printf("\nstr:%s.\n", str);
return str;
}
Output:
x is 942
Length is 3
str[1]:2, n:2. <---- All assignments are successful
str[2]:4, n:4.
str[3]:9, n:9.
str:. <----This shouldn't be empty!
You have some off-by-one errors.
The first is here:
char * str = (char*)malloc( (++len * sizeof(char)) ); //one extra space for '\0'
str[len] = '\0'; //Assigning the last character as null terminating character '\0'
You allocate enough space, but because len was incremented str[len] is off the end of allocated memory, and writing to caused undefined behavior. You instead want:
char * str = malloc( len + 1 );
Noting that you shouldn't cast the return value of malloc and that sizeof(char) is defined to be 1.
Related to this, at the bottom of the loop you decrement i and then check if it is greater than 0. This means you never write to element 0 of the array. You want:
do
{
...
}while (i >= 0);
For starters this statement
str[len] = '\0';
writes beyond the allocated character array that was allocated in this declaration using the sub-expression ++len.
char * str = (char*)malloc( (++len * sizeof(char)) );
So already the program has undefined behavior.
Also due to the condition of the while loop
while (i > 0);
you never set the element of the array str[0].
As the function parameter has the signed integer type int then the user can pass a negative number. You should process such a situation correctly.
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
size_t len_num( int x )
{
const int Base = 10;
size_t n = 0;
do
{
++n;
} while ( x /= Base );
return n;
}
char * solution( int x )
{
const int Base = 10;
size_t len = len_num( x );
int sign = x < 0;
if ( sign ) ++len;
char *s = (char * )malloc( len + 1 );
if ( s )
{
s[len] = '\0';
do
{
s[--len] = ( sign ? -( x % Base ) : ( x % Base ) ) + '0';
} while ( x /= Base );
if ( sign ) s[--len] = '-';
}
return s;
}
int main(void)
{
int x = 12345;
char *s = solution( x );
if ( s ) puts( s );
free( s );
x = -12345;
s = solution( x );
if ( s ) puts( s );
free( s );
return 0;
}
The program output is
12345
-12345

odd or even number using pointer in C

I have an array, the elements inside this array should be assigned randomly
then I create two more arrays one for odd and one for even numbers
using pointers I want to put the odd numbers inside the odd array, and the even numbers in the even one.
how can I assign it using pointers?
I came up with this:
int main()
{
int array[10];
int *arrayPtr = &array;
int arrayEven[10];
int *pEven = &arrayEven;
int arrayOdd[10];
int * pOdd = &arrayOdd;
int i, j;
for(i=0; i<10; i++)
{
array[i] =rand()%100 ;
if(array[i] %2 ==0)
{
printf("%d\n", array[i]);
printf("Even number");
}
else
{
printf("%d\n", array[i]);
printf("Odd number");
}
}
These declarations of pointers
int *arrayPtr = &array;
int *pEven = &arrayEven;
int * pOdd = &arrayOdd;
are incorrect. The initializers have the type int( * )[10] according to the declarations of the arrays as for example of the variable array
int array[10];
while the declared pointers has incompatible type int *.
What you need is declarations like this
int *arrayPtr = array;
There is no great sense to define arrays of the same size as the source array because for example the source array can have no odd or even numbers. You should deal with arrays depending on the number of odd and even numbers in the source array. If your compiler supports variable length arrays then you can use them. Or you should dynamically allocate arrays.
Here is a demonstrative program that shows how the assignment can be done using variable length arrays and pointers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void copy_if( const int a1[], size_t n, int *a2, int *a3, int predicate( int ) )
{
for ( const int *p = a1; p != a1 + n; ++p )
{
if ( predicate( *p ) )
{
*a2++ = *p;
}
else
{
*a3++ = *p;
}
}
}
size_t count_if( const int a[], size_t n, int predicate( int ) )
{
size_t cnt = 0;
for ( const int *p = a; p != a + n; ++p )
{
if ( predicate( *p ) ) ++cnt;
}
return cnt;
}
int is_even( int x )
{
return x % 2 == 0;
}
int main(void)
{
enum { N = 10 };
int a1[N];
srand( ( unsigned int )time( NULL ) );
for ( int *p = a1; p != a1 + N; ++p )
{
*p = rand() % N;
}
for ( const int *p = a1; p != a1 + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
size_t cnt = count_if( a1, N, is_even );
if ( cnt != 0 && cnt != N )
{
int a2[cnt];
int a3[N-cnt];
copy_if( a1, N, a2, a3, is_even );
for ( const int *p = a2; p != a2 + cnt; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
for ( const int *p = a3; p != a3 + N - cnt; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
}
return 0;
}
The program output might look like
6 3 3 8 3 0 5 5 3 2
6 8 0 2
3 3 3 5 5 3
If to use your straightforward approach then the program can look the following way
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
enum { N = 10 };
int array[N];
int *arrayPtr = array;
srand( ( unsigned int )time( NULL ) );
for ( int *p = arrayPtr; p != arrayPtr + N; ++p )
{
*p = rand() % N;
}
for ( const int *p = arrayPtr; p != arrayPtr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
int arrayEven[10];
int *pEven = arrayEven;
int arrayOdd[10];
int *pOdd = arrayOdd;
int *pEvenEnd = pEven;
int *pOddEnd = pOdd;
for ( const int *p = array; p != arrayPtr + N; ++p )
{
if ( *p % 2 == 0 )
{
*pEvenEnd++ = *p;
}
else
{
*pOddEnd++ = *p;
}
}
for ( const int *p = pEven; p != pEvenEnd; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
for ( const int *p = pOdd; p != pOddEnd; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
Its output might look for example like
1 0 0 3 4 5 2 1 9 5
0 0 4 2
1 3 5 1 9 5
For it to work you need two additional coutner variables
int oddCount, evenCount;
these need to be initialized to be 0 (i.e. how many odd/even number you have inserted so far). Then while iterating your first array you increment the respective coutner if you encounter an even/odd number. Also you can just use these variables to know where you need to put the next even/odd number in their respective array.
You can use binary comparison since all odd finish by 1 in binary mode :
If( a & 1)
//Odd
Else
//Even

read indefinite amount of integers until one is negative and then print them

I am new to pointers so I tried inventing this simple problem. why is it not working? other than saying what mistake I made I'd greatly appreciate if you guys could tell me an alternative to this method
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int *p;
int i, j;
i = 0;
p = (int *)malloc(sizeof(int) * (i + 1));
scanf("%d", p);
do {
i++;
p = realloc(p, sizeof(int) * i);
scanf("%d", (p + i));
} while (*(p + i) > 0);
for (j = 0; j < i; j++) {
printf("%d\n", *(p + j));
}
free(p);
return 0;
}
This statement
p=(int *)malloc(sizeof(int) * (i+1));
is redundant. It is better to write
p = NULL;
And in a call of scanf use an object of the type int not the pointer.
There can be redundant memory allocation if for example the first entered value will be negative
In this call
scanf("%d", (p+i));
there is an access beyond the allocated memory. You should at least write
scanf("%d", (p + i -1));
It is better to specify an intermediate pointer in this statement
p=realloc(p,sizeof(int)*i);
because the function can return NULL. In this case the address of the previously allocated memory will be lost.
And the condition in the loop
}while(*(p+i)>0);
does not check that the value is not negative.
The program can look the following way
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int *p = NULL;
size_t n = 0;
int value;
for ( int *tmp;
scanf( "%d", &value ) == 1 &&
!( value < 0 ) &&
( tmp = realloc( p, ( n + 1 ) * sizeof( int ) ) ) != NULL;
++n )
{
p = tmp;
*( p + n ) = value;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", *( p + i ) );
}
putchar( '\n' );
free( p );
return 0;
}
If to enter
0 1 2 3 4 5 6 7 8 9 -1
the program output will be
0 1 2 3 4 5 6 7 8 9

converted string failed to contain correct values of float

I am facing problem in converting float to char*.
I have written a function that will put integer part of float in string and then decimal values. I need it for two places of decimal. But something is horribly wrong. Either it ouputs integer value or just 1 place after decimal. Can someone please guide me?
Below is my attempt
void float_to_str(char *str, float f, char size)
{
char pos; // position in string
char len; // length of decimal part of result
char* curr; // temp holder for next digit
int value, i ; // decimal digit(s) to convert
float temp;
pos = 0; // initialize pos, just to be sure
value = ( int )f; // truncate the floating point number
snprintf( curr, sizeof(curr), "%d", value);
strncmp( str, curr, strlen( curr ) );
// now str array has the digits before the decimal
if (f < 0 ) // handle negative numbers
{
f *= -1;
value *= -1;
}
len = strlen( str );
pos = len; // position the pointer to the end of the integer part
str[pos++] = '.'; // add decimal point to string
f = f -( float ) value + 0.005;
printf( " the value of f = %f\n", f );
for( i = 0; i < size; ++i )
{
temp = f* 10;
value = ( int )temp ;
snprintf( curr, sizeof(curr),"%d", value );
str[ pos++ ] = *curr;
}
str[ pos ] = '/0';
printf(" debug --> the string is %s \n", str ); // prints only 5 instead of 6455.56
}
int main()
{
float test = 555564.5555;
char arr[ 40 ];
memset(arr, 0, 40 );
FloatToStringNew( arr,test, 2 );
printf( " the float to string is %s", arr ); // OUT Put is 5 which is wrong
return 0;
}
The entire float_to_string can be reduced to (as suggested by BLUEPIXY):
void float_to_str(char *str, float f, char size)
{
sprintf(str, "%.*f", size, f);
}
However, if you are interested in the bug in your code, it is in the for loop:
for( i = 0; i < size; ++i )
{
temp = f* 10; // Value of f stays the same in every iteration
value = ( int )temp ;
snprintf( curr, sizeof(curr),"%d", value );
str[ pos++ ] = *curr;
}
Fix:
for( i = 0; i < size; ++i )
{
f = f * 10; // Modify f each iteration
value = ( int )f;
snprintf( curr, sizeof(curr),"%d", value );
str[ pos++ ] = *curr;
f = f - (int)f; // Remove the integer part
}
Edit:
There are a couple of other stuff in the function that needs fixing:
strncmp should be strcpy
pos should be of type int or size_t
curr should be an array instead of a pointer.
The call from main should be to float_to_string, not FloatToStringNew
The compiler helped me locate them when I compiled with warnings (I used -Wall in gcc).

Function that convert int to array of char, some questions

This code need to get an int number and convert it to array of char that present the number:
for example :
The number 324
convert to this:
like:
char newstr [6] = {'3','2','4','\0','\0','\0'};
I think that '\0' is null, right?
What is wrong with my code ?
also how can I change this to a function that get an int number and return array of char that present it?
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void main ()
{
int value = 324;
char str [6];
char newstr [6];
int pointer, i = 0;
for(i=0; value>0; i++)
{
str[i] = value%10 + '0';
value /=10;
}
str[i] = '\0';
for(i=5; i>-1; i--)
{
if(str[i]!='\0')
{
newstr[pointer] = str[i];
pointer++;
}
}
for (i = 0; i < 6; i++)
{
printf("%d %c\n", i, newstr[i] );
}
printf ("shalom");
}
An easy way should be calling sprintf().
char newstr[6] = {0};
sprintf(newstr, "%d", value);
In your existing code, str looks lile {'4', '2', '3', '\0', SomethingRandom, SomethingRandom}. Reversing it and assign to newstr makes it {SomethingRandom, SomethingRandom, '\0', '3', '2', '4'}, which is definitely not what you want. And indeed you don't assign newstr when str[i] == '\0', which means newstr[2] == SomethingRandom.
Try the following
#include <stdio.h>
#include <stdlib.h>
char * itoa( int x )
{
const unsigned int BASE = 10;
unsigned int u = abs( x );
size_t n = 0;
unsigned int tmp = u;
char *s;
do { ++n; } while ( tmp /= BASE );
n += x < 0;
s = malloc( ( n + 1 ) * sizeof( char ) );
s[n] = '\0';
do
{
s[--n] = u % BASE + '0';
} while ( u /= BASE );
if ( x < 0 ) s[--n] = '-';
return s;
}
int main(void)
{
char *s = itoa( -1234567890 );
printf( "%s\n", s );
free( s );
return 0;
}
The output is
-1234567890
As for your question what is wrong with your code then it is entirely wrong.:)
For example the code ignores numbers that are equal to zero. Variable pointer was not initialized
int pointer, i = 0;
each loop deals with some garbage and so on.
It will be more helpful for you if you will investigate my code.
OP's code looks very close to being correct for limited usage.
Do not start with value>0 test, otherwise when value == 0, the result will be "". Be sure to limit the number of iterations to not exceed the array size.
do {
str[i] = value%10 + '0';
value /=10;
i++;
} while (value>0 && i < (6-1));
Set '\0' in a loop. #timra points out random unset elements.
do {
str[i] = '\0';
i++;
} while (i < (6-1));
OP still has 2 remaining issues which OP has yet to specify what to do:
Values greater than 99999
Values < 0
BTW: "I think that '\0' is null, right?" '\0' is the "null character". This differs from NULL, the "null pointer".
"how can I change this to a function that get an int number and return array of char that present it"
OP's code has a number of corner problems. Suggest a new approach.
Perform conversion into local array and then return a copy of it.
Calling code should eventually free() it.
#include <limits.h>
// max size needed for int. Note 10/33 just greater than log(2)
#define INTSIZE_MAX (sizeof int * CHAR_BIT * 10 / 33 + 3)
char *intoa_alloc(int x) {
char buf[INTSIZE_MAX];
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value to cope with INT_MIN
// This avoids portability problems with abs(x) approach.
int x_negative = x < 0 ? x : -x;
// Form string
*p = '\0';
do {
*--p = '0' - x_negative % 10;
x_negative /= 10;
} while (x_negative);
if (x < 0) {
*--p = '-';
}
char *dest = malloc(strlen(p) + 1);
if (dest) {
strcpy(dest, p);
}
return dest;
}
In this simple way you can do that.
int main()
{
char str [6] = "324";
printf ("%c",str[1]);
return 0;
}

Resources