От наибольшего значения к наименьшему значению

Добрый день, я практиковался в C и столкнулся с проблемой. Проблема была в этой части или где-то здесь. for (ctr = num2; ctr <= num1; ctr++) Например, вывод

Enter the value of n1: 3
Enter the value of n2: 10
4 6 8 10 

Я бы хотел, чтобы он начинался с наибольшего 10 8 6 4, а не с наименьшего 4 6 8 10.

#include <stdio.h>

int main(void) {
    int num1, num2, ctr;

    printf("Enter value of n1: ");
    scanf("%d", &num2);
    printf("Enter value of n2: ");
    scanf("%d", &num1);
    for (ctr = num2; ctr <= num1; ctr++) {
        if (ctr % 2 == 0)
            printf("%d ", ctr);
    }
    return 0;
}

Переверните условие и используйте вычитание

Daniel A. White 23.04.2022 14:08
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
1
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем for просто замените

ctr = num2; ctr <= num1; ctr++

с

ctr = num1; ctr >= num2; ctr--

Ваш текущий цикл for сначала инициализирует ctr в num2. По мере прохождения цикла ctr увеличивается так, что его значение становится num2 + 1, затем num2 + 2, ..., затем num1 - 1, затем num1. После того, как ctr становится num1, оператор в цикле выполняется в последний раз, затем ctr увеличивается, и его значение становится num1 + 1, что превышает num1, что приводит к завершению цикла.

  • ctr принимает значения в {num2, num2 + 1, ... , num1 - 1, num1, num1 + 1}. Оператор в цикле выполняется для каждого значения, которое принимает ctr, кроме num1 + 1.

Чтобы изменить это, вы инициализируете ctr значением num1, и по мере прохождения цикла значение ctr должно уменьшаться, чтобы его значение стало равным num1 - 1, затем num1 - 2, ..., затем num2. После того, как ctr становится num2, оператор в цикле выполняется в последний раз, затем ctr уменьшается, и его значение становится num2 - 1, что меньше num2, что приводит к завершению цикла.

  • ctr принимает значения в {num1, num1 - 1, ..., num2 + 1, num2, num2 - 1}. Оператор в цикле выполняется для каждого значения, которое принимает ctr, кроме num2 - 1.

Обратите внимание, как в обоих циклах оператор выполняется, когда ctr принимает значение в {num2, num2 + 1, ..., num1 - 1, num1}. Единственное отличие состоит в том, что в первом цикле ctr начинается с num2 и движется вверх до num1, тогда как во втором цикле ctr начинается с num1 и движется вниз к num2.

После внесения вышеуказанных изменений ваша программа должна работать должным образом. В приведенном ниже коде я (1) внес предложенное выше изменение и (2) включил проверки возвращаемого значения scanf. Нет необходимости вносить изменения (2), но обычно рекомендуется проверять возвращаемое значение scanf. Для справки (из стандарта C99)

The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.

В нашем случае мы ожидаем, что scanf вызов формы scanf("%d", &num2) вернет 1. Возвращаемое значение, отличное от 1, означает, что в scanf произошла ошибка. В настоящее время наша функция просто останавливает программу в случае возникновения ошибки. Однако, используя функции feof и ferror, можно узнать тип возникшей ошибки, и программист может изменить поведение программы в зависимости от типа ошибки. Для краткости я опустил использование feof и ferror (оба из <stdio.h>), хотя я подумал, что упомяну их, поскольку мы говорим об ошибках scanf.

Также стоит отметить, что вы должны быть осторожны, чтобы пользователь не ввел число для num2, равное INT_MIN (макрос, определенный в <limits.h>), минимальное значение для объекта типа int. Хотя присвоение INT_MIN такому int, как num2, само по себе не является неправильным, если num2 равно INT_MIN, в конечном итоге ctr будет равно num2, оператор в цикле будет выполнен в один «последний» раз, но затем num2 будет уменьшен, что означало бы попытку присвоить num2 число меньше минимального значения для объекта типа int. То есть в программе будет неопределенное поведение. Вероятным результатом установки num2 на INT_MIN будет то, что цикл будет работать вечно.

Программа

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

int main(void){

    int num1, num2, ctr;

        printf("Enter value of n1: ");
        if (scanf("%d", &num2) != 1) {
            printf("scanf: error\n");
            exit(EXIT_FAILURE);
        }

        printf("Enter value of n2: ");
        if (scanf("%d", &num1) != 1) {
            printf("scanf: error\n");
            exit(EXIT_FAILURE);
        }

        for (ctr = num1; ctr >= num2; ctr--)
            if (ctr % 2 == 0)
                printf("%d ", ctr);
        printf("\n");

    return 0;

}

Пример сеанса

Enter value of n1: 3
Enter value of n2: 10
10 8 6 4 

Вы можете добавить примечание относительно этой потенциальной проблемы: если num2 имеет значение INT_MIN (-2147483648 для большинства систем), цикл имеет неопределенное поведение и, вероятно, никогда не остановится.

chqrlie 23.04.2022 15:33

Это хорошо написанный ответ с особым акцентом на проверка возврата из scanf() и обработкой ошибки. Что касается комментария @chqrlie, вы можете защититься от проблемы с помощью #include <limits.h> и if (scanf("%d", &num2) != 1 || num2 == INT_MIN) { fputs ("error: invalid integer value or value out of range.\n", stderr); ... } Также не нужно printf(), если в строке формата нет спецификатора преобразования, подойдет puts() или fputs(). Нет необходимости в строковом литерале в printf("\n");, когда подойдет putchar('\n');. Использование printf() не является неправильным, это просто лучшие альтернативы.

David C. Rankin 23.04.2022 17:29

Наконец, смешивание подсказок для n1, но чтение num2 (и наоборот) влияет на читабельность кода. Человеческая природа такова, что можно предвидеть, что кто-то, читающий код, пробежится по соединению n1, num2 и начнет искать num1 после блока. Опять же, это не так, но больше внимания следует уделять последовательному именованию и удобочитаемости.

David C. Rankin 23.04.2022 17:31

@DavidC.Rankin: вместо того, чтобы делать num2 == INT_MIN ошибку, предпочтительнее изменить цикл с помощью правильного конечного теста: if (num2 >= num1) { for (ctr = num2;; ctr--) { if (ctr % 2 == 0) printf("%d ", ctr); if (ctr == num1) break; }}

chqrlie 23.04.2022 17:35

@chqrlie ты прав -- снова. Я знал, что должен был пойти выпить кофе, прежде чем печатать :)

David C. Rankin 23.04.2022 17:36

Использование num2 для номера 1 и num1 для номера 2 действительно сбивает с толку.

chqrlie 23.04.2022 17:36

Основная причина, по которой scanf() возвращает 0, — это сбой при преобразовании ввода, то есть: если пользователь ввел символы, которые не должны начинаться с цифры.

chqrlie 23.04.2022 17:38

Спасибо за дополнения и рекомендации @DavidC.Rankin и @chqrlie! Я постараюсь включить их в свой ответ. Полностью согласен - num1 должно соответствовать n1, а num2 должно соответствовать n2. Еще лучше было бы, чтобы num1 и num2 имели имена, сигнализирующие читателю, какая из них является нижней или верхней границей. Я чувствовал, что постараюсь изменить программу OP как можно меньше, поэтому я не менял имена переменных. Но я могу отредактировать сообщение, чтобы попытаться включить более читаемые имена для будущих читателей!

oda 23.04.2022 17:54

Другие вопросы по теме