C - Using fscanf for reading hexadecimal and characters from files

Viewed 163

I have two files. The first file (in the pointer key_file) has the following content in hexadecimal (notice that every two characters corresponds to a hexadecimal byte):

18FC5E66F9F205488BFC0E9E

And the other file (in the pointer p_text_file) has the following content

hernandariov

I want to write the bitwise XOR between these two values and save the result in another file (in the pointer c_text_file). I write the following (abbreviated) code in C:

char p_text_char;
unsigned char k_char;
for(int i = 0; i < LEN; i++) {
    fscanf(key_file, "%2hhX", &k_char);
    fscanf(p_text_file, "%c", &p_text_char); 
    fprintf(c_text_file, "%02X", k_char ^ p_text_char);
}

But when I execute the code, it exits with a non-zero value, i.e, there is an error. After try many solutions, I found that if I change the type of p_text_char to int, the code works pretty well, but I want to know why. In fact, I want to keep p_text_char as char and k_char as unsigned char because these are the natural types and sizes for this variables in the problem I am working on (the one-time-pad encryption scheme). I am working on Windows with MinGw compiler.

Thank you.

- EDIT -

After run a debugger in this code, I found that there is a "segmentation fault". I try to minimize the code in order to find the error. First, I try the following code with the files as showed before:

#include <stdio.h>

#define LEN 12

int main() {

    FILE *key_file;

    key_file = fopen("key.txt", "r");

    if(key_file == NULL) {
        printf("ERROR: cannot read the files.");
        return 1;
    }

    unsigned char k_char;
    for(int i = 0; i < LEN; i++) {
        fscanf(key_file, "%2hhX", &k_char);
    }

    fclose(key_file);
    return 0;
}

After one iteration of the for loop, the VS Code editor shows me a "segmentation fault". And when I change k_char to int, everything works fine. I will keep posting my findings about this problem.

1 Answers

The version of VS C that OP is using may not understand "%hhX". Formally this is undefined behavior and *scanf() may ignore "hh". Thus code "works" with an int.

To cope with C89-like compilers that lack "hh" understanding, use an intermediate object.

// fscanf(key_file, "%2hhX", &k_char);
unsigned utemp = 0;
fscanf(key_file, "%2X", &utemp);
k_char = utemp;

... or use a compiler that conforms at least to the 21 year old C99 standard, if not C11 or C17. C2x due out in a year or two.

Related