Thread: Double Array of Pointers (unknown length)

  1. #1
    Registered User
    Join Date
    Aug 2015
    Posts
    2

    Double Array of Pointers (unknown length)

    Hi there,

    this is my first post as I like to try and work things out wherever possible without bothering other people, but I'm completely at a wit's end with this one.

    I am trying to read in a 2D array of unknown length from a file into "myarray" using malloc and realloc as I saw this method recommended elsewhere. The data to be read in is known to be 4 columns but the number of rows is not known.

    So far I manage to allocate 5000 pointers (I think), each pointing to 4 doubles.
    Code:
        int datasize=0;
        int nrows=5000;
        float** myarray=(double**)malloc(nrows*sizeof(double*));
            for(i=0;i<=nrows;i++)
            {
               myarray[i]=(double*)malloc(4*sizeof(double));
            }
    When this runs out, I attempt to add another 1000 rows with realloc.

    Code:
    if(datasize==nrows)
                    {
                        nrows+=1000;
                        myarray=(double**)realloc(myarray,nrows*sizeof(double*));
                        for(j=0;j<nrows;j++)
                            {
                            myarray[j]=(double*)realloc(myarray[j],4*sizeof(double));
                            printf("%d\n",j); //this is just to see how far through the programme it gets
                            }
                    }
    When I run this, I get the pop-up "Data Fitting.exe has stopped working" at one of three points. Either at the first attempt of memory allocation i.e. j=0, or when j=5074 or j=5110. There is never any variation from this. Running a debugger shows there is a segmentation fault (SIGSEGV). I understand this has something to do with memory but I do not really know exactly what it means.

    I am new to C so sorry if the answer is very simple. I would be extremely grateful for any insight as I have spent a long long time on this.

    Here is my whole code for reference.

    Code:
    /////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////dynamic version////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    int main()
    {
        FILE *myfile;
        int i=0;
        int j=0;
        int c=0;
        int datasize=0;
        int nrows=5000;
        int elements=0;
        float x,y,sx,sy;
        double a, b, SigA, SigB;
        char fname[100]={0};
        double** myarray=(double**)malloc(nrows*sizeof(double*));
            for(i=0;i<=nrows;i++)
            {
               myarray[i]=(double*)malloc(4*sizeof(double));
            }
    //1) Ask user to input filename from keyboard
        printf("Enter a file path:\n");
        scanf("%s",fname);
        if (fname[0]=='\"')         //removes quotations automatically inserted when copying a file path from windows explorer
        {
            for ( c = 0 ; c < 99 ; c++ )
            {
                fname[c] = fname[c+1];
            }
            for ( c = 0 ; c < 100 ; c++ )
            {
                if (fname[c]=='\"')
                {
                    fname[c]=0;
                }
            }
        }
    //2) Call function to read in data from file (check the file was actually found and read in correctly)
    
        myfile=fopen(fname,"r");
        if (myfile!=NULL)
            {
                for (i=0; !feof(myfile); i++)
                {
                    fscanf(myfile,"%f %f %f %f",&x,&y,&sx,&sy);
                    myarray[i][0]=x;
                    myarray[i][1]=y;
                    myarray[i][2]=sx;
                    myarray[i][3]=sy;
                    datasize++;
                    if(datasize==nrows)
                    {
                        nrows+=1000;
                        myarray=(double**)realloc(myarray,nrows*sizeof(double*));
                        for(j=0;j<nrows;j++)
                            {
                            myarray[j]=(double*)realloc(myarray[j],4*sizeof(double));
                            printf("%d\n",j); //this is just to see how far through the programme it gets
                            }
                    }
    
    
                }
                elements = i-1;
                fclose(myfile);
            }
        else
            {
            printf("File does not exist");
            }
    //3) Call the function to calculate the coefficients
        double sumyoversqsig=0;
        double sumsqxoversqsig=0;
        double sumxyoversqsig=0;
        double sumoneoversqsig=0;
        double sumxoversqsig=0;
        for (i=0; i<(elements); i++)
        {
        sumyoversqsig+=((myarray[i][1])/pow(myarray[i][3],2));
        sumsqxoversqsig+=((pow(myarray[i][0],2))/pow(myarray[i][3],2));
        sumxoversqsig+= ((myarray[i][0])/pow(myarray[i][3],2));
        sumxyoversqsig+=(((myarray[i][0])*(myarray[i][1]))/pow(myarray[i][3],2));
        sumoneoversqsig+=(1/pow(myarray[i][3],2));
        }
    printf("datasize = %d \nnrows = %d",datasize,nrows);
    printf("%f\n%f\n%f\n%f\n%f\n",sumyoversqsig, sumsqxoversqsig, sumxoversqsig, sumxyoversqsig, sumoneoversqsig);
        a=((sumyoversqsig*sumsqxoversqsig)-(sumxoversqsig*sumxyoversqsig))/((sumoneoversqsig*sumsqxoversqsig)-pow(sumxoversqsig,2));
        b=((sumoneoversqsig*sumxyoversqsig)-(sumyoversqsig*sumxoversqsig))/((sumoneoversqsig*sumsqxoversqsig)-pow(sumxoversqsig,2));
        SigA=sqrt((sumsqxoversqsig)/((sumoneoversqsig*sumsqxoversqsig)-pow(sumxoversqsig,2)));
        SigB=sqrt((sumoneoversqsig)/((sumoneoversqsig*sumsqxoversqsig)-pow(sumxoversqsig,2)));
    //4) Display coefficients on the screen. ;
        printf("Coefficient a =%le\nCoefficient b =%le\nSigma a       =%le\nSigma b       =%le\n",a,b,SigA,SigB);
        free(myarray);
        return 0;
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This is wrong:
    Code:
    float** myarray=(double**)malloc(nrows*sizeof(double*));
    Do you want to work with float objects or double objects? They are not the same. If you want pointers to double, then write:
    Code:
    double** myarray = malloc(nrows * sizeof(myarray[0]));
    This has an off-by-one error:
    Code:
    for(i=0;i<=nrows;i++)
    You have nrows, so you should use strict less than:
    Code:
    for (i = 0; i < nrows; i++)
    This is fine:
    Code:
    myarray[i]=(double*)malloc(4*sizeof(double));
    But it would be better to write:
    Code:
    myarray[i] = malloc(4 * sizeof(myarray[i][0]));
    Then again, if you know for sure that the inner arrays will always have 4 doubles, why not just allocate once for a pointer to an array of 4 doubles?
    Code:
    double (*myarray)[4] = malloc(nrows * sizeof(myarray[0]));
    This way, when you want to realloc, you can just write:
    Code:
    double (*temp)[4] = realloc(myarray, nrows * sizeof(temp[0]));
    if (temp)
    {
        myarray = temp;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2015
    Posts
    2
    Thank you so much for your help. I made the first two corrections but the problem persists. I will perhaps re-write the array section improvements tomorrow and hope that works

  4. #4
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I don't know if it was mentioned yet but your code would be very simple if you just used a 1d array but indexed it like a 2d one, via :
    Code:
    double *data = malloc( ( initial_rows * initial_cols ) * sizeof( *data ) );
    
    for ( int i = 0; i < num_rows; ++i )
    {
        for ( int j = 0; j < num_cols; ++j )
        {
            data[ i * num_rows + j ] = /* ... */;
        }
    }
    This way, reallocation would be very simple and so would free()'ing the data as all it would require is a single call to free().

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How do I save a returned of unknown length?
    By Philip Rego in forum C Programming
    Replies: 3
    Last Post: 09-15-2014, 07:02 PM
  2. Reading in file of unknown length
    By zone159 in forum C Programming
    Replies: 2
    Last Post: 11-14-2012, 02:07 PM
  3. Reading from a textfile with unknown length?
    By chickenlittle in forum C++ Programming
    Replies: 4
    Last Post: 09-10-2011, 11:59 PM
  4. Pointers in a function, sizeof doesn't get array length
    By ulillillia in forum C Programming
    Replies: 4
    Last Post: 01-27-2011, 11:36 AM
  5. reading a file of unknown length
    By the bassinvader in forum C Programming
    Replies: 2
    Last Post: 07-12-2006, 03:06 PM

Tags for this Thread