Лексико-семантические ошибки можно встретить достаточно часто, особенно в разговорной речи или переписке. Такие ошибки встречаются и при переводах с одного языка на другой. Их также называют смысловыми, потому что возникают они от неверного применения слов и словосочетаний в контексте написанного.
Классификация
Понятие «семантические ошибки» (или «лексико-семантические ошибки») охватывает несколько групп смысловых ошибок. Первая группа объединяет неверно подобранное слово в предложении. Вторая связана с употреблением слов в значении, которое им несвойственно (здесь речь идет о неверном подборе из существующих слов-синонимов). Третья группа – ошибки, возникшие из-за лексической несочетаемости фразы. Четвертая группа – неверно подобранные паронимы (слова, схожие по написанию, но с различным лексическим значением).
Неправильно подобранное слово
Такие семантические ошибки часто возникают из-за неточного понимания значения слова. Например, в предложении «За месяц мы потребили сто киловольт электричества» есть неуместное употребление слова «киловольт», т. к. электроэнергия измеряется в киловаттах. Еще один пример такой ошибки: «Покупатели магазина стали невольными зрителями этого происшествия». При прочтении такого предложения в целом понятно, о чем идет речь, но вместо слова «зрители», которое в современном русском языке по смыслу означает просмотр театрального представления, спортивного состязания или киносеанса, было бы уместнее употребить слово «свидетели», означающее присутствие во время какого-либо события. Чтобы избежать подобных ошибок, лучше не употреблять в разговорной речи и в тексте слова, в значении которых есть сомнения, либо же стоить сверить свои знания со словарем. Очень часто подобные ошибки встречаются в школьных сочинениях, поэтому ученикам особенно важно изучать точные значения различных слов.
Ошибки, связанные с употреблением синонимов
В русском языке существует множество слов-синонимов со схожим значением, но разным лексическим смыслом. Например, трофей и приз, храбрый и смелый, роль и функция. Из-за употребления неверно подобранного слова из подобных синонимов и возникают семантические ошибки. Примеры таких ошибок: «Спортсмен честно выиграл свой трофей», «Эта идея была очень храброй», «В моей жизни подобное явление сыграло свою функцию». В этих предложениях четко прослеживается, что употреблено неверное слово из пары. В первом примере логично было бы употребить слово «приз», ведь оно имеет значение некой ценности, которую выигрывают, завоевывают в соревновании. Слово «трофей» тут неуместно: оно обозначает нечто, связанное с завоеванием. Например, охотничий, военный трофей. Во втором примере следовало бы употребить слово «смелый», ведь оно обозначает не только внешнее проявление, но и некое внутреннее свойство человека (смелыми могут быть его мысли или идеи), в то время как слово «храбрый» обычно относят к поведению в конкретной ситуации. В третьем примере нужно было использовать слово «роль» вместо «функция», т. к. слово «роль» означает то, что играют или изображают, в том числе в переносном смысле, а «функция» – то, что выполняется, взаимодействует.
Несочетаемость
Семантические ошибки такого типа возникают из-за неверного сочетания слов в предложении. Часто они появляются в момент быстрого написания какого-либо текста без последующей проверки. Например, ошибка этой группы есть в предложении «Герой попал в несчастье». Конечно же, вместо слова «несчастье» тут было бы уместно употребить слово «беда». Хотя эти слова являются схожими по значению, но в данном предложении слово «несчастье» с остальной конструкцией не сочетается. Употребить именно это слово возможно, если перестроить остальную часть предложения: «С героем случилось несчастье».
Еще один пример такого типа ошибок: «Более неуверенные в себе люди часто одиноки». В этом предложении правильно было бы употребить такие фразы: «Менее уверенные в себе люди часто одиноки» или «Более робкие люди часто одиноки». Ведь само словосочетание «более неуверенные» лексически неоправданно: первое слово предполагает большую степень качества, а второе – отрицание качества. И хотя общий смысл в подобных предложениях обычно понятен, подобных ошибок следует избегать.
Ошибки из-за неверного подбора паронимов
Эта группа семантических ошибок связана с выбором неверного слова из существующих для обозначения явления или предмета паронимов. Чаще всего паронимы являются однокоренными словами, схожими по значению, но в то же время обозначающими разные понятия. Это, например, такие пары слов, как «высотный-высокий», «дальний-далекий», «логический-логичный», «экономический-экономичный», «короткий-краткий» и т. д. Например, в предложении «У фильма вполне логическая концовка» неверно выбран пароним: вместо слова «логическая» нужно было употребить слово «логичная». Ведь слово «логический» применяется только для обозначения явления, основанного на законах логики, а слово «логичный», кроме этого, означает еще и некую последовательность или закономерность, и как раз это значение по смыслу подходит предложению из примера.
Еще один пример предложения, где есть подобная семантическая ошибка: «Значение этого параметра говорит о хорошей экономичной эффективности». В данном случае речь шла об экономической эффективности, т. е. показателе, связанном с экономикой, а в предложении подобран неверный пароним: «экономичный». Это слово означает выгоду в хозяйственном отношении и по смыслу к данному предложению не подходит.
Семантические ошибки при переводе
Автор, пишущий на родном языке, сталкивается с проблемами появления смысловых ошибок гораздо реже, чем переводчик. Ведь переводчик в процессе своей работы сталкивается с тем, что необходимо четко знать не только грамматику и правила построения предложений для обоих языков, но и понимать, какой смысл у каждого слова именно в том значении, в котором оно употреблено. Очень важно понимать лексическую сочетаемость слов в предложениях, чтобы не допустить семантических ошибок.
В языке, с которого осуществляется перевод, может употребляться много устойчивых выражений, которые при последовательном переводе каждого слова абсолютно теряют смысл. Обычно такие выражения без труда видит опытный переводчик, но начинающий, даже самый грамотный, не всегда сможет их распознать. Поэтому после перевода любой научной статьи или литературного произведения получившийся результат отдается на проверку редактору, который сможет оценить качество перевода и в случае необходимости внести поправки. Конечно, бывает, что срабатывает человеческий фактор, и ошибка остается незамеченной и редактором.
Пример ошибки при переводе
Семантическая ошибка имеет место в переводе И. Кашкина произведения «Владетель Баллантрэ» Р. Стивенсона: «Единственно, чего я добиваюсь, — это оградить себя от клеветы, а дом мой – от вашего вторжения». В этом предложении уместно было бы употребить числительное «единственное» вместо наречия «единственно».
В литературе
Семантические ошибки встречаются и в литературных произведениях. В большинстве случаев это связано с тем, что значения тех или иных слов, а также правила их написания и употребления меняются со временем. Например, в одном из произведений А. С. Пушкина можно встретить следующее словосочетание: «Румянцев повез его на аппробацию Петра». Из контекста становится понятным, что слово «апробация» в то время имело значение «утверждение, одобрение». Затем это слово изменилось и в написании (стало употребляться с одной «п»), и в значении: стало обозначать утверждение после произведенного испытания. Поэтому сегодня приведенное выше выражение воспринимается как ошибочное.
Еще один пример – словосочетание из романа Б. Полевого «Глубокий тыл»: «Большая половина фабрики». В данном случае ошибочно употреблено слова «половина», означающее равную часть, ½ целого. Половина не может быть большей или меньшей, поэтому такое сочетание слов является ошибкой. Однако подобные выражения можно встретить и в других произведениях, а также в периодической печати.
Отладка программы призвана выискивать «вредителей» кода и устранять их. За это отвечают отладчик и журналирование для вывода сведений о программе.
В предыдущей части мы рассмотрели исходный код и его составляющие.
После того, как вы начнете проверять фрагменты кода или попытаетесь решить связанные с ним проблемы, вы очень скоро поймете, что существуют моменты, когда программа крашится, прерывается и прекращает работу.
Это часто вызвано ошибками, известными как дефекты или исключительные ситуации во время выполнения. Акт обнаружения и удаления ошибок из нашего кода – это отладка программы. Вы лучше разберетесь в отладке на практике, используя ее как можно чаще. Мы не только отлаживаем собственный код, но и порой дебажим написанное другими программистами.
Для начала необходимо рассортировать общие ошибки, которые могут возникнуть в исходном коде.
Синтаксические ошибки
Эти эрроры не позволяют скомпилировать исходный код на компилируемых языках программирования. Они обнаруживаются во время компиляции или интерпретации исходного кода. Они также могут быть легко обнаружены статическими анализаторами (линтами). Подробнее о линтах мы узнаем немного позже.
Синтаксические ошибки в основном вызваны нарушением ожидаемой формы или структуры языка, на котором пишется программа. Как пример, это может быть отсутствующая закрывающая скобка в уравнении.
Семантические ошибки
Отладка программы может потребоваться и по причине семантических ошибок, также известных как логические. Они являются наиболее сложными из всех, потому что не могут быть легко обнаружены. Признак того, что существует семантическая ошибка, – это когда программа запускается, отрабатывает, но не дает желаемого результата.
Рассмотрим данный пример:
3 + 5 * 6
По порядку приоритета, называемому старшинством операции, с учетом математических правил мы ожидаем, что сначала будет оценена часть умножения, и окончательный результат будет равен 33. Если программист хотел, чтобы сначала происходило добавление двух чисел, следовало поступить иначе. Для этого используются круглые скобки, которые отвечают за смещение приоритетов в математической формуле. Исправленный пример должен выглядеть так:
(3 + 5) * 6
3 + 5, заключенные в скобки, дадут желаемый результат, а именно 48.
Ошибки в процессе выполнения
Как и семантические, ошибки во время выполнения никогда не обнаруживаются при компиляции. В отличие от семантических ошибок, эти прерывают программу и препятствуют ее дальнейшему выполнению. Они обычно вызваны неожиданным результатом некоторых вычислений в исходном коде.
Вот хороший пример:
input = 25 x = 0.8/(Math.sqrt(input) - 5)
Фрагмент кода выше будет скомпилирован успешно, но input 25 приведет к ZeroDivisionError. Это ошибка во время выполнения. Другим популярным примером является StackOverflowError или IndexOutofBoundError. Важно то, что вы идентифицируете эти ошибки и узнаете, как с ними бороться.
Существуют ошибки, связанные с тем, как ваш исходный код использует память и пространство на платформе или в среде, в которой он запущен. Они также являются ошибками во время выполнения. Такие ошибки, как OutOfMemoryErrorand и HeapError обычно вызваны тем, что ваш исходный код использует слишком много ресурсов. Хорошее знание алгоритмов поможет написать код, который лучше использует ресурсы. В этом и заключается отладка программы.
Процесс перезаписи кода для повышения производительности называется оптимизацией. Менее популярное наименование процесса – рефакторинг. Поскольку вы тратите больше времени на кодинг, то должны иметь это в виду.
Отладка программы
Вот несколько советов о том, как правильно выполнять отладку:
- Использовать Linters. Linters – это инструменты, которые помогают считывать исходный код, чтобы проверить, соответствует ли он ожидаемому стандарту на выбранном языке программирования. Существуют линты для многих языков.
- Превалирование IDE над простыми редакторами. Вы можете выбрать IDE, разработанную для языка, который изучаете. IDE – это интегрированные среды разработки. Они созданы для написания, отладки, компиляции и запуска кода. Jetbrains создают отличные IDE, такие как Webstorm и IntelliJ. Также есть NetBeans, Komodo, Qt, Android Studio, XCode (поставляется с Mac), etc.
- Чтение кода вслух. Это полезно, когда вы ищете семантическую ошибку. Читая свой код вслух, есть большая вероятность, что вы зачитаете и ошибку.
- Чтение логов. Когда компилятор отмечает Error, обязательно посмотрите, где он находится.
Двигаемся дальше
Поздравляем! Слово «ошибка» уже привычно для вас, равно как и «отладка программы». В качестве новичка вы можете изучать кодинг по книгам, онлайн-урокам или видео. И даже чужой код вам теперь не страшен
В процессе кодинга измените что-нибудь, чтобы понять, как он работает. Но будьте уверены в том, что сами написали.
Викторина
- Какая ошибка допущена в фрагменте кода Python ниже?
items = [0,1,2,3,4,5] print items[8] //комментарий: элементы здесь представляют собой массив с шестью элементами. Например, чтобы получить 4-й элемент, вы будете использовать [3]. Мы начинаем отсчет с 0.
- Какая ошибка допущена в фрагменте кода Python ниже?
input = Hippo' if input == 'Hippo': print 'Hello, Hippo'
Ответы на вопросы
- Ошибка выполнения: ошибка индекса вне диапазона.
2. Синтаксическая ошибка: Отсутствует стартовая кавычка в первой строке.
The third type of error is the semantic error, also called a logic error. If there is a semantic error
in your program, it will run successfully in the sense that the computer will
not generate any error messages. However, your program will not do the right thing. It will do
something else. Specifically, it will do what you told it to do, not what you wanted it to do.
The following program has a semantic error. Execute it to see what goes wrong:
This program runs and produces a result. However, the result is not what the programmer intended. It contains
a semantic error. The error is that the program performs concatenation instead of addition, because the programmer
failed to write the code necessary to convert the inputs to integers.
With semantic errors, the problem is that the program you wrote is not the program you wanted to
write. The meaning of the program (its semantics) is wrong. The computer is
faithfully carrying out the instructions you wrote, and its results
are correct, given the instructions that you provided. However, because your instructions
have a flaw in their design, the program does not behave as desired.
Identifying semantic errors can be tricky because no error message appears to make it obvious that the results are
incorrect. The only way you can detect semantic errors is if you know in advance what the program should do for a given set
of input. Then, you run the program with that input data and compare the output of the program with what you expect. If
there is a discrepancy between the actual output and the expected output, you can conclude that there is either 1) a
semantic error or 2) an error in your expected results.
Once you’ve determined that you have a semantic error, locating it can be tricky because you must work
backward by looking at the output of the program and trying to figure out what it is doing.
3.7.1. Test Cases¶
To detect a semantic error in your program, you need the help of something called a test case.
Test Case
A test case is a set of input values for the program, together with the output that you expect the program should produce when it is run with those particular
inputs.
Here is an example of a test case for the program above:
Test Case --------- Input: 2, 3 Expected Output: 5
If you give this test case to someone and ask them to test the program, they can type in the inputs, observe the output,
check it against the expected output, and determine whether a semantic error exists based on whether the actual output
matches the expected output or not. The tester doesn’t even have to know what the program is supposed to do. For this reason,
software companies often have separate quality assurance departments whose responsibility is to check that the programs written
by the programmers perform as expected. The testers don’t have to be programmers; they just have to be able to operate the
program and compare its results with the test cases they’re given.
In this case, the program is so simple that we don’t need to write down a test case at all; we can compute the expected output
in our heads with very little effort. More complicated programs require effort to create the test case (since you shouldn’t use
the program to compute the expected output; you have to do it with a calculator or by hand), but the effort pays off when
the test case helps you to identify a semantic error that you didn’t know existed.
Semantic errors are the most dangerous of the three types of errors, because in some cases they are not noticed by either
the programmers or the users who use the program. Syntax errors cannot go undetected (the program won’t run at all if
they exist), and runtime errors are usually also obvious and typically detected by developers before a program is
released for use (although it is possible for a runtime error to occur for some inputs and not for
others, so these can sometimes remain undetected for a while). However, programs often go for years with undetected
semantic errors; no one realizes that the program has been producing incorrect results. They just assume that because the
results seem reasonable, they are correct. Sometimes, these errors are relatively harmless. But if they involve
financial transactions or medical equipment, the results can be harmful or even deadly. For this reason, creating test
cases is an important part of the work that programmers perform in order to help them produce programs that work
correctly.
Check your understanding
- Attempting to divide by 0.
- A semantic error is an error in logic. In this case the program does not produce the correct output because the problem is not solved correctly. This would be considered a run-time error.
- Forgetting a right-parenthesis ) when invoking a function.
- A semantic error is an error in logic. In this case the program does not produce the correct output because the code can not be processed by the compiler or interpreter. This would be considered a syntax error.
- Forgetting to divide by 100 when printing a percentage amount.
- This will produce the wrong answer because the programmer implemented the solution incorrectly. This is a semantic error.
Which of the following is a semantic error?
- The programmer.
- You must fully understand the problem so that you can tell if your program properly solves it.
- The compiler / interpreter.
- The compiler and / or interpreter will only do what you instruct it to do. It does not understand what the problem is that you want to solve.
- The computer.
- The computer does not understand your problem. It just executes the instructions that it is given.
- The teacher / instructor.
- Your teacher and instructor may be able to find most of your semantic errors, but only because they have experience solving problems. However it is your responsibility to understand the problem so you can develop a correct solution.
Who or what typically finds semantic errors?
You have attempted of activities on this page
Семантические ошибки в программировании
Ранее я рассказывал о видах ошибок в программировании. И там я упомянул об ошибках, которые я назвал логическими. Но вообще такие ошибки часто называют семантическими. И это самые труднонаходимые ошибки, которые доставляют программистам больше всего неприятностей. Поэтому я решил рассказать о них отдельно.
Семантика — это раздел лингвистики (науки о языках), который изучает смысловое значение частей языка (слов, предложений и т.п.).
Поскольку языки программирования — это тоже языки, то и правила и термины лингвистики точно также применимы и к языкам программирования. А семантика в языке программирования означает то же самое, что и в человеческом языке, например, в русском.
Семантика определяет смысл программы, а семантические ошибки связаны с нарушением смысла программы. То есть семантические ошибки нарушают логику программы (поэтому я и назвал их ранее логическими).
С точки зрения синтаксиса программа может быть безупречной. И даже во время выполнения в ней может не быть никаких ошибок. Но при этом она может быть бессмысленна с точки зрения решаемой задачи.
Например, вам надо было написать программу, которая вычисляет площадь круга. А вы “немного” ошиблись, и ваша программа вычисляет площадь прямоугольника.
При этом:
- Программа компилируется без ошибок
- Программа запускается, работает и завершается без ошибок
- Программа получает данные, обрабатывает их и выдаёт результат
Но, что самое страшное — пользователь думает, что результат правильный!!!
То есть программа безупречна во всём. Кроме одного — она решает не ту задачу, которую нужно решить пользователю. Поэтому с точки зрения пользователя она бессмысленна.
А с точки зрения программиста она содержит семантическую ошибку.
Такая программа делает не то, что вы от неё хотели, а то, что вы ей сказали. Вы ей сказали вычислять площадь прямоугольника, и она делает это. И это не её вина, а ваша. Вы дали неправильное указание.
Кстати, плохие руководители в жизни ведут себя точно также — дают сотрудникам неправильные или неоднозначные распоряжения, а потом удивляются, что работа выполнена неправильно. И обвиняют в этом, конечно, сотрудников.
Находить семантические ошибки бывает очень трудно. Особенно в чужих программах. Я это знаю не понаслышке. Иногда на это уходит несколько дней или даже недель. Иногда вообще хочется плюнуть на это и написать новую программу.
Так что старайтесь ещё до того, как начнёте писать код, тщательно продумать алгоритмы и прочие способы решения задачи, чтобы потом не было мучительно больно при поиске таких ошибок, которые не видит компилятор, и мучительно стыдно перед заказчиком.
А на сегодня всё. Подключайтесь к каналу в Телеграм или к другим моим группам, чтобы ничего не пропустить.
Основы программирования Каждый профессионал когда-то был чайником. Наверняка вам знакомо состояние, когда “не знаешь как начать думать, чтобы до такого додуматься”. Наверняка вы сталкивались с ситуацией, когда вы просто не знаете, с чего начать. Эта книга ориентирована как раз на таких людей, кто хотел бы стать программистом, но совершенно не знает, как начать этот путь. Подробнее… |
Добавлено 30 мая 2021 в 17:27
В уроке «3.1 – Синтаксические и семантические ошибки» мы рассмотрели синтаксические ошибки, которые возникают, когда вы пишете код, который не соответствует грамматике языка C++. Компилятор уведомит вас об ошибках этого типа, поэтому их легко обнаружить и обычно легко исправить.
Мы также рассмотрели семантические ошибки, которые возникают, когда вы пишете код, который выполняет не то, что вы планировали. Как правило, компилятор не обнаруживает семантических ошибок (хотя в некоторых случаях умные компиляторы могут генерировать предупреждения).
Семантические ошибки могут вызывать большинство из симптомов неопределенного поведения, например, приводить к тому, что программа выдает неправильные результаты, быть причиной неустойчивого поведения, искажать данные программы, вызывать сбой программы – или они могут вообще никак не влиять.
При написании программ семантические ошибки практически неизбежны. Некоторые из них вы, вероятно, заметите, просто используя программу: например, если вы писали игру лабиринт, а ваш персонаж может проходить сквозь стены. Тестирование вашей программы (7.12 – Введение в тестирование кода) также может помочь выявить семантические ошибки.
Но есть еще одна вещь, которая может помочь – это знание того, какой тип семантических ошибок наиболее распространен, чтобы вы могли потратить немного больше времени на то, чтобы убедиться, что в этих случаях всё правильно.
В этом уроке мы рассмотрим ряд наиболее распространенных типов семантических ошибок, возникающих в C++ (большинство из которых так или иначе связаны с управлением порядком выполнения программы).
Условные логические ошибки
Один из наиболее распространенных типов семантических ошибок – это условная логическая ошибка. Условная логическая ошибка возникает, когда программист неправильно пишет логику условного оператора или условия цикла. Вот простой пример:
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int x{};
std::cin >> x;
if (x >= 5) // упс, мы использовали operator>= вместо operator>
std::cout << x << " is greater than 5";
return 0;
}
А вот результат запуска программы, при котором была обнаружена эта условная логическая ошибка:
Enter an integer: 5
5 is greater than 5
Когда пользователь вводит 5, условное выражение x >= 5
принимает значение true
, поэтому выполняется соответствующая инструкция.
Вот еще один пример для цикла for
:
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int x{};
std::cin >> x;
// упс, мы использовали operator> вместо operator<
for (unsigned int count{ 1 }; count > x; ++count)
{
std::cout << count << ' ';
}
return 0;
}
Эта программа должна напечатать все числа от 1 до числа, введенного пользователем. Но вот что она на самом деле делает:
Enter an integer: 5
Она ничего не напечатала. Это происходит потому, что при входе в цикл for
условие count > x
равно false
, поэтому цикл вообще не повторяется.
Бесконечные циклы
В уроке «7.7 – Введение в циклы и инструкции while
» мы рассмотрели бесконечные циклы и показали этот пример:
#include <iostream>
int main()
{
int count{ 1 };
while (count <= 10) // это условие никогда не будет ложным
{
std::cout << count << ' '; // поэтому эта строка выполняется многократно
}
return 0; // эта строка никогда не будет выполнена
}
В этом случае мы забыли увеличить count
, поэтому условие цикла никогда не будет ложным, и цикл продолжит печатать:
1 1 1 1 1 1 1 1 1 1
пока пользователь не закроет программу.
Вот еще один пример, который преподаватели любят задавать в тестах. Что не так со следующим кодом?
#include <iostream>
int main()
{
for (unsigned int count{ 5 }; count >= 0; --count)
{
if (count == 0)
std::cout << "blastoff! ";
else
std::cout << count << ' ';
}
return 0;
}
Эта программа должна напечатать «5 4 3 2 1 blastoff!«, что она и делает, но не останавливается на достигнутом. На самом деле она печатает:
5 4 3 2 1 blastoff! 4294967295 4294967294 4294967293 4294967292 4294967291
а затем просто продолжает печатать уменьшающиеся числа. Программа никогда не завершится, потому что условие count >= 0
никогда не может быть ложным, если count
является целым числом без знака.
Ошибки на единицу
Ошибки «на единицу» возникают, когда цикл повторяется на один раз больше или на один раз меньше, чем это необходимо. Вот пример, который мы рассмотрели в уроке «7.9 – Инструкции for
»:
#include <iostream>
int main()
{
for (unsigned int count{ 1 }; count < 5; ++count)
{
std::cout << count << ' ';
}
return 0;
}
Этот код должен печатать «1 2 3 4 5«, но он печатает только «1 2 3 4«, потому что был использован неправильный оператор отношения.
Неправильный приоритет операторов
Следующая программа из урока «5.7 – Логические операторы» допускает ошибку приоритета операторов:
#include <iostream>
int main()
{
int x{ 5 };
int y{ 7 };
if (!x > y)
std::cout << x << " is not greater than " << y << 'n';
else
std::cout << x << " is greater than " << y << 'n';
return 0;
}
Поскольку логическое НЕ имеет более высокий приоритет, чем operator>
, условное выражение вычисляется так, как если бы оно было написано (!x) > y
, что не соответствует замыслу программиста.
В результате эта программа печатает:
5 is greater than 7
Это также может произойти при смешивании в одном выражении логического ИЛИ и логического И (логическое И имеет больший приоритет, чем логическое ИЛИ). Используйте явные скобки, чтобы избежать подобных ошибок.
Проблемы точности с типами с плавающей запятой
Следующая переменная с плавающей запятой не имеет достаточной точности для хранения всего числа:
#include <iostream>
int main()
{
float f{ 0.123456789f };
std::cout << f;
}
Как следствие, эта программа напечатает:
0.123457
В уроке «5.6 – Операторы отношения и сравнение чисел с плавающей запятой» мы говорили о том, что использование operator==
и operator!=
может вызывать проблемы с числами с плавающей запятой из-за небольших ошибок округления (а также о том, что с этим делать). Вот пример:
#include <iostream>
int main()
{
// сумма должна быть равна 1.0
double d{ 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 };
if (d == 1.0)
std::cout << "equal";
else
std::cout << "not equal";
}
Эта программа напечатает:
not equal
Чем больше вы выполняете арифметических действий с числом с плавающей запятой, тем больше в нем накапливаются небольшие ошибки округления.
Целочисленное деление
В следующем примере мы хотим выполнить деление с плавающей запятой, но поскольку оба операнда принадлежат целочисленному типу, вместо этого мы выполняем целочисленное деление:
#include <iostream>
int main()
{
int x{ 5 };
int y{ 3 };
std::cout << x << " divided by " << y << " is: " << x / y; // целочисленное деление
return 0;
}
Этот код напечатает:
5 divided by 3 is: 1
В уроке «5.2 – Арифметические операторы» мы показали, что мы можем использовать static_cast
для преобразования одного из целочисленных операндов в значение с плавающей запятой, чтобы выполнять деление с плавающей запятой.
Случайные пустые инструкции
В уроке «7.3 – Распространенные проблемы при работе с операторами if
» мы рассмотрели пустые инструкции, которые ничего не делают.
В приведенной ниже программе мы хотим взорвать мир, только если у нас есть разрешение пользователя:
#include <iostream>
void blowUpWorld()
{
std::cout << "Kaboom!n";
}
int main()
{
std::cout << "Should we blow up the world again? (y/n): ";
char c{};
std::cin >> c;
if (c=='y'); // здесь случайная пустая инструкция
blowUpWorld(); // поэтому это всегда будет выполняться, так как это не часть оператора if
return 0;
}
Однако из-за случайной пустой инструкции вызов функции blowUpWorld()
выполняется всегда, поэтому мы взрываем независимо от ввода:
Should we blow up the world again? (y/n): n
Kaboom!
Неиспользование составной инструкции, когда она требуется
Еще один вариант приведенной выше программы, которая всегда взрывает мир:
#include <iostream>
void blowUpWorld()
{
std::cout << "Kaboom!n";
}
int main()
{
std::cout << "Should we blow up the world again? (y/n): ";
char c{};
std::cin >> c;
if (c=='y')
std::cout << "Okay, here we go...n";
blowUpWorld(); // упс, всегда будет выполняться. Должно быть внутри составной инструкции.
return 0;
}
Эта программа печатает:
Should we blow up the world again? (y/n): n
Kaboom!
Висячий else
(рассмотренный в уроке «7.3 – Распространенные проблемы при работе с операторами if
») также попадает в эту категорию.
Что еще?
Приведенные выше примеры представляют собой хороший образец наиболее распространенных типов семантических ошибок, которые склонны совершать на C++ начинающие программисты, но их гораздо больше. Читатели, если у вас есть дополнительные примеры, которые, по вашему мнению, являются распространенными ошибками, напишите об этом в комментариях.
Теги
C++ / CppLearnCppДля начинающихОбучениеПрограммирование