Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
1

Распространенные ошибки

21.09.2014, 17:33. Показов 399548. Ответов 73
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Скачать pdf:
Часто встречающиеся Ошибки.pdf
Оглавление

Ошибки этапа компиляции
Программа не компилируется или компилируется с предупреждениями.
  1. Попытка модифицировать константу через указатель
  2. Неправильное понятие приведения
  3. Лишняя точка с запятой
  4. Отсутствие точки с запятой после определения классового типа
  5. Отсутствие возврата значения из функции
  6. Использование комментариев в #define
  7. Компилятор не находит iostream.h
  8. Внутри switch ошибка Case bypasses initialization of a local variable
  9. Передача двумерных массивов и указателей в функцию
  10. Не удается открыть файл stdafx.h
  11. Ошибка "unresolved external symbol _WinMain@16"
  12. Ошибка "This function or variable may be unsafe"
  13. Компилятор не находит шаблонов описанных в других файлах проекта
Ошибки этапа выполнения
Программа прекращает работу с сообщением об ошибке
  1. Выделение памяти без дальнейшего освобождения или неверное освобождение
  2. Возврат ссылки/указателя на локальную переменную
  3. Использование неинициализированной переменной
  4. Выход за пределы массива
  5. Ошибки при использовании функции scanf()
  6. Работа с локальной копией объекта, вместо работы с самим объектом
  7. Интерпретация одиночного char символа как символьной строки
  8. Ошибка преобразования: type ** в const type **
Неправильное поведение программы на этапе исполнения
Программа исполняется, но не так, как хотелось.
  1. Неожиданное закрытие окна
  2. "Неожиданное" целочисленное деление в арифметических выражениях
  3. Ошибки в логических выражениях
  4. Лишняя точка с запятой
  5. switch без break
  6. Сравнение вещественных чисел при вычислениях
  7. Сравнение char массивов
  8. Использование чисел, записанных в других системах счисления
  9. Проверки на принадлежность значения определенному интервалу
  10. Неверный аргумент тригонометрических функций
  11. Сравнение знаковой переменной с беззнаковой
  12. Использование запятой для отделения дробной части
  13. Забытое выделение тела цикла for, while и операторов if else
  14. Определение размера массива, переданного в качестве аргумента функции
  15. Порядок вычисления аргументов при вызове функции
  16. Некорректное использование логических переменных
  17. Локальная переменная экранирует переменную с таким же именем из вышестоящей области видимости
  18. Неправильное использование memset
  19. Ошибка при использовании счётчика цикла вне цикла
Алгоритмические ошибки
Ошибки, допущенные при разработке алгоритма
  1. Двойная перестановка строк или элементов массива
  2. Использование символа цифры вместо числа
Ошибки ввода-вывода
  1. Оставление символа '\n' в потоке ввода
  2. Ошибки при использовании функции scanf()
  3. При работе с fgetc чтение файла обрывается при достижении буквы 'я'
  4. При считывании из файла последний элемент читается дважды
  5. Запись сложных объектов в бинарный файл
Ошибки, связанные с отклонением от стандарта языка
  1. Неверный тип функции main()

Ошибки проектирования АТД (классов).
  1. Вызов виртуальной функции из конструктора
  2. Отсутствие точки с запятой после определения класса/структуры
  3. Неверный вызов конструктора базового класса из конструктора производного
  4. Неверный порядок при инициализации
  5. Нарушение правила ТРЕХ.
  6. Отсутствие виртуального деструктора в базовом классе
  7. Неправильное обращение к конструктору по умолчанию
  8. Не очевидные моменты с вызовом конструктора базового класса
  9. Неявно объявленный конструктор по умолчанию
  10. Перегрузка оператора >>
  11. Невозможно обратиться к protected члену, объявленному в базовом классе
