gpt4 book ai didi

c - 读取 .bin 文件的某些部分(例如从 11 日到 23 日): hex into int, 字符串。 C

转载 作者:行者123 更新时间:2023-11-30 16:29:03 25 4
gpt4 key购买 nike

我想阅读例如。十六进制 .bin 文件中的第 11 个和第 23 个数字如下所示:https://imgur.com/b4RzPjw将某些部分打印为整数或将其他部分打印为名称(字符串)。 (最好不使用任何[],仅对指针进行操作)

我的示例 .bin 文件包含:前 4 个十六进制数字(蓝色突出显示)是名称的长度,然后 2 个数字是 ASCII 形式的名称。接下来的4个数字(蓝色下划线)是姓氏的长度(红色下划线),最后一个数字是索引。

我的尝试:
将整个 .bin 文件加载到缓冲区后,与此处所示的完全一样:http://www.cplusplus.com/reference/cstdio/fread/ ,我痛苦地尝试了多种方法将此缓冲区的部分分配给变量(或结构),然后使用格式 printf 它,只是为了看看分配了什么。

 char *name_length = malloc(4);
char *pEnd;
for(*buffer=0; *buffer<4; *buffer++) {
sscanf(buffer, "%s", name_length);
long int i = strtol (buffer, &pEnd, 16);
printf("%x", i);
}

上面(错误的)代码打印 0000 (我想它从根本上就已经完全腐烂了,尽管我不知道为什么);如果有一种优雅的方法来加载已经构建的缓冲区部分,这里是声明:

 struct student_t
{
char name[20];
char surname[40];
int index;
};

我能得到的“最接近”结果是另一个代码,它打印“2000”。来 self 的 .bin 文件:“02 00 00 46 2E”,这意味着“2 0 0 0/length/F./string/”

  for(int i=0; i<4; i++)
printf("%d", buffer[i]); //it's supposed to print first 4 hex digits...
for(int j=5; j<7; j++)
printf("%s", &buffer[j]); //it's supposed to print from 5th to 7th...

非常感谢您的帮助和指导。

最佳答案

考虑到我将您的确切二进制数据保存在名为 data.bin 的文件中,下面是一个示例:

代码.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <errno.h>

#define FILE_NAME "data.bin"


typedef struct Record_ {
uint32_t nameLen, surnameLen;
char *name, *surname;
} Record;


void printRecord(Record record) {
printf("\nPrinting record:\n Name length: %u\n Name: [", record.nameLen);
if ((record.nameLen != 0) && (record.name != NULL)) {
char *pc;
for (pc = record.name; pc < record.name + record.nameLen; pc++) {
printf("%c", *pc);
}
}
printf("]\n Surname length: %u\n Surname: [", record.surnameLen);
if ((record.surnameLen != 0) && (record.surname != NULL)) {
char *pc;
for (pc = record.surname; pc < record.surname + record.surnameLen; pc++) {
printf("%c", *pc);
}
}
printf("]\n");
}


void clearRecord(Record *pRecord) {
free(pRecord->name);
free(pRecord->surname);
memset(pRecord, 0, sizeof(Record));
}


int readRecord(FILE *pFile, Record *pRecord) {
size_t readBytes = fread(&pRecord->nameLen, sizeof(pRecord->nameLen), 1, pFile);
if (pRecord->nameLen != 0) {
pRecord->name = malloc(pRecord->nameLen);
readBytes= fread(pRecord->name, 1, pRecord->nameLen, pFile);
}
readBytes = fread(&pRecord->surnameLen, sizeof(pRecord->surnameLen), 1, pFile);
if (pRecord->surnameLen != 0) {
pRecord->surname = malloc(pRecord->surnameLen);
readBytes = fread(pRecord->surname, 1, pRecord->surnameLen, pFile);
}
return 0;
}


int main() {
FILE *fp = fopen(FILE_NAME, "r+b");
if (fp == NULL)
{
printf("Error opening file: %d\n", errno);
return 1;
}
Record record = {0, 0, NULL, NULL};
printRecord(record);
int ret = readRecord(fp, &record);
if (ret)
{
printf("readRecord returned %d\n", ret);
fclose(fp);
return 2;
}
printRecord(record);
clearRecord(&record);
fclose(fp);
return 0;
}

注释:

  • After loading entire .bin file to buffer exactly like presented here

    通常,这不是一个好主意。只阅读您需要的内容。想象一下,您想要从数百 MiB 大的文件中读取 10 个字节。这完全是资源浪费,有时甚至可能导致崩溃

  • 看来您这里有一个简单的协议(protocol):

    1. 4 个字节名称长度 - 这是一个 uint32_t
    2. name 的名称长度给出的可变字节数 - 这是一个 char *,因为它的长度在编译时未知(您可以有一个像这样的数组:char[SOME_MAX_NAME_LENGTH],您可以确定在前一个字段中永远不会有大于SOME_MAX_NAME_LENGTH的值,但我更喜欢这种方法)<
    3. #1.相同的内容应用于姓氏长度
    4. #2.相同的内容应用于姓氏


    这映射到Record结构(是的,成员顺序并不重要,只有初始化顺序)。事情还可以更进一步,因为姓氏的数据与姓名的数据重复,因此可能存在一个包含姓名的内部结构em> data 和 Record 仅包含一个包含该结构的 2 个元素的数组。
    但即使这样事情会更简单(而且函数中的代码也会更短 - 没有重复),我也没有这样做,因为它可能不太明显

  • printRecord - 以用户友好的方式显示Record数据(当printfing时,您可以注意到这里的指针逻辑单独的字符)

  • clearRecord - 释放 char * 成员占用的内存并将所有内容初始化为0

  • readRecord - 从文件读取数据并填充记录

    • 没有有任何错误处理,因为代码已经相当长了。但您应该始终检查并处理错误(函数返回码:例如fread)
    • 从各个字节重建(整数)值时要小心,因为字节顺序可能会导致意外结果。检查[SO]: Python struct.pack() behavior(@CristiFati's answer) (当然,Google)有关此主题的更多信息
    • 读取 4 个字节的大小,然后(分配并)读取“size”字节的字符串(我在这里可能是错的,但我不认为 sscanf(函数系列)应该处理二进制数据(字符串除外))

输出:

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q052085090]> gcc code.c -o code.exe && ./code.exe

Printing record:
Name length: 0
Name: []
Surname length: 0
Surname: []

Printing record:
Name length: 2
Name: [F.]
Surname length: 13
Surname: [MurrayAbraham]

关于c - 读取 .bin 文件的某些部分(例如从 11 日到 23 日): hex into int, 字符串。 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52085090/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com