Циклы for пропускаются во время выполнения

Я пытаюсь создать программу, которая находит сумму всех чисел, не кратных 17, между двумя заданными целыми числами, но мои циклы for продолжают пропускаться и не выполняться. В результате переменная «sum» всегда выводит на терминал 0.

Это код:

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

int a, b, sub, lower, j, sum;
int arr[100];

int main(){
    system("cls");

    // get numbers
    printf("Input the first number: ");
    scanf("%d", &a);
    printf("Input the second number: ");
    scanf("%d", &b);

    // calculate
    if (a-b > 0)
    {
        lower = b;
        sub = a-b;

        for (int i = b; i < sub; i++)
        {
            if (i % 17 != 0)
            {
                arr[j] = i;
                j++;
            }
        }
    }
    else if (b-a > 0)
    {
        lower = a;
        sub = b-a;

        for (int i = a; i < sub; i++)
        {
            if (i % 17 != 0)
            {
                arr[j] = i;
                j++;
            }
        }
    }

    // sum
    for (int i = 0; i < 49; i++)
    {
        sum = arr[i] + arr[i+1];
    }
    
    // result
    printf("result: %d", sum);

    return 0;
}

Я проверил, работает ли другая часть кода, и она работает. Однако я до сих пор не могу понять, почему это происходит. Есть идеи?

Заранее спасибо.

Прежде всего, внутри for(int i = 0; i < 49; i++) вы пересчитываете и, следовательно, пересуммируете. Например, проверьте индекс i = 0, который дает вам sum=arr[0]+arr[1], а затем индексируйте i=1 с помощью sum = arr[1]+arr[2]. Кроме того, так и должно быть sum += arr[i]+arr[i+1]

Iman Abdollahzadeh 07.07.2024 12:14

Кроме того, вам не нужно хранить все числа, а затем суммировать их в конце. Вы можете просто складывать каждое число по мере его нахождения.

BoP 07.07.2024 12:47

Границы вашего цикла не имеют смысла. Например, предположим a < b. Тогда в цикле i должно проходить от a до b, поэтому вам нужно for (int i = a; i <= b; i++). Но вместо этого у вас есть for (int i = a; i < b-a; i++). Этот цикл может вообще не выполняться. Предположим, a равно 100, а b равно 110. Тогда b-a равно 10. Таким образом, цикл начинается с 100 и немедленно завершается. Перестаньте пытаться вычесть a из b. Просто используйте a и b в качестве границ. Вам нужно только вычесть, чтобы создать относительный индекс, который вы обрабатываете вручную с помощью j.

Tom Karzes 07.07.2024 12:49

Пробовали ли вы запускать код построчно в отладчике, отслеживая поток управления и значения всех переменных, чтобы определить, в какой строке ваша программа перестает вести себя должным образом? Если вы не пробовали это, возможно, вам будет интересно прочитать это: Что такое отладчик и как он может помочь мне диагностировать проблемы? Возможно, вам также будет интересно прочитать это: Как отлаживать небольшие программы?

Andreas Wenzel 07.07.2024 13:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
96
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Добро пожаловать в Stack Overflow!

Есть несколько причин, по которым ваш код не работает, и я объясню их ниже, но сначала я бы рекомендовал изучить отладчики. Отладчики — отличный способ выяснить, где/почему ваш код работает не так, чтобы вам не приходилось тратить часы на его бесполезное прочесывание. Как упомянул другой пользователь, вы можете использовать эту ссылку, чтобы узнать больше.

Хорошо, перейдем к тому, что не так с вашим кодом. Во-первых, в обоих циклах for вы инициализируете i, равное наибольшему из двух данных вам чисел, будь то a или b. Это нормально, особенно если вы пытаетесь посчитать целые числа между a и b. Однако когда вы устанавливаете конечное значение цикла for (когда он остановится), вы устанавливаете его равным sub, которое, по вашему расчету, представляет собой разницу между a и b. Цикл начинается с наименьшего из a или b и проходит через каждое число, пока не достигнет разницы между a и b, а не большего из двух чисел. Если вы хотите перебрать все числа между a и b, вы можете вместо этого установить конечное значение цикла на большее из двух переменных, код для циклов будет следующим:

    if (a-b > 0)
    {
        for (int i = b; i < a; i++)
        {
            if (i % 17 = 0)
            {
                arr[j] = i;
                j++;
            }
        }
    }
    else if (b-a > 0)
    {
        for (int i = a; i < b; i++)
        {
            if (i % 17 = 0)
            {
                arr[j] = i;
                j++;
            }
        }
    }

В этих двух примерах вы можете видеть, где я заменил sum на a и b, я также удалил ненужное объявление «меньших» чисел, поскольку вы уже установили, для какого случая предназначен каждый цикл, однако, если вам нужна переменная для чего-то другого смело вставляйте его обратно.

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

    if (a-b > 0)
    {
        for (int i = b; i < a; i++)
        {
            if (i % 17 == 0)
            {
                sum += i;
            }
        }
    }
    else if (b-a > 0)
    {
        for (int i = a; i < b; i++)
        {
            if (i % 17 == 0)
            {
                sum += i;
            }
        }
    }

Вы также заметите, что я изменил ваши операторы if на ==, а не на !=. Это связано с тем, что, когда вы проверяете if (i % 17 != 0), вы проверяете каждое число, у которого есть остаток при делении на 17. В конечном итоге это будет каждое число, кроме 17. Вместо этого вам нужно выражение ==.

Я не буду вдаваться в подробности цикла for, используемого для вычисления суммы, поскольку, как я уже упоминал, гораздо эффективнее использовать время и память для вычисления в предыдущих циклах for, но если вы настаиваете на сохранении системы массивов, вы хотите добавлять array[i] к сумме только один раз, array[i+1] в любом случае будет добавлено в следующей последовательности цикла for, система, которая у вас сейчас есть, удваивает числа.

Помимо этого, я внес несколько незначительных изменений качества жизни в код, который я написал ниже, а также финальную версию, которая должна вам подойти. Обязательно присмотритесь к отладчику на будущее и удачи в ваших будущих начинаниях по кодированию!

Изменения качества жизни:

  • В конце оператора printf добавлен \n, чтобы добавить еще одну строку после печати суммы.
  • удалены ненужные переменные, такие как sub и lower
  • добавлен очень простой ответ на неверные входные данные.

Рабочий код:

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

int a, b, j, sum;

int main(){

    // get numbers
    printf("Input the first number: ");
    scanf("%d", &a);
    printf("Input the second number: ");
    scanf("%d", &b);

    // calculate
    if (a-b > 0)
    {
        for (int i = b; i < a; i++)
        {
            if (i % 17 == 0)
            {
                sum += i;
            }
        }
    }
    else if (b-a > 0)
    {
        for (int i = a; i < b; i++)
        {
            if (i % 17 == 0)
            {
                sum += i;
            }
        }
    }
    else
    {
        printf("\nInvalid input, stopping program.\n");
        return 1;
    }

    // result
    printf("result: %d\n", sum);

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

Неправильные условия цикла

Ваши условия для циклов неверны. В обычном цикле это обычно делается как for (int i = 0; i < cond; i++). Однако вы перепутали условия цикла.

Циклическая логика

Вы сделали lower, чтобы получить меньшее из двух чисел, и sub, чтобы получить разницу между a и b. Вы хотите, чтобы цикл for повторялся sub раз, но вы его неправильно реализовали. Ваши циклы не выполняются sub раз.

Пример

Пусть a=8 и b=5. В данном случае a-b > 0, lower=5 и sub=3.

Когда вы это сделаете for (int i = b; i < sub; i++), итерации будут следующими:

  • i=5, 5<2 равно false, цикл завершается

Очевидно, что приведенные выше числа примеров не имеют особого смысла для вашего варианта использования, но они ясно подчеркивают проблему с логикой цикла. Хотя вы ожидали, что цикл выполнится три раза, вместо этого он выполнился только один раз.

Исправить 1

Я вижу, что логика циклов for одинакова как для a-b > 0, так и для b-a > 0. Поэтому я рекомендую их комбинировать (СУХОЙ принцип ).

Сначала вы проверяете большее/меньшее число:

if (a - b > 0)
{
    lower = b;
    sub = a - b;
}
else if (b - a > 0)
{
    lower = a;
    sub = b - a;
}

Затем вы реализуете цикл, используя lower и sub.

Хотя есть несколько способов запустить его sub раз, поскольку вы хотите «собрать» значение i, вам следует заставить цикл переходить от меньшего числа к большему. Следовательно, вместо sub вам действительно нужен higher.

for (int i = lower; i < higher; i++)
{
    if (i % 17 != 0)
    {
        arr[j] = i;
        j++;
    }
}

Подведение итогов

Как отметила Иман Абдоллахзаде в комментариях, вы «пересчитываете и, следовательно, пересчитываете». Что еще более важно, вы НЕ суммируете значения во время цикла.

Исправление 2а: правильно связали петлю

Поскольку ваш j на самом деле отслеживает использованную часть arr, вы можете использовать его, чтобы не пересчитать.

for (int i = 0; i < j; i++)
{
    // adding logic
}

Исправление 2b: правильное добавление значений

Когда вы делаете sum = arr[i] + arr[i+1], вы добавляете 2 последовательных числа и присваиваете sum. Однако иначе этот sum не будет использоваться в будущих итерациях циклов.

Чтобы суммировать значения arr, вам нужно сделать sum = sum + arr[i] или проще sum += arr[i].

Исправление 2 (комбинированное)

Объединив исправления 2a и 2b, вы получите

for (int i = 0; i < j; i++)
{
    sum += arr[i]
}

Краткое содержание

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

Также могут быть и другие необнаруженные ошибки, которые следует попытаться отладить.

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