Задача: строка содержит арифметическое выражение, состоящее из целых чисел и знаков операции: [latex]+,-,*,/[/latex] (без скобок). Проверить корректность выражения (в смысле последовательности чисел и знаков операции)
Тесты:
Выражение | Ответ | Комментарий |
-1+2-3/4*5 | Верно | Работает |
-1 | Верно | Работает |
-1/-4 | Верно | Работает |
5—4 | Верно | Работает |
1 | Верно | Работает |
54-*3//6 | Ошибка | Работает. Неправильная последовательность |
5/0+42 | Ошибка | Работает. Деление на ноль |
5/ | Ошибка | Работает. После символа должно следовать число |
Объяснение переменных:
string a — строка для ввода. bool rightness — булева переменная для фиксирования ошибочного выражения.Код: Проверить на ideone.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <iostream> #include <string> #include <cmath> using namespace std; int main() { string a; bool rightness = true; cin >> a; // проверка первого символа if (a[0] == '+'||a[0] == '*'||a[0] == '/'){ rightness = false; } else if (a[a.length()-1]=='+'||a[a.length()-1]=='-'||a[a.length()-1]=='*'||a[a.length()-1]=='/'){ rightness = false; } // если всё верно (в начале и в конце стоят не знаки), то выполняется цикл, else { // который прогоняет строку на предмет двух символов подряд. for (int i = 0; (i < a.length()); i++) { if ((a[i] == '+'||a[i] == '-'||a[i] == '*'||a[i] == '/')&&(a[i+1] == '+'||a[i+1] == '*'||a[i+1] == '/')){ rightness = false; } if((a[i] == '/')&&(a[i+1] == '0')){ // случай /0 rightness = false; } } } //если нигде ошибки не было, то выведится первоначальное "Верно". cout << (rightness ? "Верно":"Ошибка"); return 0; } |
Алгоритм выполнения описан в комментариях в коде.
Особенности:
- Удобно предположить, что изначально выражение верно. И в случае отсутствия ошибок, переменной rightness присваивать ничего не нужно будет.
Итог работы:
Код проверяет правильность выражения (последовательность чисел и знаков) с учётом унарного минуса (но не плюса)*, так-же за ошибку считается деление на ноль. Примеры применения есть в тестах.
* — легко реализовать посредством удаления a[0] == '+' из соответствующих if’ах, но не стал, так как считаю унарный плюс бессмысленным.
С выражениями вида a.length()-1, a.length() — 2 нужно быть поосторожнее, т.к. не исключается, что длина строки будет небольшой, или даже 0 символов. Ситуацию усугубляет факт, что значение a.length() — беззнаковое. См. http://ideone.com/o4wJdk .
Еще один интересный момент: допускаете ли Вы унарный минус и плюс, т.е. корректно ли выражение 3+-1, или 5*-3, или совсем безобидное -3+2? Обычно такие выражения вполне допускаются — минус или плюс является унарным, если следует после символа операции (или вначале строки).
Кстати, переменную b можно было сделать логической (bool).
Спасибо за замечания.
По поводу a.length(). По условию задачи предусматривается, что выражение имеет И целое число И знак. Следовательно можно этого не боятся. Тем более что теперь a.length()-1, а не a.length()-2, т.к. я решил ещё проверять «/0».
Плюс допускать я считаю бессмысленным, он в любом случае опускается. А по поводу минуса соглашусь. Исправил.
b сделал логической и переименовал на rightness.
Отлично пусть будет rightness, только тогда лучше
Т.е. переменная булева — а при выводе мы генерируем хорошее читаемое для пользователя сообщение — это лучше всего. А то так как сейчас непонятно.
это деление на ноль проверяется? Тогда лучше так и указать «случай деления на 0 (/0)».
Удивительно, что сейчас последний знак теперь у Вас не проверяется и, например, «5-» у Вас правильное выражение.
Спасибо за замечания. Исправил.
Во первых, Вы не обновили программу на ideone.
Ну а во вторых… «Т.к. в самом начале мы проверяем первый символ, то в цикле не логично проверять его ещё раз.» — очень опасное и коварное рассуждение … вроде бы все верно, по крайней мере в изначальном варианте так и было … потом оказывается, что со знака минус выражение может начинаться — убираем минус из проверки первого символа, ОК, но теперь -*5 это правильное выражение! Как так? А ведь мы не проверяем сочетание первого символа со вторым — первый ведь же проверен.
Готово. Теперь я просто проверяю первый и последний символы, и заодно проверяю всю строку. Для надёжности. Должно работать
После первого if не хватает else — наверное, изначально он был, но потерялся в процессе переделки — по логике он быть должен, особенно учитывая комментарий // если всё верно (в начале и в конце стоят не знаки), то выполняется цикл,
Теперь по отчету — понимаю, что краткость сестра таланта, но сейчас он явно неполный. Ведь мы с Вами проговорили столько нетривиальных моментов — но, увы, они отражены только в комментариях к записи, ну и частично в комментариях к программе. А должны быть в отчете тоже. Самое главное чего не хватает — четкой формулировки, какие выражения Вы считаете правильными, а какие нет. Без этого из отчета непонятно, какую конкретно задачу Вы решали (ну или каким конкретно способом в другой формулировке).
Да, там сначала был else if, спасибо.
Дополнил отчёт.
Засчитано, 7 баллов.
for (int i = 0; (i < a.length()); i++) потом a[i+1] плохо! выход за пределы строки 1 Ошибка Работает. Должены быть и число и символ (по условию) Ваша программа выдает Верно . Я считаю, что программа работает правильно и одно число тоже является выражением — но в отчете у Вас написано не так — и хуже того Вы обманываете нас, в том что тест пройден.
Также никак не учтен случай пустой строки, но это уж ладно.
Вы проделали большую работу и программа нормальная — старайтесь аккуратнее подходить к выполнению задачи и подготовке отчета. Например, если Вы изменили программу Вы должны перепроверить все! тесты (во втором семестре мы устраним это неудобство при помощи технологии автоматического модульного тестирования) и переписать объяснение в отчете — понимаю, что это нудно, долго и неинтересно — но и мне приходится проверять отчет, программу, еще и запускать тесты — которые студенты поленились запустить — поверьте это занимает кучу времени.
Спасибо большое. Ранние версии кода на «1» выдавали «ошибку», я над этим не работал, следовательно и проверять не стал. Забавно вышло) Будет хороший опыт. Отчет отредактирую.