File Read Problem

Okay so I have a file which I put part data into. I then have to read the file, the problem is my code doesn't seem to want to dump the file. I'll post the code and if anyone can help me that would be awesome

Code:

/* Create and/or list a random file, which is a parts list with
* sub-assemblies. Sub-assemblies get expanded as they are listed.
*
* Lab 6 - comment this listing, and add the Dump() function.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#define FILENAME "parts.dat" // parts database
#define PART_NAME_LEN 20 // max length of a part name
#define PART_MAX_COMPONENTS 10 // at most 10 parts make up an assembly
struct Part {
int iPartNum; // NOTE the same as the record number in the file
char szName[PART_NAME_LEN]; // part name
char cPartType; // 'P' for Part, 'A' for assembly etc
int iQuantity; // quantity on hand
int iComponents[PART_MAX_COMPONENTS]; // parts which make up this part,
// IF it's an assembly. -1 for unused.
}parts;
typedef struct Part Part;
int DumpPartsList(int iExplode);
int AddToFile(void);
int main(int argc, char *argv[])
{
if ( argc > 1 ) {
// file creation mode. Prompt the user for data and append to file.
AddToFile();
// then carry on with the dump.
}
// Dump the parts list without exploding assemblies.
DumpPartsList(0);
printf("-----END of non-exploded list. Press Enter to continue------");
getc(stdin);
// Dump the parts list WITH exploded assemblies.
DumpPartsList(1);
printf("-----END of exploded list. Press Enter to continue------");
getc(stdin);
return(0);
}
// This Function will allow a user to enter parts into the database.
int AddToFile(void)
{
FILE *fd;
char szBuf[80];
char *szPtr;
Part New;
int iRecord;
int i, j;
unsigned int iChars;
// Open a file that will have elements placed into opened as a binary will all attributes given to it
fd = fopen( FILENAME, "ab" );
if ( !fd ) {
printf("File open failed.\n" );
return(-1);
}
fseek(fd,0L,SEEK_END); // Visual needs this!
// Where are we adding? This will be the next record number.
iRecord = ftell(fd) / sizeof(Part);
// Add new records to the database, until the user says to stop
for ( ; ; ) {
// Get rid of any nasty type-ahead, then get a part number. Quit on ^Z
fflush(stdin);
printf("\nPart %d: Enter name [19 max, ^Z to stop]: ", iRecord);
if ( fgets(New.szName, PART_NAME_LEN-1, stdin) == NULL ) break;
// Ignore blank lines. Remove newlines from non-blank lines.
i = strlen(New.szName);
if ( i <= 1 ) continue;
New.szName[i-1] = '\0';
// Start an infusing getline in Cinite loop which will allow the user to input parts
for ( ; ; ) {
fflush(stdin);
printf("Enter type [p or a]:");
i = scanf( "%c", &New.cPartType );
// Quit if no character entered. Otherwise, accept only A or P.
if ( i < 1 ) break;
New.cPartType = toupper(New.cPartType);
if ( New.cPartType == 'A' || New.cPartType == 'P' ) break;
}
// if no part was entered into the database just quit out
if ( i < 1 ) break;
// Get the starting quantity. Default to 10.
printf("Enter start quantity: ");
fflush(stdin);
i = scanf( "%d", &New.iQuantity );
if ( i < 1 || New.iQuantity < 0 )
New.iQuantity = 10;
// Initialize the sub-assembly/component list to all empty.
for ( i=0; i < PART_MAX_COMPONENTS; ++i ) {
New.iComponents[i] = -1;
}
// Combine part numbers into an assembly which will be a collection of parts
if ( New.cPartType == 'A' ) {
fflush(stdin);
printf("Enter up to %d component part numbers, with spaces between.\n",
PART_MAX_COMPONENTS );
// Get a list of component parts, and fill them in the iComponents array.
if ( fgets(szBuf,sizeof(szBuf),stdin) != NULL ) {
szPtr = szBuf;
for ( i=0; i < PART_MAX_COMPONENTS; ++i ) {
// %n tells scanf() to report the number of characters processed.
j = sscanf(szPtr, "%d%n", &New.iComponents[i], &iChars);
// HERE!!!
if ( j > 0 ) szPtr += iChars;
else break;
} // end for all components
}
} // end assembly
// Set a part numer equal a record.
New.iPartNum = iRecord;
// if there is an error writting to the file quit the program
i = fwrite( &New, sizeof(New), 1, fd );
if ( i != 1 ) {
printf("Error writing record %d.\n", iRecord );
break;
}
//Increment the bigges loop so the user can enter a new part which is a record.
++iRecord;
}
// Close the file.
fclose(fd);
return(0);
}
int DumpPartsList(int iExplode)
{
//File Pointer will be used for opening file
FILE *fd;
fd=fopen(FILENAME,"rb");
//if to test for non exploding
if(iExplode == 0){
//Use a loop to run until the end of file has be reached
while(!feof(fd)){
//Use fread to read the file
fread (&parts, sizeof(struct Part), 1, fd);
//Check to see if read was succesful
//if(ferror(fd) == 1) break;
//As long as there are part numbers in the structer print
if (parts.iPartNum != 0) {
printf("%-6d%-19s%-11c%-6d\n",parts.iPartNum, parts.szName, parts.cPartType, parts.iQuantity);
}//end if
}//End While
}//End if
//Close the file
fclose(fd);
return 0;
}

You say your code doesn't seem to want to dump the file. What does that mean? What errors are you getting? If you don't know what errors you are getting, use a debugger, or sprinkle some printf statements around that provide some relevant information. Guessing isn't an effective troubleshooting method.

On another note: your compiler might clear the input stream with fflush (stdin), but a standards compliant compiler will not. Your program may cease to work with the next compiler version.

C and C++ are really bad in this regard, though C++ does provide an ignore function. The best way to handle this reliably in C is to repeatedly read characters from the stream until you get a newline or an EOF. Notice, however, that if there is nothing in the stream, this operation will block, and you're screwed. To prevent that happening, use ungetc to put a character back into the steam, and then read until you get a newline or an EOF.