Ошибки при использовании STL контейнеров
  1. Невалидные ссылки/указатели, при перемещении объектов
  2. Ошибки связанные с итераторами (кэширование размера контейнера)
  3. Ошибки связанные с итераторами (удаление элементов по итератору в циклах)
  4. Ошибки связанные с итераторами (префикс-постфиксные инкременты при удалении элементов в цикле)
36
Лучшие ответы (1)
21.09.2014, 17:33
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.09.2014, 17:33
Ответы с готовыми решениями:

Вывести самые распространенные женские и мужские имена
Помогите решить задачу пожалуйста! Написать программу, которая формирует файл записей данной структуры Type Student=Record ...

Вывести самые распространенные мужские и женские имена
Имеется массив записей о студентах, каждая из которых включает поля: фамилия, имя, отчество, пол, возраст, курс. Разработать программу,...

Ошибки после компиляции на Visual Express 2012.Ошибки в теме
Добрый вечер ребят помогите пожалуйста.Программа написана на Visual Express 2012.Обясните что поменять чтобы зароботало. После компиляции...

73
Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
21.09.2014, 17:42  [ТС] 2
Неожиданное закрытие окна

Когда консольное приложение запускается непосредственно из среды программирования,
то после выполнения последнего оператора программы ( return 0; ) окно закрывается.
Вставляйте оператор, ожидающий ввода символа с клавиатуры перед return:
C++
1
2
3
4
5
6
7
8
#include <iostream>
 
int main()
{
    ...
    system( "pause" );
    return 0;
}
или
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
 
int main()
{
    ...
    cout << "Нажмите Enter для завершения";
    std::cin.get();
    return 0;
}
В этом случае надо учесть, что при вводе по командам типа cin>>xx; в потоке ввода остается символ конца строки, и cin.get() его прочтет. Хорошим тоном будет не забывать их удалять в момент ввода, например, так:
C++
1
(cin>>xx).get();
или с использованием библиотеки низкоуровневого ввода conio.h
(на *NIX системах она не используется):
C++
1
2
3
4
5
6
7
8
#include <conio.h>
 
int main()
{
    ...
    _getch();
    return 0;
}
14
Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
21.09.2014, 17:56  [ТС] 3
Двойная перестановка строк или элементов массива

Рассмотрим на примере инвертирования строки
C++
1
2
3
4
5
6
7
8
char str[] = "123456";
int L = strlen( str );
for ( int i = 0; i < L; i++ )
{
    char tmp = str[i];
    str[i] = str[L - i - 1];
    str[L - i - 1] = tmp;
}
Когда мы дойдем до L/2, то строка уже перевернута.
Последующие итерации до L-1 вернут буквы на прежние места.

Исправленный вариант
C++
1
2
3
4
5
6
7
8
char str[] = "123456";
int L = strlen( str );
for ( int i = 0; i < L / 2; i++ )
{
    char tmp = str[i];
    str[i] = str[L - i - 1];
    str[L - i - 1] = tmp;
}
Аналогичные ошибки бывают и при перестановке строк матрицы,
при транспонировании матрицы и т.п.


*** Updated:
Дополнительные варианты переворота:

C++
1
2
3
4
5
6
7
#include <algorithm>
 
...
 
    for ( int i = 0; i < L / 2; i++ ) {
        std::swap( str[i], str[L - i - 1] );
    }
***

C++
1
2
3
4
5
#include <algorithm>
 
...
 
    std::reverse( str, str + L );
11
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
37572 / 20859 / 4284
Регистрация: 12.02.2012
Сообщений: 34,286
Записей в блоге: 14
21.09.2014, 18:12 4
Попытка модифицировать константу через указатель

C++
1
2
3
4
5
6
7
8
9
10
11
void f( char * S )
{
    ...
    *(S + i) = 'Q'; // Будет ошибка !
}
 
int main()
{
    char * W = "Проба";
    f( W );
}
Исправить можно, заменив указатель массивом:
C++
1
2
3
4
5
6
7
8
9
10
11
void f( char * S )
{
    ...
    *(S + i) = 'Q'; 
}
 
int main()
{
    char W[] = "Проба"; // Под W выделится память на длину строки+1
    f( W );
}
Эта же ошибка и в таком примере:
C++
1
2
3
    // Неправильно
    char * S = "Hello";
    cin.getline( S, 255 );
C++
1
2
3
    // Правильно делать константный указатель на изменяемую строку, указав размер сразу
    char S[255] = "Hello"; // Указатель S менять нельзя, строку "Hello" можно
    cin.getline( S, 255 ); // Не больше чем выделено на массив, на начало которого указывает S
C++
1
2
3
4
5
    // Правильно выделять память с последующим освобождением. 
    char * S = new char [255]; // Требуется дальнейшее внимание, т.к. идет работа с памятью
    cin.getline( S, 255 );
    ...
    delete [] S;
13
Модератор
Эксперт по электронике
8956 / 6722 / 921
Регистрация: 14.02.2011
Сообщений: 23,723
21.09.2014, 18:33 5
Неправильное понятие приведения

Для приведения типов данных в C++ часто используются операции static_cast и reinterpret_cast.

Операцию приведения static_cast<новый_тип>( выражение ) можно использовать только в тех случаях,
когда компилятор выдает предупреждающее сообщение, например:
C++
1
2
double d = 1.5;
int n = static_cast<int>( d );
Обратите внимание, что круглые скобки вокруг выражения ( d ) ставятся всегда!

Если же выдается сообщение об ошибке, то нужно использовать операцию reinterpret_cast<новый_тип>( выражение ).

В этом случае только сам программист может вникнуть в суть преобразования и взять ответственность за преобразование на себя.
Вот пример, требующий приведение такого типа:
C++
1
2
3
4
5
6
7
8
9
struct typ1 { int t; };
struct typ2 { int g; };
 
    ...
 
    typ1 tp1 = { 1 };
    typ2 * p = reinterpret_cast<typ2 *>( &tp1 );
    p->g = 2;
    cout << typ1.t;
Здесь имеются два разных структурных типа typ1 и typ2.
К тому же и имена полей у них разные.
Но внутренне устройство одинаковое.
Т.е. мы понимаем, что типы данных абсолютно совместимы.
Осталось доказать это компилятору, что мы и делаем с помощью явного преобразования
C++
1
typ2 * p = reinterpret_cast<typ2 *>( &tp1 );
11
Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
22.09.2014, 08:44  [ТС] 6
Ошибки в логических выражениях

Использование присваивания (=) вместо сравнения (==).
C++
1
if ( a = 2 )
всегда истина, т.к. переменной a присваивается двойка, что при приведению к bool дает true (подробное объяснение)
Рекомендации:
Читайте предупреждения компилятора, о таком присваивании он может сообщить (но не обязательно).

Можно в операции сравнения поменять местами левую и правую часть, тогда возникнет
ошибка компиляции (невозможно присвоить значение константе):
C++
1
 if ( 2 = a )
Использование побитовых операций & и | вместо логических&& и ||
C++
1
2
3
char n = 2, k = 1;
if ( k & n )    // результат false
if ( k && n )   // результат true
Здесь n в двоичном представлении равно 00000010, а k равно 00000001.
При их побитовом (поразрядном) умножении получим везде нули 00000000, что при приведении к bool даст false.
Во втором случае каждая переменная сначала приводится к bool,
в обоих случаях получается true, а потом выполняется логическое умножение.

С Вашего позволения оставлю это (Условия Йоды, или нотация Йоды) здесь.
6
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
22.09.2014, 10:48 7
Использование символа цифры вместо числа

Например, такой код
C++
1
2
3
4
5
char с;
int n;
c = '9';
n = c + 10;
printf( "%d", n );
n присвоится не ожидаемое число 19, а 67 (или, может, другое число, если в какой-то кодировке другой код).
Это все из-за того, что в таблице кодировки ASCII символу '9' соответствует код 57 и подставляется код этого символа. Чтобы избежать этого, т.е., именно получить число 9, а не код символа, необходимо вычесть код символа '0', который равен 48.
Можно вычесть и код как есть, но понятнее будет вычесть символ '0'.
C++
1
2
3
c = '9';
n = c - '0' + 10;
printf( "%d", n );
И теперь мы уже получим желаемое 19 .
6
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.09.2014, 11:19 8
Выделение памяти без дальнейшего освобождения или неверное освобождение

а) При выделении памяти через оператор new - освобождайте её с помощью оператора delete в конце программы
C++
1
2
3
int * a = new int;
// ... использование переменной
delete a; // перед выходом из программы
При отсутствии явного освобождения программа может вызывать утечку памяти.

б) Используйте для освобождения памяти, выделенной под массив, оператор delete [], а под обычные переменные - delete.
C++
1
2
3
4
5
6
7
int * a = new int;      // переменная
int * b = new int [2];  // массив
// ...
// delete [] a; // не ОК
delete a;       // ОК
// delete b;    // не ОК
delete [] b;    // ОК
Несмотря на то, что программа скомпилируется, попытка освобождения с помощью неверного оператора вызывает UB (неопределённое поведение), что приводит к трудноуловимым ошибкам.

в) Не стоит сочетать в программе, а тем более по отношению к одной и той же переменной/массиву, разные способы выделения/освобождения памяти. При выделении памяти с помощью malloc/calloc - освобождайте её с помощью функции free, при выделении через оператор new/new [] - освобождайте с помощью оператора delete/delete []. Стоит отметить, что использование сишных способов работы с памятью в целом не одобряется.
7
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.09.2014, 20:29 9
Возврат ссылки/указателя на локальную переменную
C++
1
2
3
4
5
6
7
8
9
10
11
int & foo()
{
    int x = 42;
    return x;
}
 
int * foo2() 
{ 
    int x = 42; 
    return &x; 
}
Локальные переменные, созданные на стеке, уничтожаются при выходе из области видимости (в данном случае это выход из функции), таким образом, память получает статус свободный и туда могут записаться какие-либо данные, либо, если это еще не успело произойти, там будет по прежнему находиться 42.
9
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.09.2014, 22:41 10
Использование неинициализированной переменной

Пожалуй, одна из самых распространённых ошибок.

Компилятор о такой ошибке может выдать предупреждающее сообщение такого типа
d:\current\cpp\test\test.c(9) : warning C4700: использована неинициализированная локальная переменная "fp"
Однако, этого не произойдет, если предупреждения об ошибках отключены. В Visual Studio эта настройка регулируется командой:
Проект -> Свойства -> Свойства конфигурации -> С/С++ -> Общие -> Уровень предупреждений

Вариаций на эту тему много, приведу пару примеров:
C++
1
2
int x; // предполагалось, например, int x;cin>>x;
std::cout << x; // выведет мусор - значение, которое находилось в переменной x
Чаще всего почему-то встречается вариант с использованием неинициализированного счётчика или переменной для подсчёта суммы, как показано ниже:
C++
1
2
3
4
5
6
7
8
int main()
{
    const int arrSize = 3, arr[arrSize] = { 1, 2, 3 };
    int sum; // ложное предположение, что переменная неявно инициализируется нулём, т.е. надо писать int sum=0;
    for ( int i = 0; i < arrSize; i++ )
        sum += arr[i]; // мы к "мусору" добавляем значение элемента массива
    std::cout << sum; // выведет не то, что вы ожидали
}
Кликните здесь для просмотра всего текста
Да, статические и глобальные переменные таки инициализируются нулём по-умолчанию, но если вы это знаете, то наверняка и с проблемой выше не сталкивались

Также эта проблема кроется в частичной инициализации объектов.
C++
1
2
3
4
5
6
7
8
9
10
11
12
struct A
{
    int x, y, z;
};
 
A a;
a.x = 2;
a.y = 3;
// а здесь мы с помощью Ctrl + C, Ctrl + V породили себе проблему
a.y = 4; // а хотели написать a.z=0;
// некоторые вычисления
std::cout << a.x << " " << a.y << " " << a.z;
Некоторые программисты советуют всегда инициализировать переменные при объявлении какими-нибудь дефолтными значениями. Это особенно важно при использовании указателей, отладка которых занимает много драгоценных часов. Также могу посоветовать объявлять переменные как можно ближе к месту их использования, это поможет отследить проблему.
4
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
22.09.2014, 23:25 11
Лишняя точка с запятой
C++
1
2
3
int i;
for ( i = 0; i < 10; ++i ); // лишняя ;
    cout << i << endl;
Выведет число 10. А не последовательность от 0 до 9. В данном случае просто 10 раз выполнится пустой цикл.

Такая же ошибка очень часто встречается в определении функций:
C++
1
2
3
4
5
// неверно:
int cube_func( int x ); // скопировали объявление функции, а ; убрать забыли
{
    return x * x * x;
}
вместо:
C++
1
2
3
4
5
// верно:
int cube_func( int x )
{
    return x * x * x;
}
7
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5287 / 2374 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
23.09.2014, 08:04 12
Неверный тип возвращаемого значения функции main()

C++
1
2
3
4
5
// неправильно:
void main()
{
    // some code
}
Согласно стандарту функция main() должна возвращать целочисленное значение:
C++
1
2
3
4
5
6
// правильно:
int main()
{
    // some code
    return 0;
}
Замечание.
Для некоторых компиляторов (в том числе и Visual Studio) допускаются и другие возвращаемые типы.
И вариант:
C++
1
void main()
может использоваться.
Однако, следует помнить, что он может восприниматься как ошибка другими компиляторами.
8
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
23.09.2014, 09:18 13
Отсутствие точки с запятой после определения классового типа
C++
1
2
3
4
5
6
7
8
9
10
struct A
{
    int n;
} // забыли ;
 
int main()
{
    A a;
    return 0;
}
Данная ошибка приводит компилятор в ступор:
1>d:\current\cpp\test\tset.cpp(10) : error C2628: недопустимый 'A' с последующим 'int' (возможно, отсутствует ';')
1>d:\current\cpp\test\tset.cpp(11) : error C3874: возвращаемый тип 'main' должен быть 'int', а не 'A'
1>d:\current\cpp\test\tset.cpp(12) : error C2143: синтаксическая ошибка: отсутствие ";" перед "."
1>d:\current\cpp\test\tset.cpp(12) : error C2143: синтаксическая ошибка: отсутствие ";" перед "."
1>d:\current\cpp\test\tset.cpp(13) : error C2664: A::A(const A &): невозможно преобразовать параметр 1 из 'int' в 'const A &'
1> Причина: невозможно преобразовать 'int' в 'const A'
1> Ни один конструктор не смог принять исходный тип, либо разрешение перегрузки конструктора неоднозначно
4
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
23.09.2014, 17:29 14
Сравнение вещественных чисел при вычислениях

Поскольку арифметические вычисления для чисел с плавающей запятой выполняются с некоторой погрешностью, то их сравнение на равенство будет некорректным, например:
C++
1
 if ( a - b == 0 )
Соответственно и сравнивать их надо с некоторой точностью (которая зависит от поставленной задачи), например
C++
1
 if ( fabs( a - b ) < 1e-3 )
8
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
24.09.2014, 00:01 15
Сравнение символьных массивов
При сравнение char массивов через операторы <, ==, !=, >, <=, >= мы на самом деле сравниваем не содержимое, а указатели.
Для правильного сравнения стоит использовать специальную функцию strcmp.
C++
1
2
3
4
5
6
7
char c1[] = "b", c2[] = "a";
if ( c1 < c2 ) // ошибка! ожидаем сравнения в лексикографическом порядке
    printf( "I hope this line wouldn't printed on the screen\n" );
if ( strcmp( c1, c2 ) < 0 ) // правильное сравнение
    printf( "And it was true\n" );
else
    printf( "But I was wrong :(" );
9
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
24.09.2014, 11:52 16
Использование чисел, записанных в других системах счисления

Может показаться, что значения следующих двух переменных одинаковые:
C++
1
2
    int x = 123;
    int y = 0123;
Однако это совсем не так. Первое число (123) записано в десятичной системе счисления. Т.к. по умолчанию (и чаще всего) мы работаем с десятичной системой счисления, то x так и будет равен 123.
Второе же число (0123) записано в восьмеричной системе счисления и при переводе в десятичную будет равно 83, а не 123. Если вы работаете с десятичной системой счисления, то не добавляйте цифру "0" перед числом.


Проверка на принадлежность значения определенному интервалу

Иногда при проверке принадлежности значения переменной определенному интервалу можно увидеть нечто подобное
C++
1
    if ( 0 <= x <= 10 )
Несмотря на кажущуюся логичность, этот код не проверяет на то, что x лежит между 0 и 10.
Если разбить на шаги, то они будут следующими:
Т.к. оператор сравнения <= левоассоциативен (т.е., выполняется слева направо), то первым шагом будет сравнение 0 и x
1. 0 <= x. Результат сравнения - true или false, которые будут преобразованы в 1 или 0 соответственно.
2. сравниваем полученный результат с 10. 10 больше и 1, и 0. Следовательно, условие всегда истинно.
В общем случае, можно сказать, что при сравнении подобным образом, если последнее число (в примере это число 10) больше или равно 1, то условие всегда истинно.
Проверку на принадлежность интервалу правильно записывать с помощью логического оператора И.
C++
1
    if ( 0 <= x && x <= 10 )
Ошибкой также является использование запятой, вместо логического И
C++
1
    if ( 0 <= x , x <= 10 )
В этом случае, значения выражения 0 <= x никак не используется. Результатом будет значение выражения x <= 10.

Иногда вместо логического И используют логическое ИЛИ.
Выражение
C++
1
    if ( 0 <= x || x <= 10 )
не означает, что значение x лежит между 0 и 10. Это может быть вообще любое число. Почему так происходит:
1. Проверяем первое условие. Если x больше или равен нулю, то истина. Значит, любое положительное значение уже истина.
2. Если первое условие не выполнилось, то проверяем второе условие. Любое отрицательное число (а предыдущее условие могло не пройти только отрицательное значение) меньше 10, значит, условие тоже истинное.
Следовательно, условие всегда истинное.
4
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
24.09.2014, 12:11 17
Отсутствие возврата значения из функции

Например, следующая функция
C++
1
2
3
4
5
int f( int x )
{
    if ( x == 10 )
        return 1;
}
является ошибочной: в случае невыполнения условия возврата из функции нет никакого.
Для избежания этого из функции обязательно должен быть возврат, вне зависимости от выполнения или невыполнения условия.
C++
1
2
3
4
5
6
int f( int x )
{
    if ( x == 10 )
        return 1;
    return 0;
}
Компилятор может выдать предупреждающее сообщение:
1>d:\current\cpp\test\test.c(8) : warning C4715: f: значение возвращается не при всех путях выполнения
Для этого надо установить соответствующий уровень предупреждений компилятора.
В Visual Studio это делается через команду меню:
Проект -> Свойства -> Свойства конфигурации -> С/С++ -> Общие -> Уровень предупреждений -> Уровень 4 (/W4).

Реальный пример - функция поиска позиции первого вхождения символа в строку.
C++
1
2
3
4
5
6
7
int indexOf( const char * str, const char c )
{
    for ( int i = 0; str[i]; ++i )  // пробегаемся по строке
        if ( str[i] == c )          // если текущий символ - искомый
            return i;               // то возвращаем индекс этого символа
    return -1;                      // если цикл прошелся и возврата не выполнено (символ не найден), возвращаем -1
}
3
Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
24.09.2014, 12:32  [ТС] 18
Оставление символа '\n' в потоке ввода:
C++
1
2
3
4
cout << "введите n:";
int n; cin >> n;    // вводится число после нажатия Enter
cout << "введите символ:";
char c; cin.get(c); // хотим ввести символ из новой строки, но вместо него вводится '\n'
C++
1
2
3
4
cout << "введите n:";
int n; cin >> n;    // вводится число после нажатия Enter
cout << "введите строку:";
char c[100]; cin.getline(c,100);    // хотим ввести новую строку, но вводится пустая строка
исправление ошибки
C++
1
2
3
4
5
6
cout << "введите n:";
int n;
(cin >> n).get();   // вводим число и пропускаем один символ
cout << "введите символ:";
char c;
cin.get(c);         // вводится символ на новой строке ( !!!  '\n' второй строки еще не прочитали).
Вместо cin.get() можно просто пропустить символы:
C++
1
2
cin.ignore( k, '\n' );                  // k -  пропускаемое к-во символов,  параметр '\n' можно опускать 
cin.ignore( cin.rdbuf()->in_avail() );  // пропустить все оставшиеся символы
Можно также в цикле прочитать оставшиеся символы
C++
1
while ( cin.get() != '\n' );
Третий способ - синхронизация ввода с помощью cin.sync():
C++
1
2
3
4
5
6
7
8
cout<<"введите n:";
int n;
cin >> n;
cin.sync(); // вводим число и сбрасываем остаток строки
cout << "введите символ:";
char c;
cin >> c;
cin.sync(); // вводим символ на новой строке и тоже сбрасываем остаток строки.
В общем, возможности большие. Главное помнить об этой проблеме!
25
Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
24.09.2014, 12:35  [ТС] 19
Выход за пределы массива
C++
1
2
3
    int arr[5] = { 1, 2, 3, 4, 5 };
    for ( int i = 1;  i <= 5; ++i )
        printf( "%d\n", arr[i] ); // выведет 2 3 4 5 и ... всё что угодно
Индексы массивов в C++ начинаются с нуля. Для массива из N элементов допустимые индексы лежат в диапазоне [0..N-1]. Чтение или запись информации вне выделенной памяти приводит к неопределенному поведению программы.

Также часто встречается выход за пределы массива в строках в стиле C из-за отсутствии терминального нуля:
C++
1
2
3
4
char str[2] = { 'a', 'b' };
cout << str;                                // результат вывода непредсказуем, т.к. неизвестно сколько символов надо выводить
for ( int i = 0; i < strlen( str ); i++ )   // не известно, что вернет strlen()
     str[i] = 'x';                          // соответственно неизвестно к каким элементам массива обратимся.
Исправленный вариант
C++
1
2
3
4
char str[3] = { 'a', 'b', 0 };              // или char str[3] = "ab";
printf( "%s", str );                        // вывод ab
for ( int i = 0; i < strlen( str ); i++ )   // strlen() возвратит 2
    str[i] = 'x';                           // в массиве окажется строка "xx"
4
Модератор
Эксперт С++
 Аватар для zss
13730 / 10926 / 6482
Регистрация: 18.12.2011
Сообщений: 29,161
24.09.2014, 12:38  [ТС] 20
Лучший ответ Сообщение было отмечено Volga_ как решение

Решение

switch без break
C++
1
2
3
4
5
6
switch( i )
{
    case 0: cout << "zero\n";
    case 1: cout << "one\n";
    default: cout << "other\n"; 
}
При i равном 0 будет выведено zero one other. При i равном 1 будет выведено one other. Т.е. без break происходит "проваливание" к следующей метке. В большинстве случаев, приведенный выше код является ошибочным, но иногда такое поведение может быть задуманным. И в этих случаях следует для очевидности указать в комментарии, что отсутствие break это не ошибка, а явная задумка автора.
2
24.09.2014, 12:38
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.09.2014, 12:38
Помогаю со студенческими работами здесь

Распространенные ошибки
Оглавление Ошибки этапа компиляции (В процессе компиляции выдается либо сообщение об ошибке, либо предупреждение) - Попытка...

безопасность и распространенные ошибки
Тут наткнулся на очень интересные тексты: http://werad.narod.ru/articles/programm6.html http://werad.narod.ru/articles/programm9.html...

безопасность и распространенные ошибки
Тут наткнулся на очень интересные тексты: http://werad.narod.ru/articles/programm6.html http://werad.narod.ru/articles/programm9.html...

Распространенные ошибки SEO и ASP.NET 2.0
Здравствуйте, существуют несколько СЕО проблем при использовании ASP.NET, ниже я опишу эти проблемы, нужно найти простое и эффективное...

Самые распространенные строки
type Mytype = record name:string; surname:string; end; var Students:Mytype; MyFile:file of Mytype; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Опции темы

Новые блоги и статьи
Что нового в Laravel 12
Wired 18.02.2025
С момента своего появления в 2011 году Laravel постоянно развивается, внедряя инновационные решения и совершенствуя существующие возможности. В начале 2025 года ожидается выход Laravel 12 - новой. . .
Роутер в Laravel: как работать с маршрутами
Wired 18.02.2025
Маршрутизация - один из основополагающих элементов любого веб-приложения на Laravel, определяющий как приложение отвечает на HTTP-запросы к различным URL-адресам. По сути, роутинг - это механизм. . .
Интеграция шаблона Bootstrap в Laravel PHP
Wired 18.02.2025
Разработка веб-приложений в современном мире требует не только надежного бэкенда, но и привлекательного, отзывчивого интерфейса. Laravel, как один из самых популярных PHP-фреймворков, отлично. . .
Использование контроллеров и middleware в Laravel PHP
Wired 18.02.2025
Современная веб-разработка требует четкой организации кода и эффективного управления потоком HTTP-запросов. Laravel, как один из ведущих PHP-фреймворков, предоставляет два мощных инструмента для. . .
Фильтрация массива по неточному соответствию элементам другого массива в JavaScript
Wired 18.02.2025
При работе с массивами данных в JavaScript иногда возникает задача поиска и фильтрации элементов по неточному соответствию. В отличие от точного сравнения, когда мы ищем полное совпадение значений,. . .
Создаем SPA Router на чистом JavaScript
bytestream 17.02.2025
В современной веб-разработке одностраничные приложения (SPA) стали стандартом для создания динамичных и отзывчивых пользовательских интерфейсов. Ключевым компонентом любого SPA является роутер -. . .
Машинное обучение на TypeScript и TensorFlow
bytestream 17.02.2025
Машинное обучение становится все более востребованным направлением в современной разработке программного обеспечения. Интеграция искусственного интеллекта в веб-приложения открывает новые возможности. . .
Как работать с данными EXIF и JPEG в JavaScript
bytestream 17.02.2025
В современном мире цифровой фотографии метаданные изображений играют важнейшую роль в организации и управлении медиаконтентом. Формат EXIF (Exchangeable Image File Format) - это стандарт,. . .
Как создать GUID/UUID в JavaScript
bytestream 17.02.2025
GUID (Globally Unique Identifier) и UUID (Universally Unique Identifier) - это специальные форматы 128-битных идентификаторов, которые практически гарантируют уникальность значения во времени и. . .
Что такое мышление в упрощенном смысле (моё субъективное видение, для создания модели).
Hrethgir 17.02.2025
Разумеется упрощать смысл есть. Дело в том, что я пришёл к тому выводу, что даже если я создам свой процессор (конвейер), то первое для чего смогу его использовать в качестве демонстративного. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru