Thread: Problem with malloc() and sorting words from text file

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Problem with malloc() and sorting words from text file

    I'm having a problem using malloc() to allocate memory for words from a text file. I need to modify the code below by reading words from the words.txt file and allocate only the amount of memory necessary for each word using malloc().

    Then, I need to sort the words in length order of the word with the longest length words being the lowest index in the array. If two or more words are the same length, they are then sorted by ASCII sequence.

    The code below stores the words from a text file in a 2D array and simply lists the words after they have been read in from the file. It needs to be modified (changed) so that the words are read using the dynamic memory function malloc(). I take the number of words in the data file (in the attached file there are 22 words) and I need to allocate memory to store each word using a dynamic memory array for the words. In addition to that, each word should have memory allocated by allocating only enough memory for each word as it is read from the file using malloc().

    For example: "another" should only require 8 bytes to be stored and "yesterday" would only require 10 bytes to be stored.

    Here is the code that needs to be modified so that the words are read using malloc() to allocate memory and sort the words:


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #define MAXWORDS       500
    #define MAXWORDLENGTH  20
    
    int main(int argc, char *argv[]) {
        char words[MAXWORDS][MAXWORDLENGTH];
        int i;
        if (argc == 2)
        {
            int iNumWords = readwords(argv[1], words);
            for (i=0; i<iNumWords; i++)
                printf ("%s\n", words[i]);
            printf("\nThe total number of words in %s is %d", argv[1],  
            iNumWords);
        }
    
        system("PAUSE");
        return 0;
    }
    
    /* Function to read words into a two-dimensional array */
    
    int readwords(char *filename, char words[][MAXWORDLENGTH])
    {
       int   iCount = 0;
       FILE *fp = fopen(filename, "r");   // Open file for reading
    
       while (!feof(fp))
          fgets(words[iCount++], MAXWORDLENGTH, fp);
    
       fclose(fp);
       return iCount-1;
    }
    I need to modify this code so that each word of the text file is allocated only the amount of memory necessary for each word using the malloc() function. After that, the words need to be sorted in order of length. I'm not quite sure how to do that but I'm thinking I need to use the qsort() function but I would like confirmation of that from someone who knows for sure.

    Any help, advice or suggestions would be greatly appreciated.

    Thanks. I have included an attachment of the "words.txt" file for reference.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Consider using a linked list. Or, if you don't want that, an array of character pointers. There's a tutorial for linked lists on the site, as well as a few thousand posts on them.
    Code:
    repead until done:
        read a word into a buffer
        get the length of the word
        malloc that length + 1 for the null
        copy the word into it
        stick the word in your linked list or array
    Then sort it and do whatever else it is. Post your attempt when you get stuck. Be sure to include any errors or warnings your compiler generates.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    I forgot to include that I need some kind of pointer to each word so that I can allocate memory for each word.

    It should be something like:

    char *ptd;

    ptd = (char *)malloc(length of word * sizeof(char));

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Yeah, so? Go fo it. We're not here to do your work for you. I've already given you the basics of what you need.

    Oh, and on an aside, don't typecast the return for malloc. It's not needed.

    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656

  6. #6
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    I'm going to try a few things with this program. I'm busy with other things too so it may be a while but I'll post my failed attempts later tonight if I run into problems.

    Thanks Quzah.

  7. #7
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    Thanks for the posts from Quzah and Salem.

    Salem, I read the post you linked to. Basically, taking the malloc of strlen(word) + 1 will give you the amount of memory necessary for that particular word.

    I have one other question, how can I determine the number of words in a data file, assuming that there is only one word on each line?

  8. #8
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>how can I determine the number of words in a data file, assuming that there is only one word on each line?<<
    With a little thought, I'm sure you can work that one out....!
    Read a line at a time, incrementing a counter as you go.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  9. #9
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    ok I've posted my attempt at the solution for this program to allocate memory for each word in the data text file using malloc() but my program is crashing somewhere after the program determines the number of words in the text file. Here is my code (excluding the part where the words are sorted because I haven't gotten that far yet):

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXWORDLENGTH  30
    
    int main(int argc, char *argv[]) {
        FILE *fp;
        int iNumWords = 0;
        int i;
        char word[MAXWORDLENGTH];
        char *ptr[iNumWords];
    
        if (argc == 2) {
           fp = fopen(argv[1], "r");
    
           while (!feof(fp)) {
                 fgets(word, MAXWORDLENGTH, fp);
                 iNumWords = iNumWords + 1;
           }
    
           fseek(fp, 0L, SEEK_SET);
           printf("\nThe total number of words in %s is %d\n\n", argv[1],   
           iNumWords - 1);
    
           for (i = 0; i < iNumWords; i++) {
               fgets(word, MAXWORDLENGTH, fp);
               ptr[i] = (char *)malloc(strlen(word) + 1);
               strcpy(ptr[i], word);
           }
    
           fseek(fp, 0L, SEEK_SET);
    
           for(i = 0; i < iNumWords; i++) {
                 puts(ptr[i]);
                 free(ptr[i]);
           }
    
        }
    
        fclose(fp);
    
        system("PAUSE");
        return 0;
    }
    If anyone can help me figure out why the program is crashing, that would be great. I think this is close to being correct.

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    int iNumWords = 0;
    int i;
    char word[MAXWORDLENGTH];
    char *ptr[iNumWords];
    You're making an array whose size is zero. For starters, that'll be a problem.

    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    Registered User
    Join Date
    Nov 2004
    Posts
    73

    Re:

    We've got the malloc() part working I think but now the program is crashing for the sort part where I need to sort the words from the text file (one word on a line) in length order. Here is the code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXWORDLENGTH  30
    
    int compare(const void *a, const void *b);
    
    int main(int argc, char *argv[]) {
        FILE *fp;
        int iNumWords = 0;
        int i;
        char word[MAXWORDLENGTH];
        char *ptr[22];
        if (argc == 2) {
           fp = fopen(argv[1], "r");
    
           while (!feof(fp)) {
                 fgets(word, MAXWORDLENGTH, fp);
                 iNumWords = iNumWords + 1;
           }
           fseek(fp, 0L, SEEK_SET);
           printf("\nThe total number of words in %s is %d\n\n", argv[1], iNumWords - 1);
    
           for (i = 0; i < iNumWords - 1; i++) {
               fgets(word, MAXWORDLENGTH, fp);
               ptr[i] = (char *)malloc(strlen(word) + 1);
               strcpy(ptr[i], word);
           }
    
           fseek(fp, 0L, SEEK_SET);
    
           for (i = 0; i < iNumWords - 1; i++) {
               fgets(word, MAXWORDLENGTH, fp);
               qsort(word, iNumWords - 1, MAXWORDLENGTH, compare);
           }
    
           fseek(fp, 0L, SEEK_SET);
    
           for(i = 0; i < iNumWords - 1; i++) {
                 puts(ptr[i]);
                 free(ptr[i]);
           }
        }
    
        fclose(fp);
    
        system("PAUSE");
        return 0;
    }
    
    int compare(const void *a, const void *b) {
        int rc;
    
        if (strlen(a) < strlen(b)) {
           rc = -1;
        }
    
        else if (strlen(a) == strlen(b)) {
             rc = 0;
        }
    
        else {
             rc = 1;
        }
    
        return rc;
    }
    How can this problem be fixed? The logic and syntax looks correct but the program is crashing again and I believe it is happening during the sorting part of the program.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > while (!feof(fp)) {
    To avoid bogus "off-by-one", read this FAQ
    http://faq.cprogramming.com/cgi-bin/...&id=1043284351

    > char *ptr[22];
    This limits you to 22 words

    If you really want all the words, and not care about it, do this
    Code:
    char **ptr;
    // now work out your word count as you do
    ptr = malloc( iNumWords * sizeof *ptr );
    Don't forget to free(ptr) when you're done freeing each ptr[i]

    > ptr[i] = (char *)malloc(strlen(word) + 1);
    DONT cast malloc in 'C' - see the FAQ

    > qsort(word, iNumWords - 1, MAXWORDLENGTH, compare);
    What exactly are you hoping to achieve here?
    You seem to be sorting all the chars in a line, but not doing anything with the result.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with linked list sorting function
    By Jaggid1x in forum C Programming
    Replies: 6
    Last Post: 06-02-2009, 02:14 AM
  2. can any1 plz make this assignment
    By jean in forum C Programming
    Replies: 17
    Last Post: 05-13-2009, 09:19 PM
  3. ordered linked list
    By redmondtab in forum C Programming
    Replies: 48
    Last Post: 10-22-2006, 06:09 AM
  4. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM
  5. Sorting a Union
    By andy in forum C Programming
    Replies: 4
    Last Post: 11-21-2001, 10:12 AM