C语言 - 使用fscanf从文件中读取十六进制和字符

3

我有两个文件。第一个文件(在指针key_file中)以十六进制的形式包含以下内容(请注意,每两个字符对应一个十六进制字节):

18FC5E66F9F205488BFC0E9E

另一个文件(在指针 p_text_file 中)具有以下内容

hernandariov

我想要对这两个值执行按位异或运算,将结果保存到另一个文件中(指针为c_text_file)。我用下面的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);
}

但是当我执行代码时,它以非零值退出,即存在错误。尝试了很多解决方案后,我发现如果我将 p_text_char 的类型更改为 int,那么代码就可以正常工作,但我想知道原因。实际上,我希望保持 p_text_char 作为 char,并且 k_char 作为 unsigned char,因为这些是在我正在解决的问题(单次密码加密方案)中变量的自然类型和大小。我正在使用MinGw编译器的Windows系统。

谢谢。

- 编辑 -

在运行此代码的调试器中,我发现存在“分段错误”。为了找到错误,我尝试最小化代码。首先,我使用如下所示的文件尝试了以下代码:

#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;
}

在for循环的一次迭代后,VS Code编辑器显示了“分段错误”。当我将k_char更改为int时,一切正常。我会继续发布关于这个问题的发现。


1
也许你遇到了崩溃问题?你尝试在调试器中运行程序了吗?它告诉你什么? - Some programmer dude
你是否记得要检查错误?例如,如果fopen调用失败而你没有检测到它,会发生什么? - Some programmer dude
嗨,感谢您的回复@Someprogrammerdude,我将在调试器中检查它,但我已经使用条件语句询问每个文件中的NULL指针来检查文件是否已打开。我认为这与变量类型有关。我会继续搜索。 - Lemark
1
首先,使用调试器查看发生了什么。如果您无法自行解决问题,请在问题中包含一个 [mcve],并告诉我们程序中崩溃发生的时间和位置以及所有相关变量的值。 - Some programmer dude
@Someprogrammerdude,调试后我将代码缩减到答案中的“EDIT”部分。使用GDB的VS Code调试器显示了一个“分段错误”,我会继续寻找这个错误。谢谢你的帮助。 - Lemark
1个回答

2
OP正在使用的VS C版本可能无法理解"%hhX"。严格来说,这是一种未定义行为*scanf()可能会忽略"hh"。因此,这段代码可以在int中运行。
为了应对类似于C89的编译器缺乏对"hh"的理解,可以使用一个中间对象。
// fscanf(key_file, "%2hhX", &k_char);
unsigned utemp = 0;
fscanf(key_file, "%2X", &utemp);
k_char = utemp;

"...或者使用符合至少21年前的C99标准,如果不是C11或C17的编译器。C2x将在一两年内发布。"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接