Почему происходит неправильный вывод (либо "м" и "высшее", либо все наоборот "ж" и "среднее")?

Рейтинг: 0Ответов: 1Опубликовано: 09.03.2023

Вывожу в консоль

void show (list cur) {
    unsigned char k = 0;
    system ("cls");
    if (cur == NULL) {
        puts ("Список пуст");
        system("pause");
        return;
    }
    puts ("| #  |            Фамилия            | Год рождения | Пол | Образование | Год трудоустройства |");
    puts ("-----------------------------------------------------------------------------------------------");
    while (cur) {
        printf ("| %-3d| %-30s| %-12d | %-3c | %-11s | %-19d |\n", ++k, cur->data.surname, cur->data.age, cur->data.gender == 1 ? 'м' : 'ж', cur->data.educ == 1 ? "высшее" : "среднее", cur->data.work);
        cur = cur->next;
    }
    system("pause");
}

На выводе почему то все выводит "м" и "высшее", либо все наоборот "ж" и "среднее". Помогите, пожалуйста.

Ответы

▲ 2

Нужно смотреть на предупреждения компилятора - он предупреждает, что в scanf() вы передали формат для типа int, а аргумент типа short. И в результате, когда вы вводите год рождения scanf("%d", &emp.age), он перезатирает байты пола и образования. Т.к. scanf() получает адрес и записывает по этому адресу количество байт, которые вы указали в строке формата %d - это int а его размер - 4 байта (в общем случае).

struct employee {
    char surname[30];
    short age;   // 2 байта
    char gender; // 1 байт
    char educ;   // 1 байт
    short work;
};

puts ("Год рождения");
while (scanf("%d", &emp.age) // %d записывает 4 байта, т.е. поверх age, gender, educ

// должно быть 
scanf("%hd", &emp.age)

И та же самая ошибка при записи года трудоустройства.
При этом, год рождения затирает данные внутри объекта вашей структуры, а год трудоустройства - за пределами объекта что является неопределенным поведением - программа может рухнуть, а может работать и портить другие данные.
Вообще, чтобы не мучаться с приведением типов в строке формата scanf() вводите числа как целые во временную переменную, а потом просто присваивайте - приведение типов всё сделает правильно.

int tmp;
scanf("%d", &tmp)
emp.age = (short)tmp; // компилятор за вас сделает правильное приведение типа