Program wyświetla zawartość pliku w trybie szesnastkowo-tekstowym. Prezentuje obsługę parametrów wywołania programu, operacje na plikach w trybie binarnym oraz wykorzystanie funkcji formatowanego wyjścia printf.
Program pobiera nazwę pliku z linii poleceń, jeżeli nie ma nazwy w linii poleceń, program pyta o tę nazwę użytkownika. Do przetwarzania pliku wykorzystano odczyt blokowy. Program stanowi uzupełnienie wykładu z programowania w językach C/C++. Koncepcja przetwarzania plików przedstawiona została tutaj.
Do pobrania wersja źródłowa pliku (hex_view.c).
#include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <string.h> /* Liczba linii na jednej stronie - ekranie */ #define PAGE_LENGTH 24 /* Liczba znaków odczytywanych do bufora - tyle znaków będzie w pojedynczej linii na stronie, najpierw w postaci HEX, potem ASCII */ #define BUFFER_LEN 19 char * read_string(char * buffer, size_t buffer_len) { // Funkcja fgets pozwala zabezpieczyć się przed // przepełnieniem bufora, stosujemy zamiast funkcji gets. // Funkcja ta jednak pozostawia znak '\n' na końcu linii, // trzeba go usunąć. Można posłużyć się długością łańcucha // i manipulować indeksami, ja wolę poszukać czy nadmiarowy // znak występuje i przyciąć łańcuch na jego pozycji char * new_line_char; fgets(buffer, buffer_len - 2, stdin); if((new_line_char = strchr(buffer, '\n')) != 0) *new_line_char = '\0'; return buffer; } int main(int argc, char *args[] ) { char file_name[ 256 ]; /* Bufor na nazwę pliku */ FILE * file; /* Wskaźnik plikowy */ int in_chars; /* Liczba znaków odczytanych z pliku przy pojedynczym odczycie */ unsigned char buffer[ BUFFER_LEN ]; /* Bufor na odczytywane znaki */ int lines = 0; /* Licznik linii "zapełnianych" na ekranie */ int i = 0; /* Zmienna sterująca iteracji */ if(argc == 1) /* Czy nazwa pliku występuje w linii polecen? */ { printf("Enter a filename: "); /* Zapytaj o nazwę pliku */ read_string(file_name, 256); /* Wczytaj nazwę pliku */ } else strcpy(file_name, args[ 1 ]); /* Pobierz nazwę pliku z tablicy parametrów */ if((file = fopen( file_name, "rb")) == NULL) { printf("Sorry, can't open \"%s\" press Enter...", file_name); (void)getchar(); /* Czekanie na Enter */ return EXIT_FAILURE; } /* Odczytuj kolejne bloki, zapamiętaj w zmiennej in_chars ile wczytano znaków za każdym razem. Jeżeli wczytano < 0 to wystąpił koniec pliku */ while((in_chars = fread(buffer, 1, BUFFER_LEN, file)) > 0) { /* Wyświetl zawartość bufora szesnastkowo, na dwóch pozycjach, z wiodącym zerem, dużymi literami - specyfikacja %02X */ for(i = 0; i < BUFFER_LEN; i++) if(i < in_chars) printf("%02X ", buffer[i]); else /* Gdy w buforze jest mniej znaków, zwykle ostatni odczyt z pliku */ printf(" "); printf("| "); /* Separator części szesnastkowej od ASCII */ /* Wyświetla bufor jako ASCII o ile można, jeżeli nie, to wyswietla '.' */ for(i = 0; i < in_chars; i++) printf("%c", isprint(buffer[ i ]) ? buffer[i] : '.'); putchar('\n'); if((++lines % PAGE_LENGTH) == 0) /* Czy ekran zapełniony? */ { printf( "---- Press Enter for more ---" ); (void)getchar(); /* Czekanie na Enter */ } } fclose(file); /* Zamykamy plik */ return EXIT_SUCCESS; }