0

C programmer newcomer here.

I'm trying to open a .obj file (containing LC3 instructions) and print them in groups of 2 bytes line by line in hex. I've tried opening the file and iterating through char by char and printing in hex but I am unsure how to group the bytes together in groups of 2 to print them together. I am also printing out a group of "fffffff"s for the bytes that lead with a 1 (I assume).

void readFile(const char *fileName) {
FILE *file;

file = fopen(fileName, "rb");

    char ch;
    while ((ch = fgetc(file)) != EOF) {
        if (isprint(ch)) {
            printf("%x", ch);   
        }
        else {
            printf("%02x", ch);

            if (ch == '\n') {
                fputs("\n", stdout);
            }
        }
    }
 fclose(file);
}

The output I am looking to achieve is:

0x4500
0x2009 
0xe209 
0xa409 

But I am getting:

0x45 
0020
09fffffffe209fffffffa40956

I understand that the hex is printing the excess "ffffffff"s due to not being an unsigned char but I am struggling to print close to the desired output. Any help in printing in 2 byte groups or how to remove the "fffffff"s would be greatly appreciated, and I'm really struggling.

  • See [`while ((c = getc(fp)) != EOF)` loop won't stop](https://stackoverflow.com/questions/13694394/while-c-getcfile-eof-loop-wont-stop-executing) — `fgetc()` returns an `int` and not a `char`. – Jonathan Leffler May 29 '18 at 05:34

2 Answers2

1

The getchar() family of functions (including getc() and fgetc()) all behave similarly; they return an int, not a char. Read the values into an int and live life happy.

void readFile(const char *fileName)
{
    FILE *file = fopen(fileName, "rb");
    if (file == 0)
        return;

    int ch;
    while ((ch = fgetc(file)) != EOF)
    {
        printf("0x%.2x", ch);
        if ((ch = fgetc(file)) == EOF)
            break;
        printf("%.2x\n", ch);   
    }
    putchar('\n');

    fclose(file);
}

If there's an even number of bytes in the file, you'll get an extra newline at the end. If that's a problem, keep a record of whether you exit the loop at the top (no newline needed) or from the middle (newline needed).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

Both isprint(ch) and ch == '\n' have absolutely nothing to do with 2-byte grouping.

Perhaps you want something simple like this:

unsigned char ch;
while ((ch = (unsigned char)fgetc(file)) != EOF) {
    printf("0x%02x", ch);   
    if ((ch = (unsigned char)fgetc(file)) != EOF)
        printf("%02x", ch);
    printf("\n");
}
paddy
  • 60,864
  • 6
  • 61
  • 103
  • Thanks, this printed in the correct format, however just printed "0xffff" line by line in an infinite loop. Any suggestions? – user6394303 May 29 '18 at 04:59
  • 1
    Note that `ch` should be an `int`; it will not spot EOF because it is a negative `int` and the `unsigned char` will be promoted to a positive `int` in the range `0x00..0xFF` (0xFF for EOF, usually). – Jonathan Leffler May 29 '18 at 05:35
  • 1
    @JonathanLeffler I know this is informal, but you sir are a legend, thanks. – user6394303 May 29 '18 at 07:07