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;
}

