Я пытаюсь создать программу, которая находит сумму всех чисел, не кратных 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]
Кроме того, вам не нужно хранить все числа, а затем суммировать их в конце. Вы можете просто складывать каждое число по мере его нахождения.
Границы вашего цикла не имеют смысла. Например, предположим 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
.
Пробовали ли вы запускать код построчно в отладчике, отслеживая поток управления и значения всех переменных, чтобы определить, в какой строке ваша программа перестает вести себя должным образом? Если вы не пробовали это, возможно, вам будет интересно прочитать это: Что такое отладчик и как он может помочь мне диагностировать проблемы? Возможно, вам также будет интересно прочитать это: Как отлаживать небольшие программы?
Добро пожаловать в 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, система, которая у вас сейчас есть, удваивает числа.
Помимо этого, я внес несколько незначительных изменений качества жизни в код, который я написал ниже, а также финальную версию, которая должна вам подойти. Обязательно присмотритесь к отладчику на будущее и удачи в ваших будущих начинаниях по кодированию!
Изменения качества жизни:
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
, цикл завершаетсяОчевидно, что приведенные выше числа примеров не имеют особого смысла для вашего варианта использования, но они ясно подчеркивают проблему с логикой цикла. Хотя вы ожидали, что цикл выполнится три раза, вместо этого он выполнился только один раз.
Я вижу, что логика циклов 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++;
}
}
Как отметила Иман Абдоллахзаде в комментариях, вы «пересчитываете и, следовательно, пересчитываете». Что еще более важно, вы НЕ суммируете значения во время цикла.
Поскольку ваш j
на самом деле отслеживает использованную часть arr
, вы можете использовать его, чтобы не пересчитать.
for (int i = 0; i < j; i++)
{
// adding logic
}
Когда вы делаете sum = arr[i] + arr[i+1]
, вы добавляете 2 последовательных числа и присваиваете sum
. Однако иначе этот sum
не будет использоваться в будущих итерациях циклов.
Чтобы суммировать значения arr
, вам нужно сделать sum = sum + arr[i]
или проще sum += arr[i]
.
Объединив исправления 2a и 2b, вы получите
for (int i = 0; i < j; i++)
{
sum += arr[i]
}
В вашей программе есть различные ошибки, и поэтому необходимо несколько исправлений, как я уже указал (исправление 1 и 2). Конечно, вы можете отказаться от отдельного цикла и просто складывать каждое число по мере его нахождения (предложено BoP в комментариях).
Также могут быть и другие необнаруженные ошибки, которые следует попытаться отладить.
См.: Что такое отладчик и как он может помочь мне диагностировать проблемы?.