C输入问题

时间:2011-07-15 19:19:48

标签: c gcc struct fgets

=============================================== =================

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();
}

=============================================== =================

如果输入是:

  • MOE
  • 18
  • 214

// PROBLEM的打印输出为:

joe moe [joe moe/oe]

而不是

joe moe [joe/moe]

有什么想法吗?在我的生活中,我不能弄清楚为什么fn和ln的值正在改变......

3 个答案:

答案 0 :(得分:4)

问题在于namefullname共享内存(因为union)。所以

sprintf(str.name, "%s %s", str.fullname.fn, str.fullname.ln);

还会在fnln上撰写。

这不是一个糟糕的问题,但我真的没有看到如何干净利落地解决这个问题。我这样做的方法:摆​​脱上面的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)

结构的名称部分是联合,因此它可以是namefullname,但不能同时进行。{{1}}或{{1}}。因此,在设置名称后,字段fullname无效。联合的问题在于您必须提供一种机制来检测实际使用的联合部分。我在这里没有看到任何东西来决定是否使用名称或全名。