Удалить структуру из массива mmaped структур

Проблема: у меня есть структура под названием "мед" для хранения информации о лекарствах (ключ, имя, минимальное количество и количество), причем каждое лекарство имеет уникальный ключ. Я сохранил массив этих структур в файле отображения памяти, используя mmap. Теперь я хочу удалить определенное лекарство (структуру) из массива, но это не работает...

Код:

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

Кто-нибудь может помочь?


person MrPedru22    schedule 03.01.2015    source источник
comment
В чем ошибка? Только not working никому не помогает. Кроме того, размер файла никогда не меняется, поэтому в этом файле все еще есть 1000 элементов.   -  person D3Hunter    schedule 03.01.2015
comment
Конечный элемент массива является копией предыдущего, поэтому подлежит удалению.   -  person Jake0x32    schedule 03.01.2015
comment
Это продолжение mmap и struct в C.   -  person Jonathan Leffler    schedule 03.01.2015


Ответы (1)


Фактические изменения в функциональности? Была пара. Во-первых, вы должны аннулировать последнюю запись в данных после того, как вы скопировали ее вниз по списку. Во-вторых, вы должны пересчитать количество записей после того, как вы удалили некоторые из них.

На данный момент у вас нет хорошего способа остановки ввода, кроме EOF. Это означало, что я добавлял данные за один запуск программы; Затем мне пришлось запустить программу во второй раз, чтобы удалить некоторые данные. Однако, похоже, работает правильно. Я добавил ключи 1, 2, 3, 4, а затем удалил 2, 4, и в списке остались 1, 3, что мне кажется правильным.

Меня спросили об этом по электронной почте в результате ответа на связанный вопрос mmap и struct в C.< /em>

#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");
}
person Jonathan Leffler    schedule 03.01.2015