#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAX_BYTES 16

int main(int argc, const char *argv[])
{
    FILE *fp = stdin;
    
    if (argc >= 2) {
        fp = fopen(argv[1], "rb");

        if (!fp) {
            perror("fopen");
            exit(EXIT_FAILURE);
        }
    }

    size_t offset = 0;
    size_t n_bytes = 0;
    unsigned char line[MAX_BYTES] = {0};
    
    while ((n_bytes = fread(line, 1, MAX_BYTES, fp)) > 0) {
        printf("%08zx  ", offset);
    
        // printa os bytes lidos em hexadecimal
        for (size_t i = 0; i < n_bytes; i++) {
            printf("%02x ", line[i]);
            if (i == 7) printf(" ");
        }
        // alinha os espaços faltantes antes do bloco ASCII
        for (size_t i = n_bytes; i < MAX_BYTES; i++) {
            printf("   ");
            if (i == 7) printf(" ");
        }
        printf(" |");

        // printa os bytes lidos em ASCII / texto
        for (size_t i = 0; i < n_bytes; i++) {
            printf("%c", isprint(line[i]) ? line[i] : '.');
        }
        offset += n_bytes;
        printf("|\n");
    }
    printf("%08zx\n", offset);
    fclose(fp);

    return 0;
}
