Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reading a file into an Array and then looping 1

Status
Not open for further replies.

debih99

Programmer
Mar 22, 2001
7
US
I am working on a C project, to which I have little
experience. I am starting with a simple program - read input, load into an array and then write out a new file.
The problem is either I'm not loading of the array properly or I'm not writing out to the file the right way. I say this because the printf during the loop doesn't look right and I get a coredump on the memcpy into the outFILE.
The Input has 4 records and looks like this:

1234567TestBid222100.50
7654321TestBid333288.75
6543210TestBid444523.80
5432109TestBid555825.75

The printf's are as follows:
In the init array....
The array position is 0.
The array position is 1.
The array position is 2.
The array position is 3.
There are 4 records in the array.

The array position is 0
The bid is : TestBid222
765432

11472 Memory fault(coredump)

Code:
#include <stdio.h>
#include <stdlib.h>
#define  TYPELEN 7
#define  BIDLEN 10
#define	 AMTLEN 6


/*-- Pointers --*/
FILE	*fpIN;
FILE	*fpOUT;

int     col;
int     row;
int 	tot;


/* Input File */
typedef struct
 {
	char  Type [TYPELEN];
	char  Bid [BIDLEN];
	char  Amt[AMTLEN];
 }
 tIN;

 tIN inFILE;

/* Output File */
typedef struct
{
	char  Type [TYPELEN];
	char  Bid [BIDLEN];
}
tOUT;

tOUT outFILE;

/*-- Array --*/
struct tKEY
{
	char KeyType[TYPELEN];
	char KeyBid[BIDLEN];
};

struct tKEY cpsmKEY[4][2];


main()
{
/*Open stuff.....*/

/*-- Read and Load Input File into array. --*/
printf(&quot; In the init array....\n&quot;);

while ( fread((char *) &inFILE,sizeof(inFILE),1,fpIN)==1)
{
memcpy(cpsmKEY[tot][0].KeyType,inFILE.Type,TYPELEN);
memcpy(cpsmKEY[tot][1].KeyBid,inFILE.Bid,BIDLEN);
printf(&quot;The array position is %d.\n&quot;, tot);
++tot;
}

printf(&quot;There are %d records in the array.\n&quot;, tot);
printf(&quot;\n&quot;);

/*-- Loop thru array and write out new file--*/
for  (row = 0; row < tot; row++)
{
printf(&quot;The array position is %d\n&quot;, row);
printf(&quot;The bid is : %10s\n&quot;, cpsmKEY[row][1].KeyBid);
printf(&quot;\n&quot;);
memcpy(outFILE.Type,cpsmKEY[row][0].KeyType);
memcpy(outFILE.Bid,cpsmKEY[row][1].KeyBid);
fwrite(&outFILE,1,sizeof(outFILE), fpOUT);
}
}
 
Hi,

Comments inline.

>#include <stdio.h>
> #include <stdlib.h>
> #define TYPELEN 7
> #define BIDLEN 10
> #define AMTLEN 6
>
>
> /*-- Pointers --*/
> FILE *fpIN;
> FILE *fpOUT;
>
> int col;
> int row;
> int tot;

These variable are better local to a function than global.

>
>
> /* Input File */
> typedef struct
> {
> char Type [TYPELEN];
> char Bid [BIDLEN];
> char Amt[AMTLEN];
> }
> tIN;
>
> tIN inFILE;

ditto, inFILE should have function scope.

>
> /* Output File */
> typedef struct
> {
> char Type [TYPELEN];
> char Bid [BIDLEN];
> }
> tOUT;
>
> tOUT outFILE;

same here.

>
> /*-- Array --*/
> struct tKEY
> {
> char KeyType[TYPELEN];
> char KeyBid[BIDLEN];
> };
>
> struct tKEY cpsmKEY[4][2];

Again.

>
>
> main()

note that implicit int return from main() is disallowed by the new C standard, so you'd be better off using:

int main(void) OR
int main(int argc,char **argv)

> {
> /*Open stuff.....*/

ok, have to take your word for it that you're doing things right here.

>
> /*-- Read and Load Input File into array. --*/
> printf(&quot; In the init array....\n&quot;);
>
> while ( fread((char *) &inFILE,sizeof(inFILE),1,fpIN)==1)

fread() isn't the function you want. You should only use fread() to read binary files. If fread() was appropriate, you are still calling it incorrectly. The 1st argument to fread() is a pointer to void. The cast to pointer to char here doesn't make sense. In fact, you need no cast at all as pointers to any type can be implicitly converted back and forth to pointers to void without any loss of information.

Your input file is in plain text (as posted above), a series of records separated by newlines, so fgets would be a good choice. Try something like this:

#define MAXLINE 1000 /* or some suitable number */

/* ... */

char buf[MAXLINE+1]; /* to hold each line */
char *tmp;

while (fgets(buf,sizeof buf,fpIN)!=NULL) {
/* now buf will contain the current line of the file
* and the file pointer will be advanced to the start
* of the next line
*/
tmp=strchr(buf,'\n');
if (NULL==tmp) {
/* line was truncated, handle error */
} else {
*tmp=0; /* get rid of the newline */
}

Try to use text files where possible because you can run into all kinds of portability problems with binary files.

Also, for text files, make sure that your calls to fopen() look something like this:

fpIN=fopen(&quot;name_of_file&quot;,&quot;r&quot;);

> {
> memcpy(cpsmKEY[tot][0].KeyType,inFILE.Type,TYPELEN);
> memcpy(cpsmKEY[tot][1].KeyBid,inFILE.Bid,BIDLEN);

Because you're using fgets(), try using a function like sscanf() to parse each line into its pieces and copy the appropriate parts into your array.

If you /must/ use fread(), you must write the file initially with fwrite(). Post again if things still aren't clear.

HTH,

Russ
bobbitts@hotmail.com
 
Thanks Russ, Your response was very helpful.

I had started the pgm using fgets, but saw that the standard here was fread. But for my case, the files are fixed length ascii files. So this works!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top