如何解决从结构数组中传递一个元素并在 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
函数,哪个将指向数组中的这个特定元素? 看下面我写的代码,如果有错误请告诉我
- 接收应添加的
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 举报,一经查实,本站将立刻删除。