Thread: Help with Malloc() function

  1. #1
    Registered User
    Join Date
    Aug 2007
    Posts
    33

    Help with Malloc() function

    Hi,

    I want to be able to store a group of words from a file to an array. I try using the malloc() function to allocate space for all the word in a file, but i'm not sure on how to use the malloc function.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define STRSIZE 1000
    
    int main(void)
    {
      FILE *pf;
      char *space;
      char str[STRSIZE];
      int n;
      int pos = 0;
    
      pf = fopen("story.txt","r");
    
      if(!pf)
      {
        printf("Can't open the file\n");
        return 0;
      }
    
      while(fscanf(pf,"%s",str) == 1)
      {
        printf("str is: %s\n",str);  //testing
        pos++;
      }
      
      space = malloc(n*sizeof(char)); 
      printf("space is: %s\n", space);  //testing
      
      fclose(pf);
      return 0;
    
    }

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Where does n get a value? Could you post a snippet of the input file? Doesn't the while loop consume the entire file before you get to malloc?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User
    Join Date
    Aug 2007
    Posts
    33
    Quote Originally Posted by Dave_Sinkula View Post
    Where does n get a value? Could you post a snippet of the input file? Doesn't the while loop consume the entire file before you get to malloc?
    n was just a variable that i was testing with, and it is not currently in used. The file story.txt contains: "Today is cold, yesterday was hot"

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    space = malloc(n*sizeof(char));
    and it is not currently in used
    You are wrong - it is in use, but it is not initialized
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    Registered User
    Join Date
    Jul 2007
    Posts
    151
    The codes dont make sense. Whether I did not understand , or you have a defect with the algorithm.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    sizeof(char) is always 1, so you can leave it out of the expression if you like.

    Looking at your code, I'm guessing that you want to read the file through first to see how many words are in it, and then allocate enough memory to hold each word, and then read each word from the file again. (If you want to get each line instead of each word, use fgets().) Is that right?

    As I have outlined above, you'd need to use the rewind() function to reset the FILE pointer to the beginning of the file between the loops.

    But there's a better way to do it. The function realloc() allows you to resize a memory block. So you can allocate as you go. Read a line from the file, allocate space for it, repeat until the get to the end of the file.

    No matter which method you use, you need to allocate memory properly. You need an array of pointers, with enough elements in the array to point to each string, which also should be dynamically allocated. Or you could do this, I suppose:
    Code:
    char *lines[STRSIZE];
    
    ... = realloc(lines, sizeof(*lines) * n);
    strcpy(lines[n-1], line);
    Search around the board, and I'm sure you'll find several examples of dynamically allocating arrays of strings.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Aug 2007
    Posts
    33
    Quote Originally Posted by dwks View Post
    sizeof(char) is always 1, so you can leave it out of the expression if you like.

    Looking at your code, I'm guessing that you want to read the file through first to see how many words are in it, and then allocate enough memory to hold each word, and then read each word from the file again. (If you want to get each line instead of each word, use fgets().) Is that right?
    Yes, I do want to read through the file to see how many words there are, and then allocate the memory according to the number of words there are in the file. I'm just having trouble allocating memory for a file.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Could you post your current code?

    As the previous bit of code you posted is severly broken, you have hopefully fixed the bugs pointed out above, so you probably should be closer to a solution now. If you haven't fixed the bugs pointed out above, please re-read the thread and make corrections, THEN post the code.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Aug 2007
    Posts
    33
    Quote Originally Posted by matsp View Post
    Could you post your current code?

    As the previous bit of code you posted is severly broken, you have hopefully fixed the bugs pointed out above, so you probably should be closer to a solution now. If you haven't fixed the bugs pointed out above, please re-read the thread and make corrections, THEN post the code.

    --
    Mats
    Yes, the code is below:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define STRSIZE 1000
    
    int main(void)
    {
      FILE *pf;
      char *space;
      char str[STRSIZE];
      int n;
      int pos = 0;
    
      pf = fopen("story.txt","r");
    
      if(!pf)
      {
        printf("Can't open the file\n");
        return 0;
      }
    
      space = (char*) malloc(pf);
      printf("space is: %d\n", space);
    
      free(space);
      fclose(pf);
      return 0;
    
    }
    I'm just having difficulty allocating memory, malloc(), for an input file, and i'm not sure how to test if i'm doing it right or not.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by xp5 View Post
    Yes, the code is below:

    Code:
    ...
      FILE *pf;
      char *space;
    ...
      pf = fopen("story.txt","r");
    ...
      space = (char*) malloc(pf);
    ...
    }
    What do you expect this code to do, because as far as I'm concerned, this shouldn't even compile. pf is a pointer to a file, and whilst this CAN be converted to an unsigned integer of type size_t with a case, it's almost certainly not the right argument for malloc - with or without cast. A memory address for a FILE object is nearly a random number, so you are asking for some random amount of memory. For example, the numeric value of the first file opened in my Microsoft Visual Studio environment has the value 0x49f420 - that means about 4.5MB. Which is a large amount of memory to ask for. If you have a different environment, you may find that the numeric value of pf is out of range for malloc alltogether.

    Second, you should never cast the result of malloc().

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You had the right idea in your original code, passing the number of words to malloc(). Except you used the uninitialized variable n instead of the variable pos, which you incremented to count the number of words in the file.

    But stop for a moment and think about what you're allocating. If you were to code this program with a limit on the number of words in a file, say WORD_COUNT, as well as a limit on the length of each word, say WORD_LENGTH, then your declaration might look something like this:
    Code:
    char word[WORD_COUNT][WORD_LENGTH];
    You'd read words into that array as follows:
    Code:
      while(fscanf(pf,"&#37;s",str) == 1)
      {
        strcpy(word[pos++], str);
      }
    Now, what if you were to dynamically allocate memory for word[][] instead of using fixed limits? First let's get rid of the WORD_COUNT limit, because it seems more restrictive. You end up with a declaration like this:
    Code:
    char *(word[WORD_LENGTH]);
    Now, assuming that you know the number of words in the file, you can allocate memory for that array with
    Code:
    word = malloc(sizeof(*word) * words);
    Then you'd read the file in the same way as you did for the word[WORD_COUNT][WORD_LENGTH] array.

    Side note: malloc()
    The common idiom for malloc() is
    Code:
    p = malloc(sizeof(*p));
    or
    Code:
    p = malloc(sizeof *p);
    because it works no matter what type p is (as long as p is a non-void pointer).

    The parentheses for sizeof() can be left out if you're taking the sizeof() a variable rather than a type such as int.

    In this case, sizeof(*word) is equivalent to sizeof(char []) or sizeof(char *).

    You could also eliminate WORD_LENGTH instead:
    Code:
    char *word[WORD_COUNT];
    or
    Code:
    char *(word[WORD_COUNT]);
    You wouldn't need to allocate memory before you read from the file, but your file reading loop would have to look something like
    Code:
      while(fscanf(pf,"%s",str) == 1)
      {
        word[pos] = malloc(strlen(str) + 1);  /* +1 for NULL */
        strcpy(word[pos], str);
        pos ++;
      }
    And then you'd need to free() the memory once you were done with it, of course.

    But can we eliminate both restrictions on the dimensions? Will a declaration like this work?
    Code:
    char **word;
    Yes, of course it will. But you'll need to call malloc() in two places, to allocate memory for the array of pointers, which will contain the same number of elements as the file contains words; and you'll also need to allocate memory for each word.

    I won't post the code for this final version; you ought to be able to figure it out yourself from my previous examples. If you can't, just say so.

    Finally, what about realloc()? All of the above assumes that you know how many words are in the file, which you do not. I don't feel like posting a realloc() example, but you can search around for one. Here's a really old thread of mine that demonstrates this sort of thing: http://cboard.cprogramming.com/showt...hlight=realloc
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #12
    Registered User
    Join Date
    Aug 2007
    Posts
    33
    Quote Originally Posted by dwks View Post
    You had the right idea in your original code, passing the number of words to malloc(). Except you used the uninitialized variable n instead of the variable pos, which you incremented to count the number of words in the file.

    But stop for a moment and think about what you're allocating. If you were to code this program with a limit on the number of words in a file, say WORD_COUNT, as well as a limit on the length of each word, say WORD_LENGTH, then your declaration might look something like this:
    Code:
    char word[WORD_COUNT][WORD_LENGTH];
    You'd read words into that array as follows:
    Code:
      while(fscanf(pf,"%s",str) == 1)
      {
        strcpy(word[pos++], str);
      }
    Now, what if you were to dynamically allocate memory for word[][] instead of using fixed limits? First let's get rid of the WORD_COUNT limit, because it seems more restrictive. You end up with a declaration like this:
    Code:
    char *(word[WORD_LENGTH]);
    Now, assuming that you know the number of words in the file, you can allocate memory for that array with
    Code:
    word = malloc(sizeof(*word) * words);
    Then you'd read the file in the same way as you did for the word[WORD_COUNT][WORD_LENGTH] array.

    Side note: malloc()
    The common idiom for malloc() is
    Code:
    p = malloc(sizeof(*p));
    or
    Code:
    p = malloc(sizeof *p);
    because it works no matter what type p is (as long as p is a non-void pointer).

    The parentheses for sizeof() can be left out if you're taking the sizeof() a variable rather than a type such as int.

    In this case, sizeof(*word) is equivalent to sizeof(char []) or sizeof(char *).

    You could also eliminate WORD_LENGTH instead:
    Code:
    char *word[WORD_COUNT];
    or
    Code:
    char *(word[WORD_COUNT]);
    You wouldn't need to allocate memory before you read from the file, but your file reading loop would have to look something like
    Code:
      while(fscanf(pf,"%s",str) == 1)
      {
        word[pos] = malloc(strlen(str) + 1);  /* +1 for NULL */
        strcpy(word[pos], str);
        pos ++;
      }
    And then you'd need to free() the memory once you were done with it, of course.

    But can we eliminate both restrictions on the dimensions? Will a declaration like this work?
    Code:
    char **word;
    Yes, of course it will. But you'll need to call malloc() in two places, to allocate memory for the array of pointers, which will contain the same number of elements as the file contains words; and you'll also need to allocate memory for each word.

    I won't post the code for this final version; you ought to be able to figure it out yourself from my previous examples. If you can't, just say so.

    Finally, what about realloc()? All of the above assumes that you know how many words are in the file, which you do not. I don't feel like posting a realloc() example, but you can search around for one. Here's a really old thread of mine that demonstrates this sort of thing: http://cboard.cprogramming.com/showt...hlight=realloc
    Thank you very much for the in depth explanation...that's exactly what I needed!

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Oops, this
    You could also eliminate WORD_LENGTH instead:
    Code:
    char *word[WORD_COUNT];
    or
    Code:
    char *(word[WORD_COUNT]);
    should have been
    You could also eliminate WORD_LENGTH instead:
    Code:
    char *word[WORD_COUNT];
    or
    Code:
    char (*word)[WORD_COUNT];
    I'm glad it helped you understand dynamic memory allocation. If you have any other questions, just ask.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  2. C++ compilation issues
    By Rupan in forum C++ Programming
    Replies: 1
    Last Post: 08-22-2005, 05:45 AM
  3. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  4. malloc & cover function
    By Max in forum C Programming
    Replies: 4
    Last Post: 10-04-2002, 08:51 AM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM