программа hexdump на языке C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 255

void hexDump (char *desc, void *addr, int len) {
    int i;
    unsigned char buffLine[17];
    unsigned char *pc = (unsigned char*)addr;


    if (desc != NULL){

       printf ("%s:\n", desc);

    }


    for (i = 0; i < len; i++) {


        if ((i % 16) == 0) {

            if (i != 0)

                printf ("  %s\n", buffLine);
           // if (buffLine[i]== '\0') break;

            if (pc[i] == 0x00) exit(0);

            // Prints the ADDRESS
            printf ("  %07x ", i);
        }

        // Prints the HEXCODES that represent each chars.
        printf ("%02x", pc[i]);
        if ((i % 2) == 1) 
            printf (" "); 



        if ((pc[i] < 0x20) || (pc[i] > 0x7e)){
            buffLine[i % 16] = '.';
        }

        else{

           buffLine[i % 16] = pc[i];

        }    


        buffLine[(i % 16) + 1] = '\0'; //Clears the next array buffLine


    }



    while ((i % 16) != 0) {
        printf ("   ");
        i++;
    }


    printf ("  %s\n", buffLine);
}

//----------------------------------------------

int main()
    {
            FILE *ptr_file;
            char buff[SIZE];

            ptr_file =fopen("input.txt","r");
            if (!ptr_file){
            printf("returning 1");
                return 1;
            }

            memset(buff, '\0', sizeof( buff) );
            fgets(buff,SIZE, ptr_file);
            hexDump ("buff", &buff, sizeof (buff));

        fclose(ptr_file);

            return 0;
    }
    //*/

Извините, я новичок в C, так что сейчас это довольно грязно, я удалял части и создавал временные коды и т. Д. Так что в любом случае это работает, читая символы из input.txt и выводя их, печатая шестнадцатеричное представление и представления Acii справа. Для байтов, образующих непечатаемые символы, напечатайте символ «.» (символ точки/точки, т. е. шестнадцатеричное значение 2E).:

0003540: 0504 0675 6e73 6967 6e65 6420 6368 6172 ...unsigned char
0003550: 0008 0107 0000 0131 0675 6e73 6967 6e65 .......1.unsigne

НО моя программа не печатает ничего, кроме «новой строки» в тексте. Например: в моем input.txt у меня есть:

This is line 1 so this will be longer than usual
line 2 is this
this is the last line

после прочтения моей программы она выводит только так:

  0000000 5468 6973 2069 7320 6c69 6e65 2031 2073   This is line 1 s
  0000010 6f20 7468 6973 2077 696c 6c20 6265 206c   o this will be l
  0000020 6f6e 6765 7220 7468 616e 2075 7375 616c   onger than usual
  0000030 0a00 0000 0000 0000 0000 0000 0000 0000   ................

Но по какой-то причине он не печатает и не зашифровывает вторую, третью строку....


person xpluffy    schedule 22.09.2014    source источник
comment
Вам нужно либо вызвать fgets в цикле, чтобы читать строку за раз, либо использовать fread, чтобы читать блоки фиксированного размера.   -  person Paul R    schedule 22.09.2014


Ответы (3)


Вы должны использовать fread() для чтения файла и поместить его в цикл (пока он не вернет 0), чтобы он читал весь файл. Если вы работаете в Windows, обязательно откройте файл с помощью «rb» (бинарный режим), в то время как в Unix это не имеет значения.

Последнее предложение - использовать isascii() или одну из родственных функций вместо ручной проверки "пригодности для печати". См. http://linux.die.net/man/3/isalnum.

person SukkoPera    schedule 22.09.2014

Вы звоните fgets только один раз. fgets читает строку из файла и останавливается, когда исчерпан лимит символов в SIZE, когда он достигает конца файла или встречает символ новой строки. Так что такое поведение ожидаемо.

Длина данных обычно меньше предела символов, но вы печатаете все SIZE символов, что дает вам нули.

Если вы хотите обработать все строки, вы должны вызвать fgets в цикле и прервать его, когда он вернет NULL. Вы также должны передать strlen(buf) в качестве параметра длины вместо sizeof(buf), что даст вам обычно слишком длинное SIZE.

Цель шестнадцатеричного дампера — сделать данные любого файла видимыми. Вы используете fgets и char, которые следует использовать для текстовых файлов. (Я не уверен, что делает fgets, например, когда встречает нулевой байт.)

Поэтому лучше использовать байты, то есть unsigned char, и читать их поблочно с fread. Если вы сделаете размер блока кратным 16, это поможет вам отформатировать вывод. Так:

for (;;) {
    unsigned char buf[SIZE];
    size_t n = fread(buf, 1, SIZE, f);

    if (n > 0) dump(buf, n);
    if (n < SIZE) break;
}
person M Oehm    schedule 22.09.2014

Вам нужно открыть файл в двоичном режиме, используя «rb», а не «r».

Затем используйте fread() для чтения из файла либо путем чтения фрагментов из него, либо путем чтения всего файла.

person AndersK    schedule 22.09.2014