Следующий код печатает один и тот же результат — дважды (!) (С использованием Microsoft Visual C ++ 2010 IDE). Я также напечатал окончательные значения каждой переменной, чтобы увидеть, что происходит, и в действительности есть два набора значений, которые удовлетворяют if
условие выписки.
Мой вопрос так как инструкция была break;
если условие оценивается как ИСТИНА, может кто-нибудь любезно объяснить, как / почему я получаю оба результата, когда я не просил об этом (не то, что это плохо, просто пытаюсь понять)? Является ли эта часть if
построить или это как-то связано с циклами? Кажется, что что-то знает, что нужно возвращать несколько решений, если условие оценивается как ИСТИНА более одного раза, я просто не понимаю, как оно может это сделать, когда в инструкциях явно не говорится, что это нужно (если только что-то не создано. в этом я не знаю).
По сути, почему цикл не заканчивается на break;
как только условие выполнено или я думаю об этом неправильно?
Опять же, если кто-то знает или я что-то здесь упускаю, пожалуйста, дайте мне знать! Я новичок в C ++, поэтому просто пытаюсь учиться, заранее спасибо.
Вот код:
#include "stdafx.h"#include <iostream>
int main()
{
for (int a = 1; a < 500; ++a)
{
for (int b = 1; b < 500; ++b)
{
for (int c = 1; c < 500; ++c)
{
if ((a + b + c) == 1000 && ((a*a + b*b) == (c*c)))
{
cout << "The product abc = " << a*b*c << endl << "a = " << a << ", b = " << b << ", c = " << c << endl;
break;
}
}
}
}
cout << endl << "Loop terminated";
char d;
cin >> d;
return 0;
}
Вывод консоли следующий:
Продукт abc = 31875000
а = 200, б = 375, с = 425
Продукт abc = 31875000
а = 375, б = 200, с = 425
Цикл прекращен
Ваш break
только вырывается из внутренний цикл, поэтому внешний цикл продолжает выполняться.
Одна из возможностей — переместить этот код в отдельную функцию и вернуться из функции, когда вы найдете совпадение в первый раз. Тогда (если вы не вызовете функцию снова) выполнение этого кода полностью прекратится.
Я бы также исключил петлю c
полностью. Единственное значимое значение для c
является 1000 - (a+b)
так что вы могли бы просто вычислить его напрямую, вместо того, чтобы просмотреть 500 различных значений, чтобы найти его.
Итак — вы слышали это break;
это не решение — но что есть?
Если вы сделаете свой предел (в настоящее время 500) для каждого цикла переменной, скажем
int myLim = 500;
И заменить каждый из for
условия цикла с
for (int a = 1; a < myLim; ++a)
{
for (int b = 1; b < myLim; ++b)
{
for (int c = 1; c < myLim; ++c)
{
Тогда вместо break
ты говоришь myLim = -1
— и ты вырвешься из всех петель.
Обратите внимание — некоторые компиляторы будут недовольны вашей настройкой a=500
а также b=500
когда if
условие выполнено, так как вы модифицируете переменную цикла; но никто не будет возражать, если вы измените условие. Это немного чище, чем добавить флаг, но все же немного взломать.
В вашем коде вы применили только один разрыв. Таким образом, внутренний цикл for будет прерван, а другой внешний цикл продолжится.
Таким образом, вы должны определить переменную флага, чтобы разорвать все циклы.
#include "stdafx.h"#include <iostream>
int main()
{
bool flag = 0; //Set the flag
for (int a = 1; a < 500 && !flag; ++a) //Check flag condition
{
for (int b = 1; b < 500 && !flag; ++b) //Check flag condition
{
for (int c = 1; c < 500 && !flag; ++c) //Check flag condition
{
if ((a + b + c) == 1000 && ((a*a + b*b) == (c*c)))
{
cout << "The product abc = " << a*b*c << endl << "a = " << a << ", b = " << b << ", c = " << c << endl;
flag= 1; //Set the flag true
break;
}
}
}
}
cout << endl << "Loop terminated";
char d;
cin >> d;
return 0;
}
break
оператор разрывает только самый внутренний цикл, и вам может понадобиться использовать флаг для выхода из других циклов в случае разрыва
#include "stdafx.h"#include <iostream>
int main()
{
bool flag = false;
for (int a = 1; a < 500; ++a)
{
for (int b = 1; b < 500; ++b)
{
for (int c = 1; c < 500; ++c)
{
if ((a + b + c) == 1000 && ((a*a + b*b) == (c*c)))
{
cout << "The product abc = " << a*b*c << endl << "a = " << a << ", b = " << b << ", c = " << c << endl;
flag = true;
break;
}
}
if(flag)
{ break; }
}
if(flag)
{ break; }
}
cout << endl << "Loop terminated";
char d;
cin >> d;
return 0;
}
break
ты использовал просто ломает самое внутреннее for
цикл не все петли.
Используйте флаг и and
это к for
условия:
bool found = false;
for (int a = 1; a < 500 && !found; ++a)
{
for (int b = 1; b < 500 && !found; ++b)
{
for (int c = 1; c < 500 && !found; ++c)
{
if ((a + b + c) == 1000 && ((a*a + b*b) == (c*c)))
{
cout << "The product abc = " << ....
found = true;
}
}
}
}
или даже вы можете использовать goto
вежливо !
for (int a = 1; a < 500; ++a)
{
for (int b = 1; b < 500; ++b)
{
for (int c = 1; c < 500; ++c)
{
if ((a + b + c) == 1000 && ((a*a + b*b) == (c*c)))
{
cout << "The product abc = " << ...
goto break_all;
}
}
}
}
break_all:
Как уже говорили многие люди, break
вырывается только из самой внутренней петли.
Некоторые языки позволяют решить эту проблему. Ада определенно имеет способ назвать каждую петлю, и ее ближайший эквивалент, чтобы сломать, exit when <condition>;
также может быть написано exit <loopname> when <condition>;
, IIRC C # также может иметь специальный синтаксис для этого.
В C ++ ваши варианты …
использование goto
скорее, чем break
, Поместите метку цели сразу после самой внешней петли.
throw
исключение для выхода из цикла, когда все вложенные циклы вложены в try
блок.
Не вырваться из цикла вообще. Вместо этого есть флаг, done
или аналогичный, чтобы указать, когда вы закончите. Проверьте это в условиях всех петель.
Как Джерри Гроб сказал, используйте переместить петли в отдельную функцию и использовать return
(не знаю, как я пропустил это!).
Пуристы, вероятно, предпочтут 3, с опцией 2. В частности, единственная опция, которая не нарушает «принцип единого выхода» из структурированного программирования, это (3), но break
также нарушает этот принцип в любом случае. Лично я бы предпочел 1, поскольку он генерирует меньше беспорядка, поэтому (при условии, что функция, в которой вы его используете, мала, и goto
визуально очевидно) это более читабельно.
С помощью goto
как правило, избегается по уважительной причине. Многие люди полностью их запрещают, что менее оправдано, но эти люди, вероятно, break
а также continue
быть «скрытым gotos» и запретить их тоже (за исключением break
в switch
заявления, конечно). Во всяком случае, в результате вы можете даже не знать, что goto
возможно.
Там есть описание синтаксиса для goto
Вот — в принципе goto <labelname>;
а также labelname:
,
Ваш код будет очень медленным, если вы попытаетесь проверить немного больший диапазон чисел. Вы на самом деле пробуете все значения для c от 1 до 500 и проверяете, является ли a + b + c = 1000. Очевидно, что сумма равна только 1000, если c = 1000 — a — b. Так что вы можете просто написать
int c = 1000 - a - b;
if ((c >= 1 && c < 500) && (a*a + b*b == c*c)) ...
Это будет работать примерно в 500 раз быстрее …
Теперь вам не нравится, что печатается a = 200, b = 375 и a = 375, b = 200. Вы можете подумать об операторе break, но это может привести к ошибке: существует множество случаев, когда есть несколько решений, которые тривиально не связаны, как здесь.
Вам нужно избегать печати решений, где a> b, потому что если (a, b, c) является решением, то (b, a, c) также является решением. Простой способ сделать это — написать
for (int b = a; b < 500; ++b) ...
Когда a = 375, только значения от 375 до 499 проверяются для b, что позволяет избежать печати a = 375, b = 200.