Solved

How to Read file into 2d Array

Posted on 2009-07-15
19
612 Views
Last Modified: 2012-05-07
Hi

A part of my code is to read a file containing certain values into a 2D array for further processing. There can be any mumber of rows(more than 300) and any number of columns (less than 360). One of the problems im facing is to get the exact number of rows and columns in the file to dynamically allocate memory for the array. Further  to effectiveluy use fscanf or fgets to scan the file into the array.

Ive been tryina couple of things so now im just confused. Any help would be much appreciated.
0
Comment
Question by:Naverick
  • 10
  • 9
19 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 24862921
>> Ive been tryina couple of things

If you could post them, then we can have a look at what you tried, and see if you're close or not.


>> A part of my code is to read a file

What kind of file ? A binary file ? Or a text file ? What's the format of the file (can you post an example) ?
0
 

Author Comment

by:Naverick
ID: 24863143
Its a text file

getting the exact number of rows and colums and scanning correctly is an issue

been told can use fgets for rows n colums and string tokenizer to scan each character and then covert into array


/*allocate memory for array**/
array = (int**)malloc(rows*sizeof(int));
 for(i=0;i<rows;++i)
 {
   matrix[i] = (int*)malloc(cols*sizeof(int));
   }

The text file could be something like
200   0    10    1    4    0 ............
180    12    1    3    0   9..............
.
.
.
.


/*print the array  to test if working */
 for(j=0;inrows;++i)
 {
   for(k=0;k<ncols;++k)
   {
     fprintf(fpout,"%d ", array[j][k]);
   }
   fprintf(fpout,"\n");
 }
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 50 total points
ID: 24863187
>> The text file could be something like

And each line in the file represents one row, right ?


>> getting the exact number of rows and colums and scanning correctly is an issue

What you can do, is either :

(a) make a first pass over the file, just to find out how many rows and columns there are (so you can allocate the correct amount of memory), and then a second pass to copy the data.

(b) allocate a 2D array that is big enough to hold any amount of data the file can contain (you mentioned that it's always less than 360), and then simply fill the 2D array with the data from the file.

(c) read the data from the file, and realloc the 2D array to change it's size if needed.
0
 

Author Comment

by:Naverick
ID: 24863324
Its a text file

getting the exact number of rows and colums and scanning correctly is an issue

been told can use fgets for rows n colums and string tokenizer to scan each character and then covert into int

fgets(size,sizeof(nRrow),fpin);

/cant figue out for colums/

/*allocate memory for array**/
array = (int**)malloc(rows*sizeof(int));
 for(i=0;i<rows;++i)
 {
   array[i] = (int*)malloc(cols*sizeof(int));
   }

for(i=0;i<rows;i++) {
       
        fgets(nRow,sizeof(nRow),fpin);
        ptrRow=nRow;
        k=0;
        while((token=strtok(ptrRrow,"\t"))!=(char *)NULL && k<cols) {
                array[i][k++]=atoi(token);
                ptrRow=(char *)NULL;
        }
     }




The text file could be something like(while creating the file i have inserted tabs between two values)
200   0    10    1    4    0 ............
180    12    1    3    0   9..............
.
.
.
./*print the array  to test if working */
 for(j=0;inrows;++i)
 {
   for(k=0;k<ncols;++k)
   {
     fprintf(fpout,"%d ", array[j][k]);
   }
   fprintf(fpout,"\n");
 }
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24863369
Did my previous post help ?


>> 200   0    10    1    4    0 ............
>> 180    12    1    3    0   9..............

Incidentally, is there a reason that the first values of each line are much bigger than the others ? Or is that a coincidence ?

Or do they represent the amount of items in the row maybe ?
If so, does the file also contain the amount of rows somewhere (maybe the first line of the file ?) ?
And is it to be expected that rows can have a different amount of items ? (200 != 180)
0
 

Author Comment

by:Naverick
ID: 24863396
That makes a lot of sense.....but cant figure how to get number of colums

fgets(size,sizeof(nRrow),fpin);

will just have to count number of values in first row to count number of colums till i get to /n .....right??
0
 

Author Comment

by:Naverick
ID: 24863439
For some reason i do get high values in the first column.... its just a coincidence. I can modify my previous code to also print the number of rows. But it will print at the end of the file after the last row

No all rows will have the same number of values
0
 

Author Comment

by:Naverick
ID: 24863481
guess im mixing one too many thigs for a not so difficult task...hence its just messed up due to lack of structure and logic
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24863490
>> will just have to count number of values in first row to count number of colums till i get to /n .....right??

Yes, that would give you the amount of columns.

Which of the 3 approaches I listed earlier do you plan to use ?
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:Naverick
ID: 24863598
>>>>>What you can do, is either :

The logic there will take me there..... Its just the technicality im stuck with...are the bits of code any good...?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24863623
Yes, but which of the 3 approaches did you pick ? Which one do you want to implement ?
0
 

Author Comment

by:Naverick
ID: 24863705
(a) make a first pass over the file, just to find out how many rows and columns there are (so you can allocate the correct amount of memory), and then a second pass to copy the data.

Seems to be the most efficient precise and logical and simpler. The other are bit difficult for me to comprehend. Might be someting to do with using a buffer. While the second option of predefining a large array may either give rise to unsufficient memory or having to deal with filling empty cells with null ..again not sure but id go with (a)
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24863783
>> While the second option of predefining a large array may either give rise to unsufficient memory

360*360*sizeof(int) is still reasonable in size. Assuming an int is 4 bytes, that would be 518400 bytes, or about half a MB.

>> or having to deal with filling empty cells with null

You don't need to fill them, because you know how many rows and columns there are (by the time you reach the end of the file).


>> again not sure but id go with (a)

Ok, that sounds good. Let's go with that.

So, we'd make a first pass over the file, just to find out how many rows there are (ie. how many lines in the file), and how many columns there are (ie. how many numbers on one line).
After that, you allocate the needed amount of memory.
Then you rewind the file, and start again from the beginning. This time you fill the allocated array with the numbers from the file.
0
 

Author Comment

by:Naverick
ID: 24863865
the number of rows will be greater than 360 may 1000 or more....but colums will be less than 360.

as far as the snippets of code ive posted are they any good for the chosen method
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24863895
Except for this line :

>>                 ptrRow=(char *)NULL;

the code you posted looks ok for allocating the memory and filling the array with the data from the file.

But you still need to find out the amount of rows and columns.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24863903
Just give it a try with the above information, and don't hesitate to ask if you have a doubt about something.
0
 

Author Comment

by:Naverick
ID: 24863925
will do...thx for guiding me..will get back...as soon as i have something in hand....Thx again
0
 

Author Comment

by:Naverick
ID: 24866775
Hey Infinity
 I manged to do that bit. It did work to the best of my knowledge. However if u can pls go thru the code n c if its ok. i will have to later modify this bit and make it a function. Howevr, the logic seems to b fine i think. Is there any way of speeding process because the main code is supposed to run in real time and there could be at least 20 files (360x1000) to process. I have attached a small examle txt file.

I have another query amongst others. Should i cotinue on this or frame a new question. In breif , how can i dynamically increase the size of an array (add a new row) without loosing the values already stored in the previous rows. As this array will be used to for further frocessin with the array got from the file.

Thanx a lot

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

 

 

int main(int argc, char *argv[])

	{

	FILE *fin, *fout ; 

	int colCnt,rowCnt, col=0,row=0;

	int i,j;

	int**matrix;

	
 

	if(argc!=2)

		{

		printf("Check Arguments\n");

		exit(0);

		}

	if(!(fin=fopen(argv[1],"r")))

		{

		printf("Unable to open file\n");

		exit(1);

		}

	

	while((colCnt=fgetc(fin))!='\n')

		{

		if(colCnt=='\t')

			{

			++col;

			}

		}

	rewind(fin);

	while((rowCnt=fgetc(fin))!=EOF)

		{

		if(rowCnt=='\n')

			{

			++row;

			}

		}
 

	rewind(fin);

	

	printf("Number of cols = %d ",col);

	printf("Number of rows = %d\n ",row);
 

	matrix =(int**)malloc(row*sizeof(int));

	for(i=0;i<row;i++)

		{

		matrix[i]=(int*)malloc(col*sizeof(int));

		}
 

	for(i=0;i<row;i++)

		{

		for(j=0;j<col;j++)

			{

			fscanf(fin,"%d",&matrix[i][j]);

			printf("%d ",matrix[i][j]);

			}

		printf("\n");

		}

	fclose(fin);

	return 0;

		

	}

Open in new window

hist.txt
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 24866894
You have two while loops : one for counting the columns, and one for the rows. You don't need to rewind after the first loop, since you'll be reading the same characters again, and you already know that you've seen only one '\n'.


>>         matrix =(int**)malloc(row*sizeof(int));

This has to be :

        matrix =(int**)malloc(row*sizeof(int*));

since you're allocating and array of int*'s here, not an array of int.

Also, consider checking whether malloc returns NULL each time you call it, to be sure that the allocation succeeded before continuing with the rest of the code.


The rest of the code looks fine.


>> Is there any way of speeding process because the main code is supposed to run in real time and there could be at least 20 files (360x1000) to process.

There are a few ways (like : instead of rewinding the file and reading it again, read it into a memory buffer the first time, and use the memory buffer for the second pass). But don't optimize, until you actually notice a problem with performance ...


>> Should i cotinue on this or frame a new question.

Since it's a short question, and still somewhat related to the original question, I'll answer it here ;)


>> how can i dynamically increase the size of an array (add a new row) without loosing the values already stored in the previous rows

When the realloc call succeeds for increasing the size of a block of memory, it guarantees that the original data will remain unchanged. See the reference page for more information :

        http://cplusplus.com/reference/clibrary/cstdlib/realloc/
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now