开发者

C input issue

开发者 https://www.devze.com 2023-03-20 11:17 出处:网络
================================================================ typedef struct { union { struct { char fn[5];

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

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;

The above is a struct that I have no control over. I personally am not a fan, but the struct is "legal".

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

My code:

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

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

If the input was:

  • joe
  • moe
  • 18
  • 214

The printout at // PROBLEM is:

joe moe [joe moe/oe]

instead of

joe moe [joe/moe]

Any ideas? I cannot, for the life of me, figure out why the values of fn and ln are 开发者_StackOverflow社区changing...


The problem is that name and fullname share the memory (because of the union). So

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

also writes over fn and ln.

Not a bad question, but I don't really see how to cleanly solve this. The way I'd do it: get rid of the sprintf above, and do it on your own.

void caller
{
    fill(&str);

    printf("%s %s [%s/%s]\n", str.fullname.fn, str.fullname.ln, str.fullname.fn, str.fullname.ln);
}


the problem is here:

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

sprintf can't operate on overlapping memory regions.

What you can do is to NOT put a \0 after the first name, but a space instead of the \n and just print str.name.

Also, initialize the array with ' ' (spaces) it would make inputs for the 1st name that are less than 5 chars.

memset(&str, ' ', sizeof(str));


The name part of the struct is a union, so it's either name or fullname, but not both at the same time. So after setting name the field fullname is invalid. The problem with unions is that you have to provide a mechanism for detecting which part of the union is actually used. I don't see anything here to decide whether name or fullname is used.

0

精彩评论

暂无评论...
验证码 换一张
取 消