//========================================================================= #define PROGRAMMER "BAHN, William" #define PROG_CODE "wbah" #define COURSE "ECE-1021" #define YEAR (2004) #define TERM "Spring" #define SECTION (0) #define ASSIGNMENT "Example Program" #define REVISION (0) #define TITLE "File Dump Program" #define SUBTITLE "Last Modified on 08 MAR 04" #define EMAIL "wbahn@eas.uccs.edu" #define FILENAME "filedump.c" //========================================================================= // PROBLEM: // // Write a program that displays the contents of a file byte-by-byte. // Both the byte's value (in Hex) and the ASCII character (if it is // printable) should be displayed. Non-printable ASCII codes should be // displayed as a period (.). // // PSEUDOCODE: // // 1) TASK: Get the file name // 2) TASK: Open and verify the file // 3) TASK: Display Contents of File // 3.1) TASK: Display Header // 3.2) TASK: Display File Contents 16 bytes at a time // 4) TASK: Display Total Byte Count //== INCLUDE FILES ======================================================== #include // EOF, fopen(), fclose(), feof(), printf(), fgets() #include // strncpy() #include // isprint() //== MACRO DEFINITIONS =================================================== #define MAXSTRLEN (81) #define MAXMARKS (60) //== FUNCTION PROTOTYPES ================================================== void PrintHeader(void); char *stripCR(char *s); long int DumpFile(FILE *fp); void DumpHeader(void); long int DumpBody(FILE *fp); //== MAIN FUNCTION ======================================================== int main(int argc, char *argv[]) { char filename[MAXSTRLEN]; FILE *fp; long int bytes; PrintHeader(); //------------------------------------------------------------------ // 1) TASK: Get the file name //------------------------------------------------------------------ // Check for file name on command line, get from user if not found if(argc < 2) { printf("Enter filename: "); fgets(filename, MAXSTRLEN, stdin); stripCR(filename); } else { strncpy(filename, argv[1], MAXSTRLEN); } //------------------------------------------------------------------ // 2) TASK: Open and verify the file //------------------------------------------------------------------ // Open file for reading (in binary mode) printf("Attempting to open file: <%s>\n", filename); fp = fopen(filename, "rb"); if(NULL == fp) { printf("Failed to open file for reading - abort!\n"); return(1); } //------------------------------------------------------------------ // 3) TASK: Display Contents of File //------------------------------------------------------------------ printf("\nFile Contents:\n\n"); bytes = DumpFile(fp); fclose(fp); //------------------------------------------------------------------ // 4) TASK: Display Total Byte Count //------------------------------------------------------------------ printf("\nTotal bytes: %li\n", bytes); return(0); } //== SUPPORT FUNCTIONS ==================================================== void PrintHeader(void) { printf("========================================" "=======================================\n"); printf("Course....... %s-%i (%s %i)\n", COURSE, SECTION, TERM, YEAR); printf("Programmer... %s (%s)\n", PROGRAMMER, PROG_CODE); printf("Assignment... %s (Rev %i) (Source Code in %s)\n", ASSIGNMENT, REVISION, FILENAME); printf("Description.. %s\n", TITLE); printf(" %s\n", SUBTITLE); printf("========================================" "=======================================\n"); return; } char *stripCR(char *s) { char *a; a = s; do { switch(*a) { case '\n': case '\f': *a = '\0'; } } while('\0' != *(a++)); return(s); } long int DumpFile(FILE *fp) { long int bytes; bytes = 0; // 1) TASK: Display Header DumpHeader(); // 2) TASK: Display File Contents 16 bytes at a time bytes = DumpBody(fp); return(bytes); } void DumpHeader(void) { int i; // 1) TASK: Display Header // 1.1) Print column headings printf(" BLOCK "); for(i = 0; i < 16; i++) { printf("%c", (!(i%4))? '|' : ' '); printf("% 2X", i); } printf("| "); for(i = 0; i < 16; i++) { printf("%1X", i); } printf("\n"); // 1.2) Print dividing line printf("==========="); for(i = 0; i < 16; i++) { printf("%c", (!(i%4))? '|' : ' '); printf("=="); } printf("| "); for(i = 0; i < 16; i++) { printf("="); } printf("\n"); return; } long int DumpBody(FILE *fp) { int i; long int bytes; int c[16]; bytes = 0; // 2) TASK: Display File Contents 16 bytes at a time // Initialize counter variables bytes = 0; // Loop until end of file is reached - FYI: EOF may occur within a line. while(!feof(fp)) { //------------------------------------------------------------- // Print Byte Values //------------------------------------------------------------- // Print the byte count of the start of the line 0000:000 format printf(" %04lX:%04lX ", ((bytes>>16)&0x000FFFF), bytes&0x000FFFF); // Read 16 bytes from file and display for(i = 0; i < 16; i++) { // Print vertical dividing line every four bytes printf("%c", (!(i%4))? '|' : ' '); // Fetch and print next byte's value c[i] = fgetc(fp); if(EOF == c[i]) // End-of-file reached in middle of 16-byte group { // indicate EOF by ".." instead of value printf(".."); c[i] = 0; } else { // print value and increment byte count printf("%02X", c[i]); bytes++; } } //------------------------------------------------------------- // Print ASCII symbols //------------------------------------------------------------- // Separator between value printout and ASCII printout printf("| "); // Print the ASCII codes for the 16 bytes that were read for(i = 0; i < 16; i++) { printf("%c", ( isprint(c[i])? c[i] : '.' ) ); } // Close line and increment line counter printf("\n"); } return(bytes); }