while ((x > -1) && ((urav[x] != '+') || (urav[x] != '-')))
while ((x > -1) && !((urav[x] == '+') || (urav[x] == '-')))
В первой строчке условие после && полностью игнорируется, в при вынесении ! за скобку, как во второй строчке, оно учитывается. Кто знает, в чем причина?
Давайте сообразим...
(urav[x] != '+') || (urav[x] != '-')
Если urav[x] - +, мы получаем false||true == true.
Если urav[x] - -, мы получаем true||false == true.
Если urav[x] - что-то еще, получаем true||true==true.
Т.е. это всегда true. Условие &&true - это просто первая часть условия.
Вот оптимизатор и выбросил лишнее.
Надеюсь, то, что !a || !b совсем не то же, что и !(a||b), для вас очевидно? Т.е. что условие во втором цикле отличается от условия в первом цикле?
На всякий случай: !a || !b по-другому записывается как !(a&&b).
А !(a||b) - как (!a && !b)...
Предполагаем, что второе условие - исходное, а первое - то что у вас получилось после внесения отрицания в скобки. Но внесение отрицания в скобки вы не правильно выполнили, тут нужно применять законы де Моргана, т.е. при внесении/вынесении отрицания логическое ИЛИ (дизъюнкция) должно меняться на И (конъюнкция), и наоборот:
!(urav[x] == '+' || urav[x] == '-') <=> (эквивалентно) (urav[x] != '+' && urav[x] != '-')
(убрал лишние скобки, т.к. операции сравнения и так имеют более высокий приоритет, чем логические операции)
Если в первом выражении, наоборот, вынести отрицание за скобки, то получим:
!(urav[x] == '+' && urav[x] == '-')
Выражение в скобках всегда ложно, т.к. значение в ячейке массива не может одновременно быть равно двум значениям, применяем отрицание - получается true. Т.е., независимо от конкретного значения в ячейке массива данное условие всегда даст вам true.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей