⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hd.c

📁 稀疏矩阵、链表、图、队列、二叉树、多叉树、排序、遗传算法等的实现
💻 C
字号:
/*  hd.c - Hex dump code
 *
 *  HD - Hexadecimal Dump program
 *
 *  Copyright (C) 2000  Richard Heathfield
 *                      Eton Computer Systems Ltd
 *                      Macmillan Computer Publishing
 *
 *  This program is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU General
 *  Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will
 *  be useful, but WITHOUT ANY WARRANTY; without even the
 *  implied warranty of MERCHANTABILITY or FITNESS FOR A
 *  PARTICULAR PURPOSE.  See the GNU General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU General
 *  Public License along with this program; if not, write
 *  to the Free Software Foundation, Inc., 675 Mass Ave,
 *  Cambridge, MA 02139, USA.
 *
 *  Richard Heathfield may be contacted by email at:
 *     binary@eton.powernet.co.uk
 *
 */


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

void Help(void)
{
  char *HelpMsg[] =
  {
    "hd",
    "Usage: hd [-c<cols>] filename",
    "Examples: hd foo.bin",
    "          hd -c32 core.dump",
    "Reads filename, writes hex dump to",
    "standard output. cols, if supplied, is the",
    "number of characters displayed on each line.",
    "The default is 16."
  };

  size_t ThisMsg;
  size_t NumMsgs;
  
  NumMsgs = sizeof HelpMsg / sizeof HelpMsg[0];

  for(ThisMsg = 0; ThisMsg < NumMsgs; ThisMsg++)
  {
    puts(HelpMsg[ThisMsg]);
  }
}

int HexDump(char *Filename, size_t Width)
{
  int Status = EXIT_SUCCESS;

  FILE *InFilePtr;

  /* Next line relies on hexadecimal digits being
   * representable in 4 bits (which it is), and
   * ensures that we do not rely on there being
   * only 2 nybbles in a byte. (On some systems,
   * CHAR_BIT is /not/ 8.)
   */
  int HexitsPerByte = (CHAR_BIT + 3) / 4;

  unsigned char *TextBuffer;
  unsigned char *HexBuffer;

  size_t BytesRead;
  size_t ThisByte;
  size_t HexBuffWidth;

  /* First, we acquire the necessary external resources.
   * If any of these acquisitions fails, we display an
   * error message and return to the caller.
   *
   * The required resources are: a file pointer to the
   * file from which we wish to read, a text buffer for
   * reading the data into, and a hex buffer for storing
   * the hex dump itself.
   */
  InFilePtr = fopen(Filename, "rb");
  if(NULL == InFilePtr)
  {
    printf("Can't open file %s for reading.\n",
           Filename);
    Status = EXIT_FAILURE;
  }
  else
  {
    HexBuffWidth = Width * (HexitsPerByte + 1);

    TextBuffer = malloc(Width + 1);
    if(NULL == TextBuffer)
    {
      printf("Couldn't allocate %u bytes.\n",
             (unsigned)(Width + 1));
      Status = EXIT_FAILURE;
    }
    else
    {
      HexBuffer = malloc(HexBuffWidth + 1);
      if(NULL == HexBuffer)
      {
        printf("Couldn't allocate %u bytes.\n",
               (unsigned)(HexBuffWidth + 1));
        Status = EXIT_FAILURE;
      }
      else
      {
        /* We process 'Width' bytes at a time.
         * By storing the number of bytes actually
         * read (which we obtain by specifying
         * a block size of 1 and a count of 'Width'),
         * we can handle the last few bytes of a
         * file that isn't an exact multiple of the
         * specified width, in the same loop as the
         * bulk of the file.
         */
        while((BytesRead = fread(TextBuffer,
                                 1,
                                 Width,
                                 InFilePtr)) > 0)
        {
          for(ThisByte = 0;
              ThisByte < BytesRead;
              ThisByte++)
          {
            /* Insert hex code into hex buffer
             * at the appropriate offset
             */
            sprintf((char *)(HexBuffer +
                             ThisByte *
                             (HexitsPerByte + 1)),
                    "%0*X ",
                    HexitsPerByte,
                    (unsigned)TextBuffer[ThisByte]);
            /* We don't want to print unprintable
             * characters, so we'll replace them with
             * a '.' character (a common convention).
             */
            if(!isprint(TextBuffer[ThisByte]))
            {
              TextBuffer[ThisByte] = '.';
            }
          }

          /* null-terminating a string buffer is
           * commonly regarded as a good move :-)
           */
          TextBuffer[ThisByte] = '\0';

          printf("%-*.*s | %s\n",
                 HexBuffWidth,
                 HexBuffWidth,
                 HexBuffer,
                 TextBuffer);
        }
        if(ferror(InFilePtr))
        {
          printf("Warning: read error on file %s.\n",
                 Filename);
          Status = EXIT_FAILURE;
        }

        /* release memory resource */
        free(HexBuffer);
      }

      /* release memory resource */
      free(TextBuffer);
    }

    /* release file resource */
    fclose(InFilePtr);
  }

  return Status;
}


int main(int argc, char **argv)
{
  int Status = EXIT_SUCCESS;
  size_t NumChars = 16;
  char *EndPointer;
  int FilenameArg = 1;

  if(argc < 2 ||  strcmp("-?", argv[1]) == 0)
  {
    Help();
    Status = EXIT_FAILURE;
  }
  else
  {
    if(memcmp(argv[1], "-c", 2) == 0)
    {
      FilenameArg = 2;
      NumChars = (size_t)strtoul(argv[1] + 2,
                                 &EndPointer,
                                 10);

      if(EndPointer == argv[1] + 2 || NumChars < 1)
      {
        Help();
        puts("\nInvalid or missing argument.");
        Status = EXIT_FAILURE;
      }
    }
  }

  if(EXIT_SUCCESS == Status)
  {
    Status = HexDump(argv[FilenameArg], NumChars);
  }

  return Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -