Мне интересно, почему я получаю случайное целое число в качестве выходных данных в этой программе

#c

#c

Вопрос:

Эта программа предназначена для получения 3 целых чисел и упорядочивания их в порядке возрастания. Когда я ввожу комбинацию, такую как «12 8 2», я получаю на выходе «1995099040 8 12». Любая помощь в том, почему я получаю этот ответ?

 #include <stdio.h>
#include <stdlib.h>

int findBig(int d, int e, int f) {
    if ((d >= e) amp;amp; (d >= f)) {
        return d;
    } else
    if ((e >= d) amp;amp; (e >= f)) {
        return e;
    } else
    if ((f >= e) amp;amp; (f >= d)) {
        return f;
    }
}

int main(void) {
    const int MAX_NUM = 3;
    int userArray[MAX_NUM];
    int bigNum;
    int midNum;
    int smallNum;
    int j = 0;
    int a;
    int b;
    int c;

    printf("Please enter three integers separated by spaces:n");

    for (j = 0; j < MAX_NUM;   j) {
        scanf("%d", amp;userArray[j]);
    }
    a = userArray[0];
    b = userArray[1];
    c = userArray[2];

    bigNum = findBig(a, b, c);

    if (bigNum == a) {
        midNum = findBig(0, b, c);
    } else
    if (bigNum == b) {
        midNum = findBig(a, 0, c);
    } else
    if (bigNum == c) {
        midNum = findBig(a, b, 0);
    }
    if ((midNum == a) amp;amp; (bigNum == b)) {
        smallNum = c;
    } else
    if ((midNum == b) amp;amp; (bigNum == c)) {
        smallNum = a;
    } else
    if ((midNum == c) amp;amp; (bigNum == a)) {
        smallNum = b;
    }

    printf("%d %d %dn", smallNum, midNum, bigNum);

    return 0;
}
  

Комментарии:

1. Стратегия чтения чисел в массив хороша, но все, что происходит после этого, не является хорошим способом работы. Вероятно, вам следует просто отсортировать массив, чтобы вы могли тривиально выбирать значения в требуемом порядке. То, что у вас получилось, более или менее подходит в качестве упражнения при написании if инструкций, но в остальном оставляет желать лучшего.

Ответ №1:

smallNum остается с ненужным значением, которое оно получает при создании, потому что вы не охватили все возможные варианты значений для bigNum и midNum , поэтому ему не присваивается значение в определенных случаях — например, в том, с которым у вас возникла проблема — и остается неинициализированным.

Обязательно проверьте все возможные случаи:

 if((midNum == a) amp;amp; (bigNum == b)){ smallNum = c; }
else if((midNum == b) amp;amp; (bigNum == c)){ smallNum = a; }
else if((midNum == c) amp;amp; (bigNum == a)){ smallNum = b; }
else if((midNum == b) amp;amp; (bigNum == a)){ smallNum = c; }
else if((midNum == c) amp;amp; (bigNum == b)){ smallNum = a; }
else if((midNum == a) amp;amp; (bigNum == c)){ smallNum = b; }
  

Кроме того, рассмотрите возможность использования встроенных функций, чтобы сэкономить время и код — у вас есть функция max and min , которая поможет вам.

Чтобы найти максимум три числа, которые вы можете использовать max(max(a, b), c) — таким образом, мы можем сократить код до

 smallNum = min(min(a, b), c);
bigNum = max(max(a, b), c);
midNum = (a   b   c) - smallNum - bigNum;
  

(Это сократит код вдвое и сделает findBig ненужным)

Комментарии:

1. Какой язык поддерживает max({a, b, c}) ? Кроме того, midNum = min(max(a, b), c); не удается определить правильное число для a=1, b=2, c=0 .

2. интересная альтернатива для определения midNum , но не совсем ОК: она вызывает неопределенное поведение, если a b c вызывает арифметическое переполнение среди других возможностей.

3. Если вы подозреваете, что предоставленные входные данные действительно будут большими, вы можете преобразовать их в longs, применить этот метод и быть уверенным в проблемах с переполнением (результатом в любом случае будет одно из исходных значений int, поэтому вам нужны longs только для операции)

