微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从结构数组中传递一个元素并在 C 中连接一个字符串

如何解决从结构数组中传递一个元素并在 C 中连接一个字符串

我有一个结构数组,其中包含具有以下定义的结构:

typedef struct
{
    void *data;
    void (*print)(void *);
    status_ty (*add)(void *,int);
    void (*free_element)(void *);
} element_ty;

每个元素都可以是“int”元素、“float”元素或“string”元素。

我希望能够为每个元素设置 add int 个值。

例如:

add (3,array,size_of_array);

将遍历数组并将 3 的值添加到每个元素中。

Add 总是添加一个 int 值,对于 int 和 float 元素这是正常的添加,对于字符串它应该进行连接。

例如:

  • 如果数组包含以下元素:4.2,6,"welcome" - 那么如果将 3 添加到每个元素,结果将是:7.2,9,"welcome3"

我的问题是:

  • add 获得 add 并且我传递的指针类型为 void *(结构)时,我应该如何将元素本身传递给 element_ty 函数,哪个将指向数组中的这个特定元素? 看下面我写的代码,如果有错误请告诉我

这是我的 AddToStr 函数代码

  • 接收应添加int
  • 将位于 string 中的现有 element -> data 投射到 string (?) 以便以后能够连接它?当前 data 存储为 void * 类型。
  • malloc 能够接收 int 值的字符串?
  • 再次将其投射到 void * 并将其存储在 element -> data 中?
  • free() malloc

我很困惑。

这是我目前所写的:

    void FreeStrElement(void *(element_ty *element))
{

    free(element -> data);  

}


/*------------------------------------------------------------------*/

    void AddToInt(void *(element_ty *element),int IncrementValue)
{

    int data = (int) element -> data;
    int sum = data + IncrementValue;
    element -> data = (void *) sum; 

}

/*------------------------------------------------------------------*/

void AddToFlt(void *(element_ty *element),int IncrementValue)
{

    float data = (float *) element -> data;
    float sum = data + IncrementValue;
    element -> data = (void *) *(float *)∑
}

/*------------------------------------------------------------------*/

void AddToStr(void *(element_ty *element),int IncrementValue)
{

    ??

}


/*------------------------------------------------------------------*/

void PrintStr(void *num)
{

    printf("String in the element: %s\n",(char **) &num);  

}


/*------------------------------------------------------------------*/

status_ty InitStr(const char *value,element_ty *element)
{
    element -> data = (void *)value;
    element -> print = PrintStr;
    element -> add = AddtoStr;
    element -> free_element = FreeStrElement;
    
}

解决方法

分配给每个元素的函数需要将 element* 作为输入,因为它们需要能够根据需要修改 data 成员。这对于“字符串”元素尤其重要,因为您需要能够在添加更多字符时重新分配字符串内存,这意味着为 char* 分配一个新的 data 指针。

您可以将 element* 指针作为 void* 参数传入(您说这是必需的),但是您必须将 void* 类型转换回 element* 内部函数体。

尝试这样的事情:

typedef struct
{
    void *data;
    void (*print)(void *);
    status_ty (*add)(void *,int);
    void (*free_element)(void *);
} element_ty;

/*------------------------------------------------------------------*/

void FreeStrElement(void *element)
{
    element_ty *p_element = (element_ty *) element;
    free(p_element->data);
}

/*------------------------------------------------------------------*/

status_ty AddToInt(void *element,int IncrementValue)
{
    element_ty *p_element = (element_ty *) element;
    int *p_value = (int*) &(p_element->data);
    *p_value += IncrementValue;
    return ...;
}

/*------------------------------------------------------------------*/

status_ty AddToFlt(void *element,int IncrementValue)
{
    element_ty *p_element = (element_ty *) element;
    float *p_value = (float*) &(p_element->data);
    *p_value += IncrementValue;
    return ...;
}

/*------------------------------------------------------------------*/

status_ty AddToStr(void *element,int IncrementValue)
{
    element_ty *p_element = (element_ty *) element;
    char *p_str = (char*) p_element->data;

    char *new_str = realloc(p_str,strlen(p_str) + 13);
    if (!new_str) return ...;

    sprintf(new_str,"%s%d",p_str,IncrementValue);

    p_element->data = new_str;

    return ...;
}

/*------------------------------------------------------------------*/

void PrintInt(void *element)
{
    element_ty *p_element = (element_ty *) element;
    int *p_value = (int*) &(p_element->data);
    printf("Integer in the element: %d\n",*p_value);
}

/*------------------------------------------------------------------*/

void PrintFlt(void *element)
{
    element_ty *p_element = (element_ty *) element;
    float *p_value = (float*) &(p_element->data);
    printf("Float in the element: %f\n",*p_value);
}

/*------------------------------------------------------------------*/

void PrintStr(void *element)
{
    element_ty *p_element = (element_ty *) element;
    char *p_str = (char*) p_element->data;
    printf("String in the element: %s\n",p_str);
}

/*------------------------------------------------------------------*/

status_ty InitInt(int value,element_ty *element)
{
    int *p_value = (int*) &(element->data);
    *p_value = value;
    element->print = &PrintInt;
    element->add = &AddToInt;
    element->free_element = NULL;

    return ...;
}

/*------------------------------------------------------------------*/

status_ty InitFlt(float value,element_ty *element)
{
    float *p_value = (float*) &(element->data);
    *p_value = value;
    element->print = &PrintFlt;
    element->add = &AddToFlt;
    element->free_element = NULL;

    return ...;
}

/*------------------------------------------------------------------*/

status_ty InitStr(const char *value,element_ty *element)
{
    element->data = strdup(value);
    element->print = &PrintStr;
    element->add = &AddToStr;
    element->free_element = &FreeStrElement;

    return ...;
}

/*------------------------------------------------------------------*/

然后你可以做这样的事情:

void add (int value,element_ty *elements,int n) {
    for(int i = 0 i < n; ++i) {
        element_ty *elem = &elements[i];
        elem->add(elem,value);
    }
}

void print (element_ty *elements,int n) {
    for(int i = 0 i < n; ++i) {
        element_ty *elem = &elements[i];
        elem->print(elem);
    }
}

void free_elements (element_ty *elements,int n) {
    for(int i = 0 i < n; ++i) {
        element_ty *elem = &elements[i];
        if (elem->free_element) elem->free_element(elem);
    }
}

话虽如此,这种方法假设 sizeof(int)sizeof(float) sizeof(void*),通常是这种情况,但不能保证。

这种方法也违反了严格别名规则。您可以使用 memcpy() 来避免这种情况,但使用 union 会更容易、更简洁(它还可以避免 sizeof 问题),例如:

typedef struct
{
    union {
        int i;
        float f;
        char *s;
    } data;
    void (*print)(void *);
    status_ty (*add)(void *,int);
    void (*free_element)(void *);
} element_ty;

/*------------------------------------------------------------------*/

void FreeStrElement(void *element)
{
    element_ty *p_element = (element_ty *) element;
    free(p_element->data.s);
}

/*------------------------------------------------------------------*/

status_ty AddToInt(void *element,int IncrementValue)
{
    element_ty *p_element = (element_ty *) element;
    p_element->data.i += IncrementValue;
    return ...;
}

/*------------------------------------------------------------------*/

status_ty AddToFlt(void *element,int IncrementValue)
{
    element_ty *p_element = (element_ty *) element;
    p_element->data.f += IncrementValue;
    return ...;
}

/*------------------------------------------------------------------*/

status_ty AddToStr(void *element,int IncrementValue)
{
    element_ty *p_element = (element_ty *) element;
    char *p_str = p_element->data.s;

    char *new_str = realloc(p_str,IncrementValue);

    p_element->data.s = new_str;

    return ...;
}

/*------------------------------------------------------------------*/

void PrintInt(void *element)
{
    element_ty *p_element = (element_ty *) element;
    printf("Integer in the element: %d\n",p_element->data.i);
}

/*------------------------------------------------------------------*/

void PrintFlt(void *element)
{
    element_ty *p_element = (element_ty *) element;
    printf("Float in the element: %f\n",p_element->data.f);
}

/*------------------------------------------------------------------*/

void PrintStr(void *element)
{
    element_ty *p_element = (element_ty *) element;
    printf("String in the element: %s\n",p_element->data.s);
}

/*------------------------------------------------------------------*/

status_ty InitInt(int value,element_ty *element)
{
    element->data.i = value;
    element->print = &PrintInt;
    element->add = &AddToInt;
    element->free_element = NULL;

    return ...;
}

/*------------------------------------------------------------------*/

status_ty InitFlt(float value,element_ty *element)
{
    element->data.f = value;
    element->print = &PrintFlt;
    element->add = &AddToFlt;
    element->free_element = NULL;

    return ...;
}

/*------------------------------------------------------------------*/

status_ty InitStr(const char *value,element_ty *element)
{
    element->data.s = strdup(value);
    element->print = &PrintStr;
    element->add = &AddToStr;
    element->free_element = &FreeStrElement;

    return ...;
}

/*------------------------------------------------------------------*/

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。