2016-08-16 3 views
-1

я следую этому вопросу What is a bitmap in C? реализовать Bitmap в С.Реализация растрового изображения в C

я разделил свой код ниже.

Проблема, с которой я столкнулся, - это правильная установка бит в заданном положении, но несколько других бит также включаются. Я поделился примером, где он ломается. Я не могу отлаживать его с двух последних дней.

#include <stddef.h> 
#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <stdbool.h> 

// assuming a char is made up of 8 bits 
enum { BITS_PER_WORD = sizeof(unsigned long) * 8 }; 
/* 
utility functions for bit position calculations 
*/ 
unsigned long word_offset(unsigned long pos){ 
    return pos/BITS_PER_WORD; 
} 

size_t bit_offset(unsigned long pos){ 
    return pos%BITS_PER_WORD; 
} 


typedef struct bitmapNode{ 
    void *mem; 
    unsigned long len; 
}bitmapNode; 


/* 
utility funtion used to set bit 
*/ 
bool setbitUtility(void* mem, unsigned long pos){ 
    unsigned long *ptr = mem; 
    ptr += word_offset(pos); 
    *ptr |= (1 << bit_offset(pos)); 
    return true; 
} 

/* 
utility funtion used to clear bit (make bit = 0) 
*/ 
bool clearbitUtility(void* mem, unsigned long pos){ 
    unsigned long *ptr = mem; 
    ptr += word_offset(pos); 
    *ptr &= ~(1 << bit_offset(pos)); 
    return true; 
} 

/* 
utility funtion used to get bit at pos 
*/ 
bool getbitUtility(void* mem, unsigned long pos){ 
    unsigned long *ptr = mem; 
    ptr += word_offset(pos); 
    return 0 != (*ptr & (1 << bit_offset(pos))); 
} 

/* 
Returns an empty bitmap node 
*/ 
bitmapNode* newBitmapNode(){ 
    bitmapNode* node = NULL; 
    node = malloc(sizeof(bitmapNode)); 
    if(node){ 
     node->len = 0; 
    } 
    return node; 
} 

/* 
Initialize a bitmap node. Expands the memory to hold bit at given position 
*/ 
bitmapNode* initBitmapNode(long long pos, bool bit){ 
    unsigned long len = word_offset(pos); 
    bitmapNode* node = NULL; 
    node = newBitmapNode(); 
    if(node){ 
     node->mem = malloc(sizeof(unsigned long) * (len + 1)); 
     if(node->mem){ 
      memset(node->mem, 0, sizeof(node->mem)); 
      node->len = len + 1; 
      bit ? setbitUtility(node->mem, pos) : clearbitUtility(node->mem, pos); 
      return node; 
     } else { 
      free(node); 
     } 
    } 
    return node; 
} 

bool getBit(bitmapNode* node, unsigned long pos){ 
    if(pos < node->len * BITS_PER_WORD){ 
     return getbitUtility(node->mem, pos); 
    } else { 
     return false; 
    } 
} 

/* 
sets the bit stored in node at given position to value passed in bit(0 or 1) 
*/ 
bool setBit(bitmapNode* node, unsigned long pos, bool bit){ 
    unsigned long len = word_offset(pos); 
    void *new_start; 
    bool ret; 
    if(pos < node->len * BITS_PER_WORD){ 
     pos = (unsigned long)pos; 
     ret = getbitUtility(node->mem, pos); 
     bit ? setbitUtility(node->mem, pos) : clearbitUtility(node->mem, pos); 
    } else { 
     pos = (unsigned long)pos; 
     node->mem = realloc(node->mem, sizeof(unsigned long) * (len + 1)); 
     if(node->mem){ 
      new_start = node->mem + node->len; 
      memset(new_start, 0, len + 1 - node->len); 
      node->len = len + 1; 
      ret = false; 
      bit ? setbitUtility(node->mem, pos) : clearbitUtility(node->mem, pos); 
     } else { 
      // have to return err 
     } 
    } 
    return ret; 
} 

int main(){ 
    bitmapNode *bitmap = initBitmapNode(0, 0); 
    char cmd[100]; 
    int n, bit; 
    unsigned long pos; 
    scanf("%d", &n); 
    bool ret = false; 
    while(n--){ 
     printf("Enter command: "); 
     scanf("%s", cmd); 
     if(strcmp(cmd, "getbit") == 0){ 
      printf("%s\n", "Enter position: "); 
      scanf("%lu", &pos); 
      ret = getBit(bitmap, pos); 
      if(ret) 
       printf("%s\n", "1"); 
      else 
       printf("%s\n", "0"); 
     } else if(strcmp(cmd, "setbit") == 0){ 
      printf("%s\n", "Enter position and bit (space separated): "); 
      scanf("%lu %d", &pos, &bit); 
      setBit(bitmap, pos, bit); 
      printf("%s\n", "OK"); 
     } 
    } 
    free(bitmap->mem); 
    free(bitmap); 
    return 0; 
} 

./a.out

Введите команду: SetBit

Введите позицию и бит (пробелами):

OK

Введите команду: getbit

Введите позицию:

Введите команду: getbit

Введите позицию:

< Это должно быть 0

+0

Это не имеет ничего общего с вашей проблемой, но быть последовательным. Используйте 'void * x' или' void * x' и делайте это последовательно, и, конечно же, предпочитайте 'void * x' по многим причинам. –

+0

@Rup: ужасный совет. Если 'calloc()' полезно, это НЕ НЕ Скрывает ошибки. И именно поэтому его следует использовать очень осторожно. –

+0

Что это за бит? setbitUtility (node-> mem, pos): clearbitUtility (node-> mem, pos); '? –

ответ

1

Вы должны смотреть через все ваши вычисления размера. Вы смешиваете размеры, выраженные в байтах и ​​sizeof (long). Вы также используете арифметику указателя для типа void (mem).

Как следствие, ваши memset звонки не очищают весь блок памяти, а всего лишь небольшую часть.

Самое важное исправление будет в setBit:

unsigned long *new_start; 


    node->mem = realloc(node->mem, sizeof(unsigned long) * (len + 1)); 
    if(node->mem){ 
     new_start = (unsigned long *)(node->mem) + node->len; // Added cast 
     memset(new_start, 0, sizeof(long) * (len + 1 - node->len)); // Multply by sizeof long to get size in bytes 
     ... 
Смежные вопросы