我是C编程的初学者,我对将通用结构传递给C中的函数存在疑问。
这就是我所拥有的:
typedef struct {
char name[20];
float price;
} product;
typedef struct {
char name[20];
int type;
} category;
我想做这样的事情:
void changeName(struct *s, newName[20]) {
strcpy(s->name, newName);
}
如果有人已经问过这个问题,请不要理会,并向我发送问题链接。
有人可以帮助我吗?
感谢。
答案 0 :(得分:1)
union
一种方法是添加一个包含union
的结构,其中包含指向product
和category
结构的指针,以及enum
以确定其类型struct
中的数据。此union
或指向它的指针可以传递给change_name()
函数。
这是一个可以在C11中使用的示例。它使用未命名的union
成员,因此这不是有效的C99代码:
#include <stdio.h>
#include <string.h>
typedef struct {
char name[20];
float price;
} product;
typedef struct {
char name[20];
int type;
} category;
typedef struct {
enum { PRODUCT, CATEGORY } type;
union {
product *prod;
category *cat;
};
} generic;
void change_name(generic *gen, const char *new_name);
int main(void)
{
product prod_a = { .name = "widget", .price = 1.99 };
category cat_a = { .name = "general", .type = 1 };
generic gen_prod_a = { .type = PRODUCT, .prod = &prod_a };
generic gen_cat_a = { .type = CATEGORY, .cat = &cat_a };
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
change_name(&gen_prod_a, "gadget");
change_name(&gen_cat_a, "specific");
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
return 0;
}
void change_name(generic *gen, const char *new_name)
{
switch (gen->type) {
case PRODUCT:
strcpy(gen->prod->name, new_name);
break;
case CATEGORY:
strcpy(gen->cat->name, new_name);
break;
default:
fprintf(stderr, "Unknown type in change_name()\n");
}
}
通过命名union
:
typedef struct {
enum { PRODUCT, CATEGORY } type;
union {
product *prod;
category *cat;
} data; // named for C99
} generic;
/* ... */
generic gen_prod_a = { .type = PRODUCT, .data.prod = &prod_a };
generic gen_cat_a = { .type = CATEGORY, .data.cat = &cat_a };
/* ... */
void change_name(generic *gen, const char *new_name)
{
switch (gen->type) {
case PRODUCT:
strcpy(gen->data.prod->name, new_name);
break;
case CATEGORY:
strcpy(gen->data.cat->name, new_name);
break;
default:
fprintf(stderr, "Unknown type in change_name()\n");
}
}
或者,一个struct
类型可以包含enum
标识符和包含产品和类别结构的union
。这种方法似乎更精简:
#include <stdio.h>
#include <string.h>
typedef struct {
enum { PRODUCT, CATEGORY } type;
union {
struct {
char name[20];
float price;
} prod;
struct {
char name[20];
int type;
} cat;
} data;
} record;
void change_name(record *rec, const char *new_name);
int main(void)
{
record prod_a = { .type = PRODUCT };
change_name(&prod_a, "widget");
prod_a.data.prod.price = 1.99;
record cat_a = { .type = CATEGORY };
change_name(&cat_a, "general");
cat_a.data.cat.type = 1;
printf("prod_a.name = %s\n", prod_a.data.prod.name);
printf("cat_a.name = %s\n", cat_a.data.cat.name);
change_name(&prod_a, "gadget");
change_name(&cat_a, "specific");
printf("prod_a.name = %s\n", prod_a.data.prod.name);
printf("cat_a.name = %s\n", cat_a.data.cat.name);
return 0;
}
void change_name(record *rec, const char *new_name)
{
switch (rec->type) {
case PRODUCT:
strcpy(rec->data.prod.name, new_name);
break;
case CATEGORY:
strcpy(rec->data.cat.name, new_name);
break;
default:
fprintf(stderr, "Unknown type in change_name()\n");
}
}
上述两种方法都有点尴尬。另一种解决方案(仅适用于C11)是在类型通用宏中使用_Generic
关键字。这里,为每个预期的数据类型编写函数,宏根据类型选择要使用的函数定义。这种方法的一个优点是,随着新类型的添加,只需要新的函数和类型通用宏的更新来处理它们。
#include <stdio.h>
#include <string.h>
#define change_name(S, N) _Generic ((S), \
prod_ptr: change_name_prod, \
cat_ptr: change_name_cat \
)((S), (N))
typedef struct {
char name[20];
float price;
} product;
typedef struct {
char name[20];
int type;
} category;
typedef product *prod_ptr;
typedef category *cat_ptr;
void change_name_prod(product *prod, const char *new_name);
void change_name_cat(category *cat, const char *new_name);
int main(void)
{
product prod_a = { .name = "widget", .price = 1.99 };
category cat_a = { .name = "general", .type = 1 };
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
change_name(&prod_a, "gadget");
change_name(&cat_a, "specific");
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
return 0;
}
void change_name_prod(product *prod, const char *new_name)
{
strcpy(prod->name, new_name);
}
void change_name_cat(category *cat, const char *new_name)
{
strcpy(cat->name, new_name);
}
以上所有程序都有相同的输出:
prod_a.name = widget
cat_a.name = general
prod_a.name = gadget
cat_a.name = specific
答案 1 :(得分:0)
您已经对结构进行了类型定义。您可以使用这些其他名称。
例如,如果名称为product
,则首先创建一个变量并调用函数
product var={"name", 1.2};
changeName(&var, "AnotherName");
然后将此变量传递给函数
void changeName(product *s, char newName[])
{
strcpy(s->name, newName);
}
答案 2 :(得分:-1)
通用编程,暗示类型安全只是在C中确实存在。但是有很多方法可以解决这个问题。
我从你的问题中理解的是,我能定义一个可以应用于不同结构的共同元素的函数吗?
让我们展开一些例子,让项目具有共同的特征。
struct info
{
char name[20];
int id;
};
struct product
{
Info info;
int price;
};
struct category
{
Info info;
int type;
};
您现在可以定义一个能够安全地处理产品和类别共享的特征的函数。
void changeName(info* p, const char* name)
{
strcpy_s(info->name, sizeof(info->name), name);
}
int main()
{
category cat;
product prod;
memset(&cat, 0, sizeof(cat));
memset(&prod, 0, sizeof(prod));
changeName(&cat.info, "Category 1");
changeName(&prod.info, "blue product");
return 0;
}