Axel Foolya
Axel Foolya

Reputation: 1

Truncate string with realloc() in C?

For an assignment i´m asked to change a string str3 containing "Hello World!" to "Hello", and to use realloc() to remove the the exess memory. I dont realy know how to do it.

  1. How do i use realloc() to truncate the string?
  2. How do i change the string from "Hello World!" to "Hello"?

The DString is a char* pointer so DString *str is a double pointer char**. From the main()function we send str3 containing "Hello World!" and a blanc space to the function shrinkDString().

int main() {
    shrinkDString(&str3, ' ');  // truncate str3 after the blank, only "Hello" remains
    shrinkDString(&str3, ' ');  // nothing happens, "Hello" remains the same
}

As pre- and postcondition i´m supposed to use assert(). The DString *str is a double pointer to str3 and ch is a blanc space. Storing "hello World!" in str3 uses 13 memory including \0, "Hello" should only use memory of 6 including \0.

void shrinkDString(DString *str, char ch) {
   // Shrinks the DString *str up to the first occurence of ch.
   // Precondition: str is not NULL
   // Precondition: *str is not NULL
   /* Postcondition: if str has been truncated, its new length corresponds to the position of ch in the 
      original str*/

   /* Tips:
      - think that str is already allocated in memory and may be changed! Only the proper amount of 
        memory for storing the truncated string is allocated when the function return
      - do not forget the char for ending a string '\0'
      - useful C functions: realloc.
   */
}

This is what i´ve tried so far but i get a memory leak when using realloc() and assert(*str != NULL); is dereferencing NULL pointer.

void shrinkDString(DString *str, char ch) {

    assert(str != NULL);
    assert(*str != NULL);
   
    *str = (char*)realloc(*str, 6);
}

I dont know how to continue. Grateful for any help!

Upvotes: 0

Views: 1061

Answers (4)

How do i use realloc() to truncate the string?

You don't. A string is terminated by a null byte, and realloc() does not change any of the string's bytes. At least not in any way that you could rely on. The entire effect of a shrinking realloc() is, that it will consider the memory beyond the new size as free and safe for reuse by a future malloc() call. So, for example, the code

char* string1 = strdup("Hello World!");
string1 = realloc(string1, 6);
char* string2 = malloc(7);
printf("%s", string2);   //reading uninitialized data, don't do this

might conceivably print "World!". It could print "I've encrypted your harddrive, please pay ***$ in bitcoins..." instead. Whatever. The C standard does not care. It is simply one of the possible things that might happen, that the malloc() call returns the memory that was cut off from string1 with the realloc() call. (Real implementations won't actually print "World!" for reasons which are way beyond this question.)


How do i change the string from "Hello World!" to "Hello"?

You terminate the string with a null byte. That's as simple as

(*str)[5] = 0;

Note the parentheses which force the double pointer to be dereferenced before performing the array subscript operation. Once you have cut down the string like this, you can subsequently also shrink the allocation with realloc():

(*str)[5] = 0;
*str = realloc(*str, 6);   //5 characters plus one terminating null byte

Upvotes: 0

user3629249
user3629249

Reputation: 16540

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. checks for and handles errors

and now, the proposed code:

#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>


void shrinkDString( char **str, char targetChar) 
{
    char *localStr = *str;
    
    assert(str != NULL);
    assert(localStr != NULL);

   
    char *stopChar = strchr( localStr, (int)targetChar );
    if( ! stopChar )
    {
        fprintf( stderr, "target char not in  **str\n" );
        return;
    }
    
    // impllied else, target char found
    
    *stopChar = '\0';
    
    char *temp = realloc( localStr, strlen( localStr ) + 1 );
    if( ! temp )
    {
        perror( "realloc failed" );
        exit( EXIT_FAILURE );
    }
    
    // implied else, realloc successful
    *str = temp;
}

Upvotes: -1

You'd do something like

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
  {
  char *s = malloc(100);

  strcpy(s, "Hello World!");
  
  printf("1 - s=%p  *s = '%s'\n", s, s);
  
  s[5] = '\0';
  
  s = realloc(s, strlen(s)+1);
  
  printf("2 - s=%p  *s = '%s'\n", s, s);

  return 0;
  }

Note that realloc may not actually change the address of the memory block - it may just release the extra space at the end of it, or it may not do anything at all!

Note that this example code doesn't do any of the necessary checking for invalid return values, etc, which you should add.

onlinegdb here

Upvotes: 2

0___________
0___________

Reputation: 67709

It is not possible only using the realloc. You need also to add the trailing null character.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TEXT "Hello World"

int main()
{
    char *ptr = malloc(strlen(TEXT) + 1);

    strcpy(ptr,TEXT);
    printf("original string: %s", ptr);

    ptr = realloc(ptr, 6);
    ptr[5] = 0;
    printf("realloced string: %s", ptr);
    free(ptr);
    return(0);
}

Upvotes: 0

Related Questions