C входной вопрос - PullRequest
       15

C входной вопрос

0 голосов
/ 15 июля 2011

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

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

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

Если ввод был:

  • joe
  • мо
  • 18
  • 214

Распечатка на // PROBLEM:

joe moe [joe moe/oe]

вместо

joe moe [joe/moe]

Есть идеи?Я не могу понять, почему меняются значения fn и ln ...

Ответы [ 3 ]

4 голосов
/ 15 июля 2011

Проблема в том, что 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 голос
/ 15 июля 2011

проблема здесь:

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

sprintf не может работать с перекрывающимися областями памяти.

Что вы можете сделать, это НЕ ставить \0 после имени, а пробел вместо \n и просто печатать str.name.

Кроме того, инициализируйте массив с помощью ' ' (пробелы), он будет вводить для первого имени менее 5 символов.

memset(&str, ' ', sizeof(str));
0 голосов
/ 15 июля 2011

Именной частью структуры является union , так что это либо name, либо fullname, но не оба одновременно. Таким образом, после установки имени полное имя поля недействительно. Проблема с объединениями заключается в том, что вы должны предоставить механизм для определения того, какая часть объединения фактически используется. Я не вижу здесь ничего, чтобы решить, используется ли имя или полное имя.

...