=============================================== =================
typedef struct {
union {
struct {
char fn[5];
char ln[5];
} fullname;
char name[5+5+1];
}
unsigned int age;
unsigned int area_code;
} my_struct;
以上是我无法控制的结构。我个人不是粉丝,但结构是“合法的”。
=============================================== =================
我的代码:
void caller {
my_struct str;
str = (my_struct){}; //initialise
fill(&str);
printf("%s [%s/%s]\n", str.name, str.fullname.fn, str.fullname.ln); // PROBLEM!
}
void fill(my_struct * str) {
//first name
printf("Enter first name: ");
fgets(str.fullname.fn, sizeof(str.fullname.fn), stdin);
if (str.fullname.fn[strlen(str.fullname.fn) - 1] == '\n')
str.fullname.fn[strlen(str.fullname.fn) - 1] = '\0';
//last name
printf("Enter last name: ");
fgets(str.fullname.ln, sizeof(str.fullname.fn), stdin);
if (str.fullname.ln[strlen(str.fullname.ln) - 1] == '\n')
str.fullname.ln[strlen(str.fullname.ln) - 1] = '\0';
sprintf(str.name, "%s %s", str.fullname.fn, str.fullname.ln);
printf("Age: ");
scanf("%ud", &str.age);
getchar();
printf("Area Code: ");
scanf("%ud", &str.area_code);
getchar();
}
=============================================== =================
如果输入是:
// PROBLEM
的打印输出为:
joe moe [joe moe/oe]
而不是
joe moe [joe/moe]
有什么想法吗?在我的生活中,我不能弄清楚为什么fn和ln的值正在改变......
答案 0 :(得分:4)
问题在于name
和fullname
共享内存(因为union
)。所以
sprintf(str.name, "%s %s", str.fullname.fn, str.fullname.ln);
还会在fn
和ln
上撰写。
这不是一个糟糕的问题,但我真的没有看到如何干净利落地解决这个问题。我这样做的方法:摆脱上面的sprintf
,然后自己动手。
void caller
{
fill(&str);
printf("%s %s [%s/%s]\n", str.fullname.fn, str.fullname.ln, str.fullname.fn, str.fullname.ln);
}
答案 1 :(得分:1)
问题在于:
sprintf(str.name, "%s %s", str.fullname.fn, str.fullname.ln);
sprintf无法在重叠的内存区域上运行。
你可以做的是不要在名字后加\0
,而在\n
后加一个空格,然后打印str.name
。
此外,使用' '
(空格)初始化数组,它将为第一个名称输入少于5个字符的输入。
memset(&str, ' ', sizeof(str));
答案 2 :(得分:0)
结构的名称部分是联合,因此它可以是name
或fullname
,但不能同时进行。{{1}}或{{1}}。因此,在设置名称后,字段fullname无效。联合的问题在于您必须提供一种机制来检测实际使用的联合部分。我在这里没有看到任何东西来决定是否使用名称或全名。