从mmaped结构数组中删除struct

时间:2015-01-03 00:38:10

标签: c arrays struct mmap

问题:我有一个名为" med"保持有关药物(关键字,名称,最小数量和数量)的信息,每个医学院都有一个唯一的关键。我使用mmap将这些结构的数组存储在内存映射文件中。现在我想从数组中删除一个特定的med(struct),但它不起作用......

代码

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#define NUM_MEDS 1000 
#define FILESIZE (NUM_MEDS * sizeof(struct med))

struct med
{
   int key;
   char name[25];
   int quant_min;
   int quant;
};

int main(void)
{
    int fd;
    int result;
    struct med *map;  /* mmapped array of structs */

    fd = open("meds.dat", O_RDWR | O_CREAT, (mode_t)0600);
    if (fd == -1)
    {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    result = ftruncate(fd, FILESIZE); 
    if (result == -1)
    {
        close(fd);
        perror("Error calling lseek() to 'stretch' the file");
        exit(EXIT_FAILURE);
    }

    /* Now the file is ready to be mmapped.  */
    map = (struct med *)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    struct med m;

    printf("Please enter the code of med: ");
    scanf("%d",&m.key);

    int j;
    for (j = 0; j < NUM_MEDS; j++)
    {
        if (m.key == map[j].key)
        {
            for(j; j < NUM_MEDS - 1; j++)
            {
            map[j] = map[j+1];
            }
            printf("Med %d removed with success\n",m.key);
            break;
        }
     }

     if (munmap(map, FILESIZE) == -1)
     {
         perror("Error un-mmapping the file");
     }

      close(fd);
      return 0;
}

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

功能的实际变化?有一对。首先,在将数据下载到列表中之后,必须使数据中的最后一个条目无效。其次,您必须在删除一些条目后重新计算条目数。

目前,除了EOF之外,你没有其他方法可以阻止输入。这意味着我通过一次运行程序添加了数据;然后我不得不第二次运行该程序来删除一些数据。但是,它似乎正常工作。我添加了键1,2,3,4然后删除了2,4,剩下的列表是1,3,这对我来说是正确的。

我在回答相关问题mmap and struct in C时通过电子邮件询问了我。

#define _XOPEN_SOURCE 800
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#define FILEPATH "/tmp/mmapped.bin"
#define NUM_MEDS 1000
#define FILESIZE (NUM_MEDS * sizeof(struct med))

struct med
{
    int key;
    char name[25];
    int quant_min;
    int quant;
};

static int find_num_entries(struct med *map, int max_meds);
static int get_new_key(struct med *map, int num_meds, int *key);
static int med_in_map(struct med *map, int num_meds, int key);
static int remove_key_med(struct med *map, int num_meds, int *key);
static int remove_med(struct med *map, int num_meds, int key);
static void insert_med_mmap(void);
static void interface(void);
static void list_meds_mmap(void);
static void load_meds_mmap(void);
static void print_med(char *tag, const struct med *med);
static void remove_med_mmap(void);
static void search_med_mmap(void);

int main(void)
{
    interface();
    return 0;
}

// interface
void interface(void)
{
    printf("\n");
    printf("=> Management and administration of Meds \n");
    printf("\n");
    printf("=> Mmap version \n");
    printf("\n");
    printf("Choose your operation \n");
    printf("1- Insert med \n");
    printf("2- Remove med \n");
    printf("3- Search med \n");
    printf("4- List meds ordered by name \n");
    printf("5- Load meds \n");
    printf("6- Exit \n");

    int a;
    scanf("%d", &a);
    switch (a)
    {
    case 1:
        printf("\n");
        printf("Insert med \n");
        insert_med_mmap();
        break;
    case 2:
        printf("\n");
        printf("Remove med \n");
        remove_med_mmap();
        break;
    case 3:
        printf("\n");
        printf("Search med \n");
        search_med_mmap();
        break;
    case 4:
        printf("\n");
        printf("List meds ordered by name \n");
        list_meds_mmap();
        break;
    case 5:
        printf("\n");
        load_meds_mmap();
        break;
    case 6:
        return;
    }
}

static void print_med(char *tag, const struct med *med)
{
    printf("%s: %4d: Q(%2d, min %2d): %s\n",
           tag, med->key, med->quant, med->quant_min, med->name);
}

static int med_in_map(struct med *map, int num_meds, int key)
{
    int i;
    for (i = 0; i < num_meds; i++)
    {
        if (key == map[i].key)
        {
            printf("The med with key %d already exists in the file. \n", key);
            return 1;
        }
    }
    return 0;
}

static int get_new_key(struct med *map, int num_meds, int *key)
{
    while (printf("Type the key of med: ") > 0 && scanf("%d", key) == 1)
    {
        if (med_in_map(map, num_meds, *key) == 0)
            return 0;
    }
    return EOF;
}

static int find_num_entries(struct med *map, int max_meds)
{
    int i;
    for (i = 0; i < max_meds; i++)
    {
        if (map[i].key == 0)
            break;
    }
    return i;
}

static int remove_med(struct med *map, int num_meds, int key)
{
    int i;
    for (i = 0; i < num_meds; i++)
    {
        if (key == map[i].key)
        {
            for ( ; i < num_meds - 1; i++)
            {
                map[i] = map[i + 1];
            }
            printf("Med %d removed with sucess\n", key);
            map[i].key = 0;
            map[i].name[0] = '\0';
            map[i].quant = 0;
            map[i].quant_min = 0;
            return 0;
        }
    }
    return 1;
}

static int remove_key_med(struct med *map, int num_meds, int *key)
{
    while (printf("Type the key of med: ") > 0 && scanf("%d", key) == 1)
    {
        if (remove_med(map, num_meds, *key) == 0)
            return 0;
    }
    return EOF;
}

// load meds
void load_meds_mmap(void)
{
    printf("Test \n");
}

// insert med with mmap
void insert_med_mmap(void)
{
    int fd;
    int result;
    struct med *map;  /* mmapped array of structs */

    fd = open(FILEPATH, O_RDWR | O_CREAT, (mode_t)0600);
    if (fd == -1)
    {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    result = ftruncate(fd, FILESIZE);
    if (result == -1)
    {
        close(fd);
        perror("Error calling lseek() to 'stretch' the file");
        exit(EXIT_FAILURE);
    }

    map = (struct med *)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    /* Input loop */
    int num_meds;
    for (num_meds = find_num_entries(map, NUM_MEDS); num_meds < NUM_MEDS; num_meds++)
    {
        struct med m;
        memset(&m, '\0', sizeof(m));

        if (get_new_key(map, num_meds, &m.key) == EOF)
            break;

        printf("Name of med: ");
        if (scanf("%s", m.name) != 1)
            break;
        printf("Quant. min. of med: ");
        if (scanf("%d", &m.quant_min) != 1)
            break;
        printf("Quant. of med: ");
        if (scanf("%d", &m.quant) != 1)
            break;

        map[num_meds] = m;

        printf("Med %d saved.\n", m.key);
    }

    /* Output loop */
    printf("\nRecorded meds:\n");
    int i;
    for (i = 0; i < num_meds; i++)
    {
        char buffer[32];
        snprintf(buffer, sizeof(buffer), "M%.4d", i);
        print_med(buffer, &map[i]);
    }

    /* Don't forget to free the mmapped memory */
    if (munmap(map, FILESIZE) == -1)
    {
        perror("Error un-mmapping the file");
        /* Decide here whether to close(fd) and exit() or not. Depends... */
    }

    /* Un-mmapping doesn't close the file, so we still need to do that.  */
    close(fd);
}

// remove med with mmap
void remove_med_mmap(void)
{
    int fd;
    int result;
    struct med *map;  /* mmapped array of structs */

    fd = open(FILEPATH, O_RDWR | O_CREAT, (mode_t)0600);
    if (fd == -1)
    {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    result = ftruncate(fd, FILESIZE);
    if (result == -1)
    {
        close(fd);
        perror("Error calling lseek() to 'stretch' the file");
        exit(EXIT_FAILURE);
    }

    /* Now the file is ready to be mmapped.  */
    map = (struct med *)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    /* Input loop */
    int num_meds;
    for (num_meds = find_num_entries(map, NUM_MEDS); num_meds < NUM_MEDS; num_meds++)
    {
        struct med m;
        memset(&m, '\0', sizeof(m));

        if (remove_key_med(map, num_meds, &m.key) == EOF)
            break;
    }

    /* Partial bug fix */
    num_meds = find_num_entries(map, NUM_MEDS);


    /* Output loop */
    printf("\nRecorded meds:\n");
    int i;
    for (i = 0; i < num_meds; i++)
    {
        char buffer[32];
        snprintf(buffer, sizeof(buffer), "M%.4d", i);
        print_med(buffer, &map[i]);
    }

    /* Don't forget to free the mmapped memory */
    if (munmap(map, FILESIZE) == -1)
    {
        perror("Error un-mmapping the file");
        /* Decide here whether to close(fd) and exit() or not. Depends... */
    }

    /* Un-mmapping doesn't close the file, so we still need to do that.  */
    close(fd);
    return;
}

void search_med_mmap(void)
{
    printf("Test \n");
}

void list_meds_mmap(void)
{
    printf("Test \n");
}