#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);