9) [C++ Error] Unit1.cpp(N): E2121 Function call missing )
Це повідомлення свідчить про те, що було пропущено (або поставлено у невідповідному місці) круглу дужку, що закриває список параметрів при викликанні функції. Найчастіш це буває, коли поряд йде кілька дужок (рис. 15.11). Слід уважно перевірити кількість круглих дужок у рядку і правильність їхнього розташування.
Рис. 15.11. Помилка Е2121: пропущено круглу дужку у виклику функції
10) [C++ Error] Unit1.cpp(N): E2227 Extra parameter in call to pow(double, double)
Така помилка виникає, коли кількість параметрів при викликанні функції перевищує їхню кількість за синтаксисом. У прикладі на рис. 15.12 замість десяткової крапки у числі 5.1 (або 1.4) було поставлено кому, і компіляторові “здалося”, що викликається функція pow() з трьома параметрами замість двох. Слід перевірити правильність написання чисел, відповідність параметрів і правильність розташування круглої дужки, яка закриває виклик функції (можливо, її було пропущено чи помилково поставлено в інше місце).
550
Розділ 15
Рис. 15.12. Помилка Е2227: виклик функції pow() з трьома параметрами замість двох
11) [C++ Error] Unit1.cpp(N): E2193 Too few parameters in call to 'pow(double, double)'
Така помилка виникає, коли кількість параметрів є менша, аніж вимагає синтаксис. У прикладі на рис. 15.13, можливо, десяткова крапка поставлена випадково замість коми, яка розділяє параметри, або пропущено один з параметрів. Слід уважно перевірити список фактичних параметрів при викликанні функції.
Рис. 15.13. Помилка Е2193: виклик функції pow() з одним параметром замість двох
Оскільки, зазвичай, break припиняє виконування циклу, то якщо його розташовано поза циклом, видається така помилка. Вона свідчить про те, що присутність break в цьому місці програми не має сенсу. Слід уважно перевірити, чому так сталося, що break опинився поза циклом. Можливо, пропущено фігурні дужки (рис. 15.14)? Чи ці дужки закрито завчасно? Чи дійсно вживати break не було сенсу?
Налагодження програм
551
Рис. 15.14. Помилка Е2030: пропущено фігурні дужки і вживання break немає сенсу
Інструкція else міститься не на власному місці. Така помилка виникає, коли неможливо встановити, до якого if належить else. У прикладі на рис. 15.15 ця помилка виникла внаслідок того, що було помилково поставлено крапку з комою одразу після умови і вважається, що умовний оператор вже завершився і else до нього не належить. У прикладі на рис. 15.16 ця помилка виникла внаслідок того, що пропущено операторні (фігурні) дужки після умови і пе-
ред else.
Рис. 15.15. Помилка Е2054: неможливо встановити, до якого if належить else, через зайву крапку з комою після умови
552
Розділ 15
Рис. 15.16. Помилка Е2054: неможливо встановити, до якого if належить else, через те, що пропущено фігурні дужки
14) [C++ Error] Unit1.cpp(N): E2034 Cannot convert 'int' to 'char'
Така помилка виникає за спроби присвоїти змінній значення, яке не може бути неявно перетвореним на тип цієї змінної, тобто виникає суперечка типів. На рис. 15.17 показано дві такі помилки: в рядку 23 число 15 не може бути неявно перетвореним у тип char*, а в наступному – 24-му рядку послідовність символів не можна записати в один символ. Така сама помилка виникає за спроби задати фактичні параметри функції зі значенням, яке не може бути неявно перетвореним на тип, зазначений при оголошенні функції.
Помилка виникає внаслідок неправильного розташування операторних дужок. У прикладі на рис. 15.18 дужка після s++; закрита завчасно, компілятор інтерпретує її як завершення тексту функції Button1Click, тому вважається, що наступні рядки є некоректні (можливо, зайві). Слід уважно перевірити відповідність і правильність розташування усіх фігурних дужок.
16) [C++ Error] Unit2.cpp(N): E2356 Type mismatch in redeclaration of 'sum(int, int) '
Найчастіше така помилка виникає у визначенні функції, коли у заголовку функції було зазначено інший тип результату (рис. 15.19). Слід уважно простежити, щоб прототип функції та її визначення (реалізація) мали однаковий тип результату.
Рис. 15.19. Помилка Е2356: типи функції в оголошенні та визначенні не збігаються
17) [C++ Error] Unit2.cpp(N): E2308 do statement must have while
Помилка виникає внаслідок неправильного розташування операторних дужок (компілятор чекає на while після s++;}, але не знаходить цієї інструкції
18) [C++ Error] Unit2.cpp(N) E2308 Unterminated string or character constant
Помилка виникає, коли в кінці рядка чи після символу пропущено лапки, тобто рядок не завершено (рис. 15.21).
Рис. 15.21. Помилка Е2380: пропущено лапки
19) [C++ Error] Unit1.cpp(N): E2376 If statement missing (
Помилка виникає, коли пропущено одну чи обидві дужки в умові оператора if (рис. 15.22).
Рис. 15.22. Помилка Е2376: пропущено дужки в умові оператора if
Налагодження програм
555
20) [C++ Error] Unit1.cpp(N): E2378 For statement missing ;
Помилка виникає, коли замість крапки з комою стоїть кома (рис. 15.23) чи інший символ або крапка з комою взагалі відсутня (рис. 15.24). Перевірте наявність складових частин оператора for та їх розділювачів – крапок з комами.
Рис. 15.23. Помилка Е2378: розділювач у операторі for – кома замість крапки з комою
Рис. 15.24. Помилка Е2378: друга крапка з комою у for є відсутня
21) [C++ Error] Unit1.cpp(N): E2060 Illegal use of floating point
Помилка виникає за спроби виконати операцію, для дійсних чисел не визначену, наприклад обчислення остачі від ділення (рис. 15.25). Перевірте правильність виразу. Можливо, слід змінити тип операнда (з float на int) чи операцію.
Рис. 15.25. Помилка Е2378: операцію обчислення остачі від ділення дійсних чисел не визначено
556
Розділ 15
22) [C++ Error] Unit1.cpp(N): E2015 Ambiguity between '_fastcall
Sysutils::IntToStr(__int64)' and '_fastcall Sysutils::IntToStr(int)'
Помилка виникає за спроби задати фактичний параметр іншого типу, аніж формальний (на рис. 15.26 функція IntToStr() чекає на ціле число, а зустрічає дійсне).
Рис. 15.26. Помилка Е2378: фактичний параметр у функції IntToStr() дійсний замість цілого
15.2 Попередження і підказки
За виявляння у програмі неточностей, які не є помилками, компілятор виводить підказки (Hints) і попередження (Warnings). Доволі часто вони допомагають програмістові уникнути логічних помилок у програмі.
Розглянемо деякі з найбільш поширених попереджень і підказок.
Попередження виводиться, коли в умові замість операції порівняння “==” використовується оператор присвоювання “=” (рис. 15.27).
Рис. 15.27. Попередження W8060: замість операції порівняння використано оператор присвоювання
Налагодження програм
557
2) [C++ Warning] Unit1.cpp(N) W8004 'x' is assigned a value that is never used
Змінній х присвоєно значення, яке ніде не використовується. Це зауваження може сигналізувати про те, що значення виразу обчислено, але не виведено. Або про те, що значення обчислено, але далі замість нього використовується інша змінна, що призводить до логічної помилки і помилкового результату (чи взагалі нездобуття результату).
3) [C++ Warning] Unit1.cpp(N) W8004 Possible use of x before definition
Змінній х не присвоєно початкове значення.
15.3 Компонування
Якщо у програмі немає синтаксичних помилок, можна виконувати компонування. Для цього слід у меню Project обрати команду Make чи Build. Різниця поміж командами Make й Build полягає в такому. Команда Make забезпечує компонування файлів проекту, а команда Build – примусову перекомпіляцію, а потім компонування.
На етапі компонування також можуть виникати помилки. Найчастіше причиною помилок при компонуванні є недоступність файлів бібліотек чи інших раніше відкомпільованих модулів.
Наприклад:
[Linker Error] Unresolved external 'sum(int, int)' referenced from … (далі йде повне ім‟я файла)
Найчастіше така помилка виникає у багатофайловому проекті, коли в заголовному файлі прототип функції (ім‟я чи щось інше) не збігається з іменем функції при виклику чи то заголовком функції в її реалізації. Наприклад, помилка на рис. 15.28 виникла внаслідок того, що в заголовному файлі Unit2.h ім‟я функції sum написано з малої літери, а в Unit2.cpp – з великої (тобто не збігається регістр і імена вважаються за різні). Слід уважно простежити, щоб прототип функції, її визначення (реалізація) і виклик мали однакове ім‟я.
Рис. 15.28. Помилка на етапі компонування: імена функції в оголошенні (у .h файлі) та визначенні (у .cpp файлі) не збігаються
558
Розділ 15
15.4 Помилки етапу виконання
Помилки другого рівня (помилки етапу виконання – run time errors) або виняткові ситуації (exceptions) зазвичай пов‟язані з некоректними початковими значеннями, помилками обраного алгоритму чи неправильною програмною реалізацією алгоритму. Ці помилки виявляються в тому, що результат обчислень є неправильним або відбувається переповнення, ділення на нуль, зависання програми тощо. Тому вже налагоджену програму обов‟язково слід протестувати, тобто зробити розрахунки за таких комбінацій початкових даних, для котрих заздалегідь є відомий результат. Якщо тестові розрахунки вказують на помилку, для її пошуку слід використовувати вбудовані способи налагодження середовища C++ Builder.
Найпоширеніші причини помилок етапу виконання:
1)неправильне визначення вихідних даних;
2)логічні помилки;
3)накопичування похибок результатів обчислень.
У простому випадку для локалізації місця помилки рекомендовано чинити в такий спосіб. У вікні редактора програмного коду встановити курсор у рядку перед підозрілою ділянкою і натиснути клавішу <F4> (виконання до курсора). Виконання програми буде призупинено на рядку, в якому перебуває курсор. Тепер можна переглянути значення всіх змінних, обчислених до цього рядка. Для цього слід помістити чи підвести до змінної курсор миші (на екрані поряд зі змінною висвітиться її значення) або натиснути <Ctrl>+<F7> і у діалоговому вікні, яке з‟явиться, вказати змінну (за допомогою даного вікна також можна змінювати значення змінної у перебігу виконування програми). Натискаючи клавішу <F7> (покрокове виконування), можна виконувати програму по рядках, контролюючи змінювання тих чи інших змінних і правильність обчислень. Якщо курсор перебуває усередині циклу, після натискання <F4> розрахунок зупиняється після одного виконання операторів тіла циклу. Для продовження обчислень слід натиснути кнопку запуску програми на виконання.
Наведемо приклади типових помилок етапу виконання програми. 1) У програмі міститься код
void __fastcall TForm1::Button1Click
(TObject *Sender)
{ float x=5.7, y; Edit1->Text=x/y;
}
Результат програми є помилковим. Причина полягає в тому, що при діленні використовується змінна у, значення якої до ділення не було визначено, тобто воно є випадкове. Щоб уникнути цієї помилки, слід попередньо ініціалізувати змінну у.
2) Віднайти й виправити помилки у програмі з кодом