4. Технически преобразование в long или даже long long не исключает неопределенного поведения на архитектурах, где sizeof(int) == sizeof(long) или sizeof(int) == sizeof(long long) . Существует простое решение, использующее арифметику без знака, которая полностью определена, если a , b и c неотрицательны, а реализация определена иначе: midNum = (unsigned)a   b   c - smallNum - bigNum;

5. Как насчет (a - bigNum) (b - smallNum) c ? Это должно гарантировать отсутствие переполнения во время оценки (поправьте меня, если я ошибаюсь).

Ответ №2:

Для определения smallNum необходимо рассмотреть 6 случаев.

 if((midNum == a) amp;amp; (bigNum == b) || ((midNum == b) amp;amp; (bigNum == a))){
 smallNum = c; 
}
else if((midNum == b) amp;amp; (bigNum == c) || ((midNum == c) amp;amp; (bigNum == b))){
 smallNum = a; 
}
else if((midNum == c) amp;amp; (bigNum == a) || ((midNum == a) amp;amp; (bigNum == c))){ 
smallNum = b; 
}
  

Мусор возникает из-за пропущенных случаев.

Ответ №3:

Вы получаете мусорный вывод, потому что ваш код вызывает неопределенное поведение: для ввода 12 8 2 регистр (midNum == b) amp;amp; (bigNum == a) не обрабатывается в коде и smallNum остается неинициализированным.

Вы можете упростить свой код, переставив массив с помощью 3 тестов и замен:

 #include <stdio.h>

int main(void) {
    const int MAX_NUM = 3;
    int userArray[MAX_NUM];
    int x;

    printf("Please enter three integers separated by spaces:n");

    for (int j = 0; j < MAX_NUM;   j) {
        if (scanf("%d", amp;userArray[j]) != 1)
            exit(1);
    }
    if (userArray[0] > userArray[1]) {
        x = userArray[0]; userArray[0] = userArray[1]; userArray[1] = x;
    }
    if (userArray[1] > userArray[2]) {
        x = userArray[1]; userArray[1] = userArray[2]; userArray[2] = x;
    }
    if (userArray[0] > userArray[1]) {
        x = userArray[0]; userArray[0] = userArray[1]; userArray[1] = x;
    }

    printf("%d %d %dn", userArray[0], userArray[1], userArray[2]);

    return 0;
}
  

Ответ №4:

Я согласен с другими ответами — ваш код не учитывает все 6 возможностей, в которых значения могут быть упорядочены.

Возможный способ исправить это: сначала измените вашу функцию «find maximum», чтобы она возвращала индекс вместо значения:

 int findBig(int d, int e, int f) {
    if ((d >= e) amp;amp; (d >= f)) {
        return 0; // index of largest element is 0
    } else
    if ((e >= d) amp;amp; (e >= f)) {
        return 1; // index of largest element is 1
    } else
    if ((f >= e) amp;amp; (f >= d)) {
        return 2; // index of largest element is 2
    }
}
  

Затем найдите, какое число является большим, маленьким и медианным:

 bigIndex = findBig(a, b, c);
smallIndex = findBig(-a, -b, -c); // a hack to find the minimum instead of maximum
if (bigIndex == smallIndex)
{
    // Edge case - all numbers are equal
    // Doesn't matter which index is which; just choose 3 different ones
    bigIndex = 0;
    midIndex = 1;
    smallIndex = 2;
}
else
{
    // Choose the index that is neither big nor small
    midIndex = 3 - bigIndex - smallIndex;
}
  

Затем распечатайте их:

 printf("%d %d %dn", userArray[smallIndex], userArray[midIndex], userArray[bigIndex]);
  

Здесь помогает то, что у вас есть массив. В противном случае все еще было бы возможно преобразовать индекс в бит значения, это было бы некрасиво:

 printf("%d %d %dn",
    smallIndex == 0 ? a : smallIndex == 1 ? b : c,
    midIndex == 0 ? a : midIndex == 1 ? b : c,
    bigIndex == 0 ? a : bigIndex == 1 ? b : c);