Thread: I need help fixing a warning

  1. #1
    Registered User
    Join Date
    Apr 2006
    Posts
    7

    I need help fixing a warning

    Hi guys,

    I'm a beginner in C and need help with my project for school. Here's my code,

    Code:
    /* -------------------------------------------------------
     * Carpooling
     * -------------------------------------------------------
     * This program will read a file that contains records of
     * people's addresses and will group the records together
     * based on the home zip code and work zip code.
    */
    
    #include <stdio.h>
    #include <assert.h>
    #include <string.h>
    #include <stdlib.h>
    #define MAX_RECORDS 200
    
    typedef struct
    {
        char* last_name;
        char* first_name;
        char* address;
        char* city;
        char* state;
        int home_zip_code;
        int work_zip_code;
    }address_record;
    
    /* Extract the next field from the string passed by the caller.
     * The field is delimited by either a comma or the end of the
     * string */
    char* next_field (char* pStart)
    {
        char* pComma;
        int length;
        char* pField;
    
        pComma =  (char*) strchr(pStart, ',');
        if (pComma == NULL)
        {
            length = strlen(pStart);
        }
        else
        {
            length = pComma - pStart;
        }
    
        pField = (char*) calloc (1, length+1);
        assert (pField != NULL);
        
        strncpy(pField, pStart, length);
        return pField;
    }
    
    /* This function reads address records in the form of comma 
     * separated values from a file specified by the user and
     * sets up a dynamically allocated address record struct for
     * each record.  It puts pointers to the address record structs
     * into the array passed by the caller.
     * The caller specifies length of the array in nr_address.
     * This function sets nr_addresses to the number of array entries
     * actually filled.
    */
    void get_input (address_record* addresses[], int* nr_addresses)
    {
        int k;
        char file_name[1000];
        FILE* pAddressFile;
        address_record* pA;
        
        printf("Input file: ");
        scanf("%999[^\n]", file_name);
        
        pAddressFile = fopen(file_name, "r");
        
        if(pAddressFile == NULL)
        {
            fprintf(stderr, "Error trying to open %s to read file.\n", file_name);
            abort();
        }
    
        for(k = 0; k < MAX_RECORDS; k++)
        {
            addresses[k] = fscanf(pAddressFile, "%s,%s,%s,%s, %s,%d,%d\n",
                                  pA->last_name, pA->first_name, pA->address,
                                  pA->city, pA->state, &pA->home_zip_code,
                                  &pA->work_zip_code);
        }
    }
    
    /* Sort an array of pointers to address records according to
     * home zip code and work zip code.
    */
    void sort_by_zip_code (address_record* rec[], int length)
    {
    
    }
    /* Output blocks of address records that have the same home
     * and work zip code.
    */
    void output_matches(address_record* addresses[], int length)
    {
    
    }
    
    int main()
    {
        int nr_addresses = MAX_RECORDS;
        address_record* addresses[MAX_RECORDS];
        
        get_input(addresses, &nr_addresses);
        /*sort_by_zip_code(addresses, nr_addresses);
        output_matches(addresses, nr_addresses);*/
        return 0;
    }
    Now my problem is that I keep getting this error from the compiler,

    warning: assignment makes pointer from integer without a cast
    It appears to be coming from my for loop in my get_input function or atleast that's what the (Unix) compiler says. Could someone point me in the direction to fix this? Maybe a website or a hint on what I'm doing wrong would be great.

    Any help is appreciated. Thanks!

    -Nterpol

    Edit: Would it be a better idea to get each of the item individually from the file? If so, do I need a loop to do it?
    Last edited by Nterpol; 04-13-2006 at 03:59 PM.

  2. #2
    Registered User
    Join Date
    Nov 2005
    Posts
    95

    Variable type

    You are confusing types.

    In function main , you declare
    Code:
    address_record *addresses[MAX_RECORDS];
    I think you meant. An array and not an array of pointers.
    Code:
    address_record   addresses[MAX_RECORDS];

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    7
    It's what my teacher wants us to do.

  4. #4
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    i look like u are declaring the array of pointers of type struct ... but u are not allocating any space. which will end up with the SEGFAULT.

    Code:
    address_record* addresses[MAX_RECORDS];
    ssharish2005
    Last edited by ssharish2005; 04-13-2006 at 04:22 PM.

  5. #5
    Registered User
    Join Date
    Nov 2005
    Posts
    95

    Weired.

    By doint this :
    Code:
     address_record *addresses[MAX_RECORDS];
    you don't allocate memory to put the data read from file.
    Have you learned about dynamic memory allocation ? like malloc, calloc, realloc ?

  6. #6
    Registered User
    Join Date
    Apr 2006
    Posts
    7
    Yeah,

    So I would use malloc in the get_input function before I start getting the data, correct?

  7. #7
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    yes u are right!!! use somehting like this
    Code:
    address[k] = malloc(sizeof(address_record));
    ssharish2005

  8. #8
    Registered User
    Join Date
    Nov 2005
    Posts
    95

    Dont forget

    Dont forget to use free.

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    7
    Sweet!

    Edit*

    Now I'm confused on how I would go about getting the data. I would use fscanf (could I also use sscanf?) right? Do I store the results from fscanf in another variable that I declare or into the address array? Also, do I need a loop to get all the data from the file? I'm confused on this because when I compile and try to run, I get a Segmentation Fault.
    Last edited by Nterpol; 04-13-2006 at 04:56 PM.

  10. #10
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    fscanf is different from sscanf. sscanf is basicaly used for string manipulation and fscanf for files. what u can do is read a single line of data from the file using the fgets fucntion tokense the string to get the each data field from the string. and place that into the struct data members. u can use sscanf to get each field from the string which u have read from the file using fucntion fgets(tokenising).

    its good to post your updated code

    ssharish

  11. #11
    Registered User
    Join Date
    Apr 2006
    Posts
    7
    Here's the part that I updated, everything else remained the same.

    Code:
    void get_input (address_record* addresses[], int* nr_addresses)
    {
        int k;
        char file_name[1000];
        FILE* pAddressFile;
        address_record* pA;
        
        printf("Input file: ");
        scanf("%999[^\n]", file_name);
        
        pAddressFile = fopen(file_name, "r");
        
        if(pAddressFile == NULL)
        {
            fprintf(stderr, "Error trying to open %s to read file.\n", file_name);
            abort();
        }
        
        for(k = 0; k < MAX_RECORDS; k++)
        {
            addresses[k] = malloc(sizeof(address_record));
        }
    }
    So from here, I would use fgets inside (or outside?) of the loop to get each line from the file and from there use sscanf to get each of the parts of the line and store each of them in the struct members? Also, what do you mean by tokense and tokenising? I don't remember my teacher talking about this.

    Edit*
    One more question. My program has to be able to read 200 records. So would I need to multiply the sizeof in malloc by 200 or is it already taken care of by the address[k] assignment?
    Last edited by Nterpol; 04-13-2006 at 08:06 PM.

  12. #12
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    Also, what do you mean by tokense and tokenising? I don't remember my teacher talking about this.
    its nothing but breaking the string to get the appropriate data

    updated code looks more simililar of the past.
    Code:
    addresses[k] = malloc(sizeof(address_record));
    no memeory allocated for this array. but mentioned before

    ssharish2005

  13. #13
    Registered User
    Join Date
    Apr 2006
    Posts
    7
    Code:
    addresses[k] = (address_record*) malloc (200 * sizeof(address_record));
    How about now?

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    >addresses[k] = fscanf(pAddressFile, "%s,%s,%s,%s, %s,%d,%d\n",
    > pA->last_name, pA->first_name, pA->address,
    > pA->city, pA->state, &pA->home_zip_code,
    > &pA->work_zip_code);

    fscanf returns the number of conversions (an int), not the whole record.
    Your updates to the record are via all those & references you pass as additional parameters.
    And yes, you need to malloc each record as others have pointed out.

    So something like this
    Code:
    void get_input (address_record* addresses[], int* nr_addresses)
    {
        int k = 0;
        // snip filename stuff for brevity, it was reasonably OK
    
        while( k < MAX_RECORDS && !feof(pAddressFile) )
        {
            address_record temp;
            int result;
            result = fscanf(pAddressFile, "%s,%s,%s,%s, %s,%d,%d\n",
                                  temp.last_name, temp.first_name, temp.address,
                                  temp.city, temp.state, &temp.home_zip_code,
                                  &temp.work_zip_code);
             if ( result == 7 ) {
                 addresses[k] = malloc ( sizeof *addresses[k] );
                 *addresses[k] = temp;
                 k++;
             } else {
                 // report bad format?  try and do some error recovery?
             }
        }
        *nr_addresses = k;
    }
    A better way of reading the file, which makes the error recovery so much simpler is
    Code:
    void get_input (address_record* addresses[], int* nr_addresses)
    {
        char buff[BUFSIZ];
        int k = 0;
        // snip filename stuff for brevity, it was reasonably OK
    
        while( k < MAX_RECORDS && fgets(buff, sizeof buff, pAddressFile) )
        {
            address_record temp;
            int result;
            result = sscanf(buff, "%s,%s,%s,%s, %s,%d,%d\n",
                                  temp.last_name, temp.first_name, temp.address,
                                  temp.city, temp.state, &temp.home_zip_code,
                                  &temp.work_zip_code);
             if ( result == 7 ) {
                 addresses[k] = malloc ( sizeof *addresses[k] );
                 *addresses[k] = temp;
                 k++;
             } else {
                 // report bad format?
             }
        }
        *nr_addresses = k;
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 10
    Last Post: 07-10-2008, 03:45 PM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM