Thread: unable to save a column element into dynamically memory allocated array

  1. #1
    Registered User
    Join Date
    Jan 2014
    Posts
    10

    unable to save a column element into dynamically memory allocated array

    I am trying to store each value of a column from a text file into an dynamically allocated array, which needs to be globally declared for further usage in the program.
    The input textfile contains the following: 34932\t13854\t13854\t2012-01-07\r 172098\t49418\t53269\t2012-01-07\r
    I have written the following code:
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int main()
    {
        FILE *int_file1;
        int BUF = 1024;
        
        char first_col[BUF],sec_col[BUF],third_col[BUF],fourth_col[BUF];
        
        int index=0,i=0;
    
    
        char *array1=malloc(10*sizeof(char));
            
        int_file1=fopen("test.txt","r");
    
    
        if(int_file1 == NULL)
        {
            perror("Error while opening the file.\n");
        }
        else
        {
            while(fscanf(int_file1,"%[^\t]\t%[^\t]\t%[^\t]\t%[^\n]",first_col,sec_col,third_col,fourth_col) == 4)
            {
    //            printf("%s",first_col);
                array1=realloc(array1,strlen(first_col)+1);
                array1[index]=first_col;
                index++;
            }
         }
        
        fclose(int_file1);    
        
        printf("%s",array1[1]);
    
    
        return 0;
    }
    The commented printf line gives the entire values of the column, which proves that the file is correctly being read.
    But on compiling this program I get both compiler warnings and finally segmentation fault.
    Please suggest where I am getting it wrong.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,907
    If you get compiler errors/warnings you don't understand, it's best to post them -- copy-paste the complete message with line number:
    Code:
    $ make bar
    gcc -Wall -ggdb3 -pedantic -std=gnu99 -O0 -o bar bar.c -lm -lpthread -lrt
    bar.c: In function ‘main’:
    bar.c:30:26: warning: assignment makes integer from pointer without a cast [enabled by default]
    bar.c:37:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
    bar.c:12:17: warning: unused variable ‘i’ [-Wunused-variable]
    array1 is an array of char, so array1[index] is a single char. You are trying to assign first_col to it, but first_col is of type pointer to char. char and char * are not compatible for assignment.

    Also, you try to print array1[1] with %s. Read the printf documentation, %s is for strings (null-terminated char *). array1[1] is a single char, so use %c if you want a single char.

    EDIT:
    1. You should only call fclose if you successfully opened the file. if the open fails, int_file1 is null, and attempting to fclose it will result in undefined behavior.
    2. You should free array1 when you're done with it.
    3. You should use a temp pointer when using realloc. If realloc fails, it returns null. array1 becomes null, you lose the original pointer, so you lose the original data and you can't free the pointer, so you have a memory leak.
    4. If you want to copy a string, try strcpy.
    Last edited by anduril462; 03-03-2014 at 04:32 PM.

  3. #3
    Registered User
    Join Date
    Jan 2014
    Posts
    10
    Apologies for not pasting the compiler errors.

    I expect "172098" as the output of this program and I have considered it to be as a string. Initially, I had run the same program without the use of malloc and realloc and it ran fine. So, is the problem actually with the declaration type??

    My earlier code was:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    
    int main()
    {
        FILE *int_file1;
        int BUF = 1024;
        
        char first_col[BUF],sec_col[BUF],third_col[BUF],fourth_col[BUF];
        
        int index=0,i=0;
    
    
        char *array1[BUF];
            
        int_file1=fopen("test.txt","r");
    
    
        if(int_file1 == NULL)
        {
            perror("Error while opening the file.\n");
        }
        else
        {
            while(fscanf(int_file1,"%[^\t]\t%[^\t]\t%[^\t]\t%[^\n]",first_col,sec_col,third_col,fourth_col) == 4)
            {
    //            printf("%s",first_col);
                array1[index]=malloc(strlen(first_col)+1);
                strcpy(array1[index],first_col);
                index++;
            }
         }
        
        fclose(int_file1);    
    
    
        printf("%s",array1[1]);
    
    
        return 0;
    }

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    In your second code, array1 is an array of strings (it is of type array-of-pointer-to-char). In your first code, array1 is a string (it is of type pointer-to-char).

    When doing dynamic memory, we often exploit the "feature" that arrays can decay to pointers, so our array of strings can decay into pointer-to-pointer-to-char.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,907
    > So, is the problem actually with the declaration type??
    Assuming you're talking about the declaration of array1, then yes.

    Note that in your earlier code, array1 is an array of pointer to char, thus array1[index] is a pointer to char -- which you then assign to the return value of malloc making it point to a sufficiently large group of bytes to store the copy of first_col.

    In your later code, array1 is simply a char *. Thus each element is a single char, which is not sufficient for holding a copy of an entire string (i.e. first_col). You need the following:
    Code:
    char **array1;
    That declares array1 as a pointer to pointer to char. Then you malloc N number of pointers to char, which is how many strings you want to store (how many lines from the file you are reading in). Each item, such as array1[index] is a pointer to char, which you can assign the return value from malloc and then copy into. If you need more lines, you can use realloc on array1.

  6. #6
    Registered User
    Join Date
    Jan 2014
    Posts
    10
    Thanks a lot for the clarification and the patience in explaining the complicated stuff.. Though my program is not yet done but I think I better get some reading on textbooks on pointers before proceeding further. Thanks anyways!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Freeing memory from dynamically allocated array of linked lists
    By NotAProgrammer in forum C Programming
    Replies: 1
    Last Post: 02-26-2013, 09:50 PM
  2. Freeing dynamically allocated memory
    By kkk in forum C Programming
    Replies: 4
    Last Post: 05-30-2011, 12:24 PM
  3. Dynamically allocated memory question
    By caduardo21 in forum C Programming
    Replies: 3
    Last Post: 01-13-2006, 07:37 PM
  4. Dynamically allocated memory
    By ^xor in forum Linux Programming
    Replies: 9
    Last Post: 06-28-2005, 11:42 AM
  5. deleting dynamically allocated memory...
    By heljy in forum C++ Programming
    Replies: 2
    Last Post: 09-08-2002, 11:40 AM

Tags for this Thread