user4252523
user4252523

Reputation: 69

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!

Upvotes: 0

Views: 246

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 311028

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

Upvotes: 1

dbush
dbush

Reputation: 224082

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

Upvotes: 2

Related Questions