Wyświetlacz zawartości pliku tekstowego. Możliwe są dwa tryby wyświetlania: tekstowy i szesnastkowy. Domyślnym trybem jest tryb tekstowy. Nazwę pliku i tryb określają argumenty wywołania programu. Pierwszy to nazwa pliku do wyświetlenia, drugi to tryb wyświetlania – t dla trybu tekstowego, h dla szesnastkowego..
Gdy nazwa pliku nie została podana, program pyta o nią i domyślnie wyświetla podgląd tekstowy.
Przykłady wywołania programu (przy założeniu, że wersja wykonywalna nazywa się file_view
):
file_view plik.txt file_view plik.txt t file_view plik.txt h file_view
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 (file_view.c).
#include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <string.h> /* Liczba linii na jednej stronie - ekranie */ #define PAGE_LENGTH 24 /* Maksymalna dlugość linii -- dla dłuższych linii program nie będzie działal prawidłowo */ #define TEXT_BUFFER_LEN 256 #define HEX_BUFFER_LEN 19 void pause_if_necessary(int lines_counter) { if((++lines_counter % PAGE_LENGTH) == 0) /* Czy ekran zapełniony? */ { printf( "---- Press Enter for more ----" ); (void)getchar(); /* Czekanie na Enter */ } } void text_view(FILE * file) { char buffer[TEXT_BUFFER_LEN]; /* Bufor na odczytywane znaki */ int lines = 0; /* Licznik linii zapełniających ekran */ /* Odczytuj kolejne linie tekstu */ putchar('\n'); while(fgets(buffer, TEXT_BUFFER_LEN, file) != NULL) { printf("%s", buffer); pause_if_necessary(++lines); } } void hex_view(FILE * file) { unsigned char buffer[HEX_BUFFER_LEN]; /* Bufor na odczytywane znaki */ int in_chars; /* Liczba znaków odczytanych z pliku */ int lines = 0; /* Licznik linii zapełniających ekran */ int i; /* Odczytuje kolejne bloki, zapamiętuje w zmiennej in_chars ile wczytano znaków za kazdym razem. Jeżeli wczytano < 0 to wystąpił koniec pliku */ putchar('\n'); while((in_chars = fread(buffer, 1, HEX_BUFFER_LEN, file)) > 0) { /* Wyświetla zawartość bufora szesnastkowo, na dwoch pozycjach, z wiodącym zerem, dużymi literami - specyfikacja %02X */ for(i = 0; i < HEX_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żli nie to wyswietla '.' */ for(i = 0; i < in_chars; i++) printf("%c", isprint(buffer[i]) ? buffer[i] : '.'); putchar('\n'); pause_if_necessary(++lines); } } 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 otwieranego pliku */ int view_mode = 't'; /* Jaki jest tryb wyświetlania */ if(--argc == 0) /* Czy nazwa pliku występuje w linii komend? */ { printf("Enter a filename: "); /* Zapytaj o nazwę pliku */ read_string(file_name, 256); /* Wczytaj nazwe pliku */ } else { /* Pobierz nazwę pliku z pierwszego parametru wywołania */ strcpy(file_name, args[1]); /* Opcja wyświetlania z drugiego parametru,o ile istnieje */ if(argc == 2) view_mode = tolower(args[2][0]); } /* Próba otwarcia pliku */ if((file = fopen( file_name, "rb")) == NULL) { printf("Sorry, can't open \"%s\" press Enter...", file_name); (void)getchar(); return EXIT_FAILURE; } /* Wybór funkcji wyświetlającej */ switch(view_mode) { case 'h' : hex_view(file); break; case 't' : default : text_view(file); break; } fclose(file); puts("\n---- Press Enter to quit ----" ); (void)getchar(); return EXIT_SUCCESS; }