Dynamic memory allocation and strings.

This is a discussion on Dynamic memory allocation and strings. within the C Programming forums, part of the General Programming Boards category; Hi, I am trying to ask the user for an input (a string), then store the input in a string ...

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    2

    Dynamic memory allocation and strings.

    Hi,
    I am trying to ask the user for an input (a string), then store the input in a string variable with the same length of the string in-putted.
    Is this possible? I have some code below but this requires the user to input the string twice.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void){
    int num_char=1, i;
    char holder=' ';
    char *string;
    printf("Please enter a sentence:\n");
    while (holder != '\n'){
    	holder = getchar();
    	printf("%c ",holder);
    	num_char++;
    }
    printf("\n%d\n",num_char);
    string = (char*) malloc(sizeof(char)*num_char);
    gets(string);
    for (i=0; i<num_char; i++){
    	printf("%c",string);}
    return 0;
    }
    Thanks

    Sef

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,164
    You're not allocating enough space. Make sure you allocate enough room to store the '\0':
    Code:
    string = (char*) malloc(sizeof(char)*(num_char + 1));
    Also, please don't ever use gets(). It's not safe.

    And to the meat of the matter, there's no way to portably peak into the input buffer, so the only way you're going to pull off what you're trying to accomplish is by slowly building up the buffer using realloc():
    Code:
    char *string = NULL;
    size_t bytes_allocated = 0;
    puts("Please enter a sentence:");
    do
    {
      holder = getchar();
      if(holder != '\n')
      {
        if(string != NULL)
          string = malloc(2);
        else
          string = realloc(string, bytes_allocated + 2);  // + 2 to make room for the input character plus a '\0'
        string[bytes_allocated++] = holder;
      } while(holder != '\n');
    }
    string[bytes_allocated] = '\0';
    Something like that anyway.
    Last edited by itsme86; 01-03-2011 at 11:00 AM. Reason: Initially malloc() 2 bytes instead of 1
    If you understand what you're doing, you're not learning anything.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,498
    I can think of two basic options.
    1. There is a maximum you expect from the user and will discard anything else after that:
    Code:
    char buffer[MAX_LEN+1];  // one extra space for the null character
    char *input;
    read string into buffer using fgets, scanf, etc
    allocate strlen(buffer) + 1 bytes into input 
    copy the contents of buffer into input
    2. There is no maximum, or you like causing yourself undue suffering.
    Code:
    char c;
    char *input = malloc(1);  // initial allocation so we can just realloc in our loop
    int n_char = 0;
    input[0] = '\0';  // null terminate input in case they enter no data
    do
        c = read a character
        if c is not EOF
            reallocate n_char+1 bytes into input
            copy c onto the end of input
            null terminate input
    while c is not EOF
    There is a third method that uses a combination of 1 and 2 so you read in, say, 1000 chars at a time to a buffer and reallocate if need be. This would be my preferred method only if option 1 is not sufficient.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,498
    Quote Originally Posted by itsme86 View Post
    Code:
    ...
          string = realloc(string, bytes_allocated + 2);  // + 2 to make room for the input
    ...
    You only need to add one more byte each time, since your previous instance already had a null, and you're only adding one character of input in each iteration.

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,164
    Quote Originally Posted by anduril462 View Post
    You only need to add one more byte each time, since your previous instance already had a null, and you're only adding one character of input in each iteration.
    Look at my code again. I'm only adding the '\0' once, after the loop.
    If you understand what you're doing, you're not learning anything.

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,498
    Duh...yeah, I see that now. Besides, you only increment bytes_allocated by 1 each time, so realloc will only go up by one from it's previous value. I'll take that foot out of my mouth and remove my head from my...

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,304
    You appear to be using gets. gets is bad and can never be used safely. Do not use it ever!
    Use fgets instead.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Registered User
    Join Date
    Jan 2011
    Posts
    2
    Ahh it all makes sense now, also I realise not to use gets. haha

    Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Array of strings and memory allocation
    By maluyk in forum C Programming
    Replies: 7
    Last Post: 01-26-2009, 10:52 AM
  2. Strings and Dynamic Memory
    By grooveordie in forum C Programming
    Replies: 3
    Last Post: 10-20-2008, 02:08 PM
  3. dynamic memory allocation on demand
    By oilrg in forum C Programming
    Replies: 5
    Last Post: 12-02-2007, 01:59 AM
  4. Dynamic allocation of an array of strings
    By earth_angel in forum C Programming
    Replies: 3
    Last Post: 06-24-2005, 09:40 AM
  5. Pointer's
    By xlordt in forum C Programming
    Replies: 13
    Last Post: 10-14-2003, 02:15 PM

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