Question:
More Help With .txt Data To An Array in C?
J B
2008-07-11 13:04:50 UTC
So, I'm trying to take data from a text file in m by 3 (m is many unknown rows) and assign the data to a like-sized array in C. The data is tab delineated and floating point.

The following is what I have so far, and keep in mind the text file is already open for reading...

#include
#include

int main(void)
{ float arrayf1(float array1[][3], float i, float j);
FILE *fp1;

/*note this section is mostly opening and reading the file and is skipped to show just the function recall*/

printf("\nThe first three values are: %f, %f, and %f\n", arrayf1[0][0], arrayf1[0][1],arrayf1[0][2]);

return 0;
}

/* Function Definitions */
float arrayf1(float array1[][3],float i, float j);
{
float i;
float j;
for ( int i = 0; i < max; i++)
for (int j = 0; j < 2; j++)
fscanf(%f, &array1[i][j]);
return array1;
}
Four answers:
gene_frequency
2008-07-11 15:19:37 UTC
I recommend a process like that below.



Now, please note that you can re-work parsefile() for use only as a counter for first run--where no data is stored--just to first enquire how many values are to be captured in the file. Add a "which_pass" flag.



On the second pass, when data qty is known, allocate memory, and call parsefile() again.



Hope this is helpful.....





//---------------------------------------------------------------------

//

// get_field_offs()

//

// Find the offset of the desirred field in the buffer

//

//---------------------------------------------------------------------

int get_field_offs(char *s, int fld)

{

int i,len=strlen(s);

int tabs=0;



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

{

if(tabs>=fld) //stop if we hit required number of tabs

{

return i; //normal-usual exit

}

if(s[i]=='\t')

tabs++;

}

puts("ERR: get_field_offs()"); //user alert

return 0; //<<
//after all, zero (1st offset) is a valid value

}





//---------------------------------------------------------------------

//

// get_field()

//

// Function that returns a buffer having only the desired field.

// Strips leading spaces, tabs

//---------------------------------------------------------------------

char *get_field(char *s, int fld)

{

static char buff[100];

char *ps,*pd;

int done=0;



pd=buff;

ps=&s[get_field_offs(s, fld)];



while(*ps == ' ') //strip leading spaces, if exixst

ps++;



// Parse until 1st tab, etc

while(!done)

{

switch(*ps)

{

case '\0': //string terminator

case '\t': //tab

case '\r': //end of line character

case '\n': //end of line character

done=1;

break;



default:

*pd++=*ps++; // Collect normal chars, OK

break;

}

}

*pd=0; //Strip trailing junk



if(strlen(buff))

return buff;

return NULL;

}





//----------------------------------------------------------------------

//

// parsefile()

//

// Reads a file gathering data

//----------------------------------------------------------------------

void parsefile(FILE *fp)

{

char buff[300]; // make big enough to hold a line of data

int iii=0;

char *next_value=NULL;

double bigNumber;

long count=0;

memset(buff , '\0', sizeof(buff) );

fseek(fp, 0, SEEK_SET); //goto start of file



while(fgets(buff, sizeof(buff)-1, fp) != NULL)

{

for(iii=0; iii<1000; iii++) //note: '1000' is an arbitrary line length

{

next_value = get_field(buff, iii);

if(!next_value)

break; ///end of line -- no more data

bigNumber = atof( next_value );

count++;

///we've got the next number....do what you will with it--display, store...

printf("Next number is: %f\n", bigNumber);

}

}

printf("You'll need enough memory to hold %ld numbers.", count);

}
Steve G
2008-07-11 13:41:19 UTC
If you don't know at compile time how big the array is going to be, you're going to want to use malloc and realloc.



I'm *way* out of practice with this, but...



int main(void)

{

float *array1 = NULL;

float arrayf1(float *arrary1, float i, float j);

...

arrayf1 = (float *)malloc(sizeof(float) * 3);

...

}



/* Function Definitions */

float arrayf1(float *array1, float i, float j)

{

int size = 1;

while (!feof(fp1))

{

/* do a realloc for **each** new row! */

array1 = (float *)realloc(array1, sizeof(float) * 3 * size++ );



/* read in your current line form the file */

}

}



The source below may give your some ideas for more complex (but more robust) ways of handling this.
Krzys
2008-07-11 13:58:06 UTC
This one is hard :)



If 'm' is large then you should not use an array to read the data. Arrays require continuous memory blocks. If you ask for a huge block, it might not work.



There are two methods there:

- do each row separately and avoid 2D array (the very best but obviously not always possible)

- use a linked list to represent rows.



Lists are extremely important topic but can be a bit tough at first sight. The best advice I can give you is DRAW, WHAT IS GOING ON ON EACH LINE OF YOUR CODE. Where each pointer points, what memory is allocated, what is free etc. If you want to really understand this, drawing is vital! Take a look at:

http://pages.cs.wisc.edu/~vernon/cs367/notes/4.LINKED-LIST.html

BUT MAKE SIMILAR PICTURES FOR YOUR CODE YOURSELF. DO ***N O T*** SKIP ANY LINE. (Sorry for screaming, but I see this as one of the most important advices I can give to anyone wishing to learn dynamic data structures). There is no other way :)
siwani
2016-10-30 14:03:47 UTC
pass the subsequent 2 traces OUT of the on a similar time as loop int zipArray[one hundred]; *** Initialize outdoors of the loop i = 0; ** you will desire to initialize outdoors of the loop and alter cout << zipArray[a million]; to cout << zipArray[i]; reason: you're rewriting the zipArray (lossing contents) each time the loop starts off and putting your instream archives to index 0 (i=0), that's rewriten on the subsequent loop and by no skill to i = a million,2,3, and so on.


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...