Dynamic array allocation and reallocation

This is a discussion on Dynamic array allocation and reallocation within the C Programming forums, part of the General Programming Boards category; Well my other thread regarding the best way to get user input got me thinking. Using fgets() and fgetc() are ...

  1. #1
    Registered User purple's Avatar
    Join Date
    Mar 2002
    Posts
    28

    Dynamic array allocation and reallocation

    Well my other thread regarding the best way to get user input got me thinking. Using fgets() and fgetc() are great if you have an array of a predetermined size and you don't want to overflow the buffer.

    It led me to a different question of how to handle user input of any size without limitation. I came up with the following code which sort of works except for some reason that I can't figure out it also seems to place garbage characters into the buffer along with the wanted ones.

    When I enter the string: asdf

    It gives me this as output, you can clearly see the 'a', 's', 'd', 'f' in there along with the garbage: as d f

    Here is my code for anyone that wants to try and figure out my error:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
    	char c1[1];			//used for fgetc
    	char *ptr;			//pointer to dynamic array
    	int ar_size = 1;	//incremental counter for size of dynamic array
    
    		printf("\n- Enter a string: ");
    
    		c1[0] = fgetc(stdin);
    		ptr = (char *)calloc(ar_size, sizeof(char));
    		strcpy(ptr, c1);
    
    	/*	loop until no more chars in the input stream	*/ 
    		while( (c1[0] = fgetc(stdin)) != '\n' )
    		{
    			ptr = (char *)realloc((char *)ptr, ar_size*sizeof(char));
    			strcat(ptr, c1);
    			ar_size++;
    		}
    
    		printf("\n- Successfully allocated memory for: %s", ptr);
    
    	/*	used in Windows environment to keep window open	*/
    		printf("\n\nPress ENTER to exit...");
    		fgetc(stdin);
    
    	return(0);
    }

  2. #2
    Mayor of Awesometown Govtcheez's Avatar
    Join Date
    Aug 2001
    Location
    MI
    Posts
    8,825
    To allocate space for a string, you don't have to go through all this - look up the malloc function.

  3. #3
    Registered User purple's Avatar
    Join Date
    Mar 2002
    Posts
    28
    The only difference that I know of between malloc and calloc is that calloc zeros out the array if it's of a numeric type, or NULLs out the array if it's of type char.

    I don't see how that would help, but I could be wrong.

  4. #4
    moi
    moi is offline
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    both arguments to strcat() should be null terminated strings (c1 is not)

    strcat() is therefore reading out of c1 and into garbage space, and you're lucky things are running at all

    edit: it's too early in the morning for me, but i dont think ptr is null-terminated either
    Last edited by moi; 08-01-2002 at 07:43 AM.

  5. #5
    moi
    moi is offline
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    this compiled and worked fine for me, but that in it self doesnt mean much

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main (void)
    {
      char c1[2];
      char *ptr;
      int ar_size = 2;
      ptr = (char *) calloc (1, 1);
      c1[1] = '\0';
      printf  ("\nType some shizzle fo my nizzle:\n");
    
      while ((c1[0] = fgetc (stdin)) != '\n')
      {
        ptr = (char *) realloc ((char *) ptr, ar_size);
        ptr[ar_size - 1] = '\0';
        strcat (ptr, c1);
        ar_size++;
      }
      printf ("\nMeh: %s\n", ptr);
      free (ptr);
      return EXIT_SUCCESS;
    }
    Last edited by moi; 08-01-2002 at 08:13 AM.

  6. #6
    Registered User purple's Avatar
    Join Date
    Mar 2002
    Posts
    28
    Sweet...thanks for pointing that out. I made some minor alterations and now it works flawlessly.

    - I increased the size of c1 by one to allow room for one char and the NULL.

    - I also increased the initial value of ar_size by one for basically the same reason so the char and the NULL can fit when doing strcpy() and strcat().

    - I manually added the NULL character to the end of the c1 array and also to the array that ptr points to.

    Here is the finalized working code, enjoy...BIG THANKS to moi for pointing out that minor problem
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
    	char c1[2];			//used for fgetc
    	char *ptr;			//pointer to dynamic array
    	int ar_size = 2;	//incremental counter for size of dynamic array
    
    		printf("\n- Enter a string: ");
    
    		c1[0] = fgetc(stdin);
    		c1[1] = '\0';
    		ptr = (char *)calloc(ar_size, sizeof(char));
    		strcpy(ptr, c1);
    
    	/*	loop until no more chars in the input stream	*/ 
    		while( (c1[0] = fgetc(stdin)) != '\n' )
    		{
    			c1[1] = '\0';
    			ptr = (char *)realloc((char *)ptr, ar_size*sizeof(char));
    			ptr[ar_size-1] = '\0';
    			strcat(ptr, c1);
    			ar_size++;
    		}
    
    		printf("\n- Successfully allocated memory for: %s", ptr);
    
    	/*	used in Windows environment to keep window open	*/
    		printf("\n\nPress ENTER to exit...");
    		fgetc(stdin);
    
    	return(0);
    }

  7. #7
    Registered User purple's Avatar
    Join Date
    Mar 2002
    Posts
    28
    Heh...you beat me to it

  8. #8
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Remember that fgetc() returns an int, whereas you are assigning it to a char. I know you're not testing for EOF in this particular program, but for good habit's sake, use an int!

    Also, don't use the same pointer as the first parm to realloc() as you do to receive the functions return value. If realloc() fails, it will return NULL, and you will loose the pointer to the original memory block, thus creating a leak.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  9. #9
    moi
    moi is offline
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    Originally posted by Hammer
    If realloc() fails, it will return NULL, and you will loose the pointer to the original memory block, thus creating a leak.
    eww good point (i never use realloc)

    so a safe usage of realloc would be

    edit: fixed stupiditiy

    Code:
    int oldsize;
    int newsize;
    char *thingy;
    char *tmp;
    /* snip */
    if (!(thingy = malloc (oldsize)))
      /* handle failure to allocate original size */
    tmp = thingy;
    if (!(thingy = realloc (thingy, newsize)))
      /* handle failure to allocate new size, but no memory leak
       * because we can call free (tmp); */
    right?
    Last edited by moi; 08-01-2002 at 08:18 AM.

  10. #10
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Code:
    char *mainptr, *tempptr;
    
    mainptr = malloc(10);
    
    tempptr = realloc(mainptr, 20);
    
    if (tempptr == NULL)
    {
    	/* request for more memory failed */
    	/* but we're still running. */
    	/* mainptr still points to our original block */
    }
    else
    {
    	/* got more memory OK, reassign pointers */
    	mainptr = tempptr;
    }
    I think this matches what you said, but you didn't give realloc() enough parms, so I can't be sure.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  11. #11
    Registered User purple's Avatar
    Join Date
    Mar 2002
    Posts
    28

    Great Point!!!

    Yes I totally agree Hammer, although this program was just for fun to see if I could code it.

  12. #12
    moi
    moi is offline
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    Originally posted by Hammer
    Code:
    char *mainptr, *tempptr;
    
    mainptr = malloc(10);
    
    tempptr = realloc(mainptr, 20);
    
    if (tempptr == NULL)
    {
    	/* request for more memory failed */
    	/* but we're still running. */
    	/* mainptr still points to our original block */
    }
    else
    {
    	/* got more memory OK, reassign pointers */
    	mainptr = tempptr;
    }
    I think this matches what you said, but you didn't give realloc() enough parms, so I can't be sure.
    DOH it's too early for me

  13. #13
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231

    Re: Great Point!!!

    >Yes I totally agree Hammer, although this program was just for fun to see if I could code it.
    Good, and I'm glad you're having fun.

    >DOH it's too early for me
    I have that trouble too, late at night... eyes failing... brain shutdown....
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  14. #14
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,484
    You also don't need to call malloc before calling realloc.

    So long as you initialise your pointer to NULL, you can do this

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 05-29-2009, 07:25 PM
  2. Understanding Memory Allocation
    By Ragsdale85 in forum C Programming
    Replies: 7
    Last Post: 10-31-2005, 07:36 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21