2015-10-11 1 views
0

Это мой код:Есть ли способ выполнить функцию additem без изменения значений двух указателей?

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

typedef struct{ 
    unsigned long sz; 
    char *item; 
} itemset; 

void additem(char** ram,itemset** items,char* thing){ 
    unsigned long sz=strlen(thing); 
    if (sz > 20000 || sz < 1){return;} 
    (**items).item=*ram; 
    (*ram)+=sz; 
    (**items).sz=sz; 
    memcpy((char*)((**items).item),thing,sz); 
    (*items)++; 
} 

void showitems(itemset* items){ 
    unsigned long ct=1; 
    while(items->sz > 0){ 
     char buf[items->sz+2]; 
     memset(buf,0,items->sz+2); 
     memcpy(buf,items->item,items->sz); 
     printf("Item %d: size: %d = %s\n",ct,items->sz,buf); 
     items++;ct++; 
    } 
} 

int main(){ 
    char itembuf[50000]; 
    itemset* myitems=(itemset*)itembuf; 
    char* mp=calloc(1,100000); 
    char* wmp=mp; 
    itemset* items=myitems; 
    additem(&wmp,&myitems,"Test"); 
    additem(&wmp,&myitems,"Tests"); 
    additem(&wmp,&myitems,"Tester"); 
    additem(&wmp,&myitems,"Testing"); 
    showitems(items); 
    printf("%s\n",mp); 
    free(mp); 

} 

После выполнения, правильный выход отображается на экране следующим образом:

Item 1: size: 4 = Test 
Item 2: size: 5 = Tests 
Item 3: size: 6 = Tester 
Item 4: size: 7 = Testing 
TestTestsTesterTesting 

Для функции AddItem работать, это требует двух указателей, которые автоматически обновляются. один для обновления адреса памяти RAM, а один - для обновления адреса памяти стека структуры.

Мне интересно, есть ли способ обновить функцию и назвать ее так, чтобы только один указатель был передан и обновлен. Например:

additem(&stuff,"Test"); 

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

+1

Этот вопрос может быть лучше подходит на код обзора HTTP: //codereview.stackexchange .com/ –

+1

Вы всегда можете связать несколько значений в структуре и передать им указатели. Затем вы можете написать функции для инициализации этой структуры и ее очистки. Вызывающий код никогда не должен беспокоиться о сохранении всех переменных в синхронизации. –

ответ

0

Свяжите все, что принадлежит вашему item-set-cum-char-buffer, в struct, а затем передайте указатели на эту структуру в свои функции. Если вы не изменяете структуру, например, когда вы печатаете набор элементов, передайте указатель const.

Вы также должны предоставить функции для инициализации и очистки набора элементов, чтобы код cleont не беспокоился о деталях реализации набора.

Ваш код может выглядеть следующим образом:

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

typedef struct{ 
    size_t length; 
    char *str; 
} Item; 

typedef struct { 
    size_t bufsize;   /* fixed size of the char buffer */ 
    size_t buflen;   /* currently used size of buffer */ 
    char *buf; 
    size_t maxitem;   /* max. number of items */ 
    size_t count;   /* current number of items */ 
    Item *item; 
} Itemset; 

int iset_init(Itemset *iset, size_t maxitem, size_t bufsize) 
{ 
    iset->buflen = 0; 
    iset->bufsize = bufsize; 
    iset->buf = malloc(bufsize); 

    iset->count = 0; 
    iset->maxitem = maxitem; 
    iset->item = malloc(maxitem * sizeof(*iset->item)); 

    if (iset->item && iset->buf) return 0; 

    free(iset->item); 
    free(iset->buf); 
    return -1; 
} 

int iset_add(Itemset *iset, char* str) 
{ 
    size_t sz = strlen(str); 

    if (iset->count >= iset->maxitem) return -1; 
    if (iset->buflen + sz + 1 > iset->bufsize) return -1; 

    iset->item[iset->count].str = &iset->buf[iset->buflen]; 
    iset->item[iset->count].length = sz; 
    iset->count++; 

    strcpy(&iset->buf[iset->buflen], str); 
    iset->buflen += sz + 1; 

    printf("%zu\n", iset->buflen); 

    return 0; 
} 

void iset_show(const Itemset *iset) 
{ 
    size_t i; 

    printf("%zu items:\n", iset->count); 

    for (i = 0; i < iset->count; i++) { 
     printf("[%d] %s (%zu letters)\n", 
      i, iset->item[i].str, iset->item[i].length); 
    } 
} 

void iset_free(Itemset *iset) 
{ 
    if (iset) { 
     free(iset->buf); 
     free(iset->item); 
    } 

    memset(iset, 0, sizeof(*iset)); 
} 

клиентский код будет выглядеть намного опрятнее:

int main() 
{ 
    Itemset iset; 

    if (iset_init(&iset, 50, 500) < 0) { 
     fprintf(stderr, "Couldn't initialise dict."); 
     exit(1); 
    } 

    iset_add(&iset, "Test"); 
    iset_add(&iset, "Tests"); 
    iset_add(&iset, "Tester"); 
    iset_add(&iset, "Testing"); 

    iset_show(&iset);  
    iset_free(&iset); 

    return 0; 
}