有没有办法在不修改两个指针的值的情况下执行additem函数?

时间:2015-10-11 04:04:12

标签: c function pointers memory-management

这是我的代码:

#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内存地址,另一个用于更新struct的堆栈内存地址。

我想知道是否有更新函数的方法并调用它,以便只传入一个指针并进行更新。例如:

additem(&stuff,"Test");

我希望整体程序功能仍然相同,但我不想在结构中使用固定字符数组,因为这会浪费宝贵的内存。

1 个答案:

答案 0 :(得分:0)

struct中捆绑属于item-set-cum-char-buffer的所有内容,然后将指向该结构的指针传递给您的函数。如果不修改结构,例如打印项目集时,请传递const指针。

您还应该提供初始化和清理项集的函数,以便cleint代码不必担心集的实现细节。

您的代码可能如下所示:

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