RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1182191
Accepted
kaylil_01
kaylil_01
Asked:2020-09-25 06:34:23 +0000 UTC2020-09-25 06:34:23 +0000 UTC 2020-09-25 06:34:23 +0000 UTC

如何正确地将一定数量的字节读入结构?

  • 772

我有结构:

struct map {
   void* key;
   void* value;
}

我正在将整个二进制文件读入缓冲区:

void* buffer = malloc(size);

fseek(file, 0, SEEK_SET);

fread(buffer, size, 1, file);

我需要将缓冲区中的一定数量的字节映射到结构上。那些。让我们从缓冲区中获取 40 个字节,在键字段中获取 20 个字节,在值中获取 20 个字节,这样遍历整个缓冲区并将其作为映射数组返回。实际上问题是:如何读取 20 个字节的 key 和 20 个字节的 value?

c++
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Harry
    2020-09-25T11:52:53Z2020-09-25T11:52:53Z

    你不能只接受和计算指针。您需要用尺寸写下每个结构,例如

    map m;
    ...
    int len = strlen(m.key);
    fwrite(&len,sizeof(len),1,file);
    fwrite(m.key,len+1,1,file);
    len = strlen(m.value);
    fwrite(&len,sizeof(len),1,file);
    fwrite(m.value,len+1,1,file);
    

    然后,一边阅读,一边交替阅读……

    map m;
    ...
    int len;
    fread(&len,sizeof(len),1,file);
    m.key = malloc(len);
    fread(m.key,len+1,1,file);
    fread(&len,sizeof(len),1,file);
    m.value = malloc(len);
    fread(m.value,len+1,1,file);
    

    或多或少是这样的。

    否则,您只是在写入和读取指针,而不是它们指向的数据。

    如果您将结构描述为

    struct map {
       char key[20];
       char value[20];
    };
    

    那么事情就不同了,可以直接读写。但是您提供的选项是不可能的。

    • 4
  2. Best Answer
    avp
    2020-09-26T05:33:08Z2020-09-26T05:33:08Z

    假设,根据结构 ( map) 的名称判断,映射是假设的,即 直接访问缓冲区中的数据。

    然后,如果您使用带有指针的结构,那么除了缓冲区之外,您还需要为结构数组分配内存,然后用缓冲区中的地址填充它并返回它。

    让我们得到类似的东西

    struct map * 
    foo (FILE *f, size_t size)
    {
       char *buffer = malloc(size); // предположим, что size в самом деле кратен 40 и проверять это не будем
       struct map *p = malloc(size / 40 * sizeof(struct map));
    
       rewind(f);
       fread(buffer, size, 1, f);
    
       size_t i = 0;
       for (char *t = buffer; t < buffer + size; t += 40, i++) {
          p[i].key = t; p[i].value = t + 20;
       }
    
       return p;
    }
    

    完成后删除缓冲区

    struct map *m_map = foo(input_file, data_size);
    
    .....
      for (int i = 0; i < data_size / 40; i++)
        printf("key: %s  value: %s\n", m_map[i].key, m_map[i].value);
    .....
    
     free (m_map[0].key);
    

    然后映射(生成的结构数组)

     free (m_map);
    

    如果你想直接处理缓冲区中的数据,那么你需要使用这个结构

    struct c_map {
      char key[20];
      char value[20];
    };
    

    然后我们得到以下读取数据的函数

     struct c_map *
     bar (FILE *f, size_t size)
     {
        char *buffer = malloc(size); // предположим, что size в самом деле кратен 40 и проверять это не будем
    
        rewind(f);
        fread(buffer, size, 1, f);
    
        return (struct c_map *)buffer;
     }
    

    你得到一个映射到缓冲区的结构数组,在处理结束时,像这样删除缓冲区

     struct c_map *m_map = bar(input_file, data_size);
     .....
      for (int i = 0; i < data_size / 40; i++)
        printf("key: %s  value: %s\n", m_map[i].key, m_map[i].value);
     .....
     free(m_map);
    

    当然,在这两种情况下,如果文件中每 19 个字节后没有二进制零(行终止符),那么它也不会出现在结构字段中。

    • 4
  3. Yaroslav
    2020-09-25T16:07:35Z2020-09-25T16:07:35Z

    可以这样实现

    struct map
    {
      uint8_t key[40];
      uint8_t value[40];
    }__attribute__((packed));
    
    uint8_t * buffer = malloc(size);
    fread(buffer, size, 1, file);
    
    map * begin_map = (map*)buffer;
    map * current_map = begin_map;
    map * end_map = (map*)(bufffer + size);
    
    /*теперь к поля структуры можно обращаться  */
    current_map->key;
    current_map->value;
    /*перемещаться между структурами */ 
    current_map += number;
    current_map -= number;
    /*но нужно проверять не вышли за пределы данных*/
    if (current_map > begin_map) {
       ...
    }
    if (current_map < end_map) {
       ...
    }
    
    • 1
  4. Yakov
    2020-09-26T04:33:49Z2020-09-26T04:33:49Z

    或多或少是这样的。如果我正确理解了一切。不要踢你的脚。凭记忆在笔记本上写的。也许某处错了。

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef 
    struct 
    {
        union
        { 
            char[20] key; 
            void* pkey;
        } 
        union
        { 
            char[20] value; 
            void *pvalue;
        }
    } MYMAP, *PMYMAP;
    
    void main()
    {
        void* buffer;
        int i;
        long size;
        fpos_t *pos; /* fpos_t определен в stdio.h */
        pos = &l;
        FILE *file = fopen("data.txt", "r");
        fseek(file, 0, SEEK_END);
        fgetpos(file, (fpos_t*) &size); 
        fseek(file, 0, SEEK_SET);
        buffer = malloc(size+2);
        fread(buffer, size,  size, file);
        //после чтения файла в буфер просто делим его на куски. 
        for(i=0;i<size/sizeof(MYMAP);i++)
        {
            //т.к. это пример, положим, что значения key и value в файле завершаются нолем и будут выводиться как си-строка. если нет эту часть надо исправить.
            printf("key = %s, value = %s", 
            PMYMAP(buffer+i*sizeof(MYMAP)).key,
            PMYMAP(buffer+i*sizeof(MYMAP)).value);
        }
    }
    
    • -1

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5