Thread: Reading a file and storing it as a 2d Array.

  1. #1
    Registered User
    Join Date
    Aug 2012
    Posts
    6

    Reading a file and storing it as a 2d Array.

    Hi everyone,

    I have been given the assignment to create a program to find the the least squares method of fitting a straight line function to one of two data sets given to me in a txt format. the file has an unknown number of data points. The format of the data file is x, y, error x, error y. The data should be read in from the file and then the various sums calculated so that the a and b coefficients and their associated error can be found I have to read the data into an array before performing the sums as it will demonstrate that i know how to use multidimensional arrays(well that's the idea). Finally, i have to make the program modular so that there is a separate function for reading in the data and a function for calculating the least squares coefficients.

    As yet i have searched the internet and my notes and i can open the the file and with fgets and fputs print to screen but i think as this works with strings i cant see how i can then get the information and put it into a 2d array from there. Unfortunately my file will not print at all now that i have tried to put it into a 2d array.

    the source file looks a bit like:



    13.079 0.051658 0.77359 0.00052980
    14.162 0.051750 0.0097982 0.0019695
    15.888 0.054027 0.80159 0.0019485
    16.191 0.054512 0.62303 8.9929e-05
    17.339 0.055797 0.99587 0.00041386
    18.784 0.056146 0.25421 0.0016562
    19.967 0.056846 0.60045 0.00038078
    20.437 0.058294 0.61663 0.00014638
    21.397 0.058011 0.026190 0.00032348
    22.998 0.059799 0.26090 0.00092712
    23.456 0.059883 0.64564 0.0016402
    24.070 0.060772 0.83006 0.0017486
    25.109 0.060415 0.80091 0.00093706
    26.887 0.061940 0.80918 6.3588e-05
    27.527 0.063505 0.86446 0.0012275
    28.860 0.064270 0.31924 0.0014887
    29.616 0.063735 0.63400 0.0016803
    30.430 0.065634 0.64624 0.00025035
    31.863 0.067435 0.20427 0.00051878
    32.326 0.067050 0.0066200 0.00017732
    33.043 0.068377 0.71793 0.0017101

    and my code at the moment is:
    Code:
    #include <stdio.h>int main(int argc,char ** argv)
    {
        int i, j;
        int nrows;
        int ncolumns;
        char filename[20];
        FILE * userfile = 0;
        printf("Please Enter The Name Of The File You Would Like To Fetch\n");
        scanf("%s", filename);
        userfile = fopen(filename, "r");
    
    
    
    
        char buffer[nrows][ncolumns];
    
    
        if (userfile)
        {
            printf("file opened\n");
            while(fgets(buffer, 200, userfile)) { printf("%s", buffer);}
            fputs(buffer, userfile);
            for (i=0;i<nrows;i++)
            {
                for(j = 0; j < ncolumns; j++)
                    {
                        buffer[i][j]=userfile;
                        printf("buffer: %s",buffer);
                    }
            }
    
    
            fclose (userfile);
        }
        else
        {
            printf("userfile not opened");
        }
        return 0;
    }

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You have several problems in the following snippet:
    Code:
    int main(int argc,char ** argv)
    {
        int i, j;
        int nrows;
        int ncolumns;
        char filename[20];
        FILE * userfile = 0;
        printf("Please Enter The Name Of The File You Would Like To Fetch\n");
        scanf("%s", filename);
        userfile = fopen(filename, "r");
     
        char buffer[nrows][ncolumns];
    First you should be very careful when using such a small size for your file name. File names are no longer limited to such small sizes. Second you should never use scanf() to retrieve a string without using the width specifier to limit the number of characters that scanf() will attempt to read. Also note scanf() will not accept strings with spaces in them, which can happen with file names.

    Next you should always check to insure that your file opened correctly.

    Lastly, what compiler are you using? Using VLA (Variable Length Arrays) is only allowed when your compiler supports the C99 or newer C standard. Normally you must use compile time constants when defining the size of an array. But most important is the fact that you have never assigned a value to nrows or ncolumns. Therefore you have now idea how large, or small these variables are.

    Jim

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    • You do not initialize the size of the array,ncolumns and nrows!
    • Also this line
      Code:
      buffer[i][j]=userfile;
      does not seem ok to me.A seg fault will probably result.
    • Code:
      printf("%s", buffer);
      buffer is not a string.If you wish to print an element of it you have to access the cell as you do below with for loops.Actually if you do that you always going to read from the start of the array.If that is want you want,ok,but to me it is not clear.This is more clear in my opinion
      Code:
      printf("buffer: %c",buffer[i][j]);
      This will give you one digit of the number!
    • Code:
       fputs(buffer, userfile);
      Why writting again in the file?No need do.Actually you opened the file with "r" ,so read-only state.
    • did you get rid of this warning?
      main.c:22: warning: passing argument 1 of 'fgets' from incompatible pointer type

  4. #4
    Registered User
    Join Date
    Aug 2012
    Posts
    6
    Thanks Jim, don't know what i should use instead of scanf(), and i will expand the filename char limit. If i have it right i am using code blocks and a GNU GCC compiler (really new to programming sorry for my ineptitude) when it came to nrows and ncolumns i want it to take its values from the file and adjust to the data size in the file as i have to do this with the above file and a much larger on, but thinking on it i dont need the ncolumns to be variable so i can state that as 4 but that does not help with the problem of getting the no. of rows from the file.

    i thought that the
    Code:
    else{}
    would tell me if the file did not open correctly?

  5. #5
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    The else really tells you that.Instead of scanf you may use fgets.

  6. #6
    Registered User
    Join Date
    Aug 2012
    Posts
    6
    currently i get no output and it crashes. std10093 do i just leave it as
    Code:
     char buffer [][4]
    for the four columns and variable rows? and not have
    Code:
    buffer[i][j]=userfile;
    but have
    Code:
    buffer[nrows][ncolumns]=userfile;
    Last edited by zimbomac; 08-24-2012 at 07:06 AM. Reason: thanks for the tip :)

  7. #7
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Code:
     buffer[nrows][ncolumns]=userfile;
    does what?I think that a spot where your code might crashes is here.

    If i remember well the first dimension must be declared,and the second one is optional.Does the compiler lets you do this?

    Tip:[\code] should be with /

  8. #8
    Registered User
    Join Date
    Aug 2012
    Posts
    6
    would
    Code:
     if (userfile != NULL)    {
            printf("file opened/n");
        }
    else 
        {
            printf("file not opened/n");
        }
    be better and tell me if it had opened then?

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    when it came to nrows and ncolumns i want it to take its values from the file and adjust to the data size in the file as i have to do this with the above file and a much larger on, but thinking on it i dont need the ncolumns to be variable so i can state that as 4 but that does not help with the problem of getting the no. of rows from the file.
    I suggest you think about using dynamic memory, malloc/free, to allocate memory for your array. To do this you will need to first determine the number of entries to malloc, or use realloc() to add elements as you read them.

    Jim

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    There are two common ways to read in all the data from a file:

    1) Use fgets(), in a while loop. When NULL is returned, the loop should end.

    2) Use fscanf(), in a while loop. When the count of objects stored is less than it should be, the loop should end.

    Here's a simple example program:

    Code:
    #include <stdio.h>
    #include <time.h>
    
    int main(void) {
       int i;
       char a[7][128];
       time_t start, stop;
       FILE *fp=fopen("Edelweiss.txt", "r");
       if(!fp) {printf("\nError: unable to open the file.\n"); return 1;}
        start = time(NULL);
    
       i=0;
    
       while((fgets(a[i],sizeof(a[i]), fp)) != NULL) {
          fputs(a[i++],stdout);
          //getchar();
       }
    /*
       //shows the use of fscanf() reading a line until it reaches a 
       //newline, and reading all the data in a file, while it can store at 
       //least one object.
       while((fscanf(fp, " %[^\n]s",a[i])) > 0) {
          printf("%s\n",a[i++]);
          //getchar();
       }
    */
       fclose(fp);
       stop = time(NULL);
       if(stop-start > 10) { 
          printf("\nYour 10 seconds are up! Ending program in 4 seconds!\n");
          _sleep(4);
       }else {
          printf("\nThat was fast! The program will end when you hit enter\n");
          getchar();
       }
       return 0;
    }
    /*
    In a file named "Edelweiss.txt, put this into the programs directory before you run it:
          "Edelweiss, edelweiss, every morning you greet me.
          Small and white, clean and bright, you look happy to meet me.
          Blossom of snow may you bloom and grow, bloom and grow forever.
          Edelweiss, edelweiss, bless my homeland forever.
          Small and white, clean and bright, you look happy to meet me
          Blossom of snow, may you bloom and grow, bloom and grow forever.
          Edelweiss, edelweiss, bless my homeland forever."
    */
    If you use fgets(), you have the data in a string. You still need to use sscanf() to store the numbers out of the string, into your array. If the data is STRICTLY formatted - not user entered (which will always have errors), then fscanf() is perfectly fine to store the data into the array.
    Last edited by Adak; 08-24-2012 at 07:15 AM.

  11. #11
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Quote Originally Posted by zimbomac View Post
    would
    Code:
     if (userfile != NULL)    {
            printf("file opened/n");
        }
    else 
        {
            printf("file not opened/n");
        }
    be better and tell me if it had opened then?
    It's ok

    Quote Originally Posted by jimblumberg View Post
    I suggest you think about using dynamic memory, malloc/free, to allocate memory for your array. To do this you will need to first determine the number of entries to malloc, or use realloc() to add elements as you read them.

    Jim
    I agree with jim.And then do not forget to use function free!!! (in order to de-allocate memory)

  12. #12
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Quote Originally Posted by zimbomac View Post
    would
    Code:
     if (userfile != NULL)    {
            printf("file opened/n");
        }
    else 
        {
            printf("file not opened/n");
        }
    be better and tell me if it had opened then?
    I myself would check right after trying to open the file, and if the opening failed immediately exit the program. If your file didn't open correctly there is really no reason to continue the program. But if the question is if you should use NULL in your check, then my recommendation is yes.

    Jim

  13. #13
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Isn't your main problem that you are supposed to be able to accept files of arbitrary size, meaning you can not know the value of 'nrows' in your array until after you have attempted to read the file, at which point it's to late.

    You can create a function that finds the row count in the file, then from that you can allocate an array with nrows that the file can be read into.

  14. #14
    Registered User
    Join Date
    Aug 2012
    Posts
    6
    thats what i was thinking subsonics, but again i would need to surly read the file to find the number of rows?

  15. #15
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by zimbomac View Post
    thats what i was thinking subsonics, but again i would need to surly read the file to find the number of rows?
    Yes, but you wouldn't necessarily have to read it to your array you could keep a count of the amount of rows you encounter. It may seem a bit wasteful, and there are more ways than one to do it. But you are supposed to use a plain text file with no header info, and are not allowed to use something like a linked list so the options are a bit limited, if I have understood your requirements correctly. You can read everything into a big blob which you can determine the size of by using stat() (or your own diy stat using fseek/ftell), then proceed to iterate that blob and count the occurrence of '\n' characters and keep a count. The last example is doing essentially the same but in memory which adds some complexity to it all.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 04-25-2012, 04:30 AM
  2. Reading from File and Storing into Array
    By Magic staple in forum C Programming
    Replies: 13
    Last Post: 12-05-2011, 12:00 AM
  3. Replies: 12
    Last Post: 09-23-2010, 11:49 AM
  4. Help - Reading a file and storing it as a 2d Array.
    By MetallicaX in forum C Programming
    Replies: 2
    Last Post: 03-08-2009, 07:33 PM
  5. Reading strings from a file and storing into an array
    By Rizage in forum C++ Programming
    Replies: 1
    Last Post: 10-24-2002, 03:04 AM