Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/2: Рейтинг темы: голосов - 2, средняя оценка - 5.00
Модератор
Эксперт С++
 Аватар для zss
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233

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

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

Студворк — интернет-сервис помощи студентам
Скачать 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)
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
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233
21.09.2014, 17:42  [ТС]
Неожиданное закрытие окна

Когда консольное приложение запускается непосредственно из среды программирования,
то после выполнения последнего оператора программы ( 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
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233
21.09.2014, 17:56  [ТС]
Двойная перестановка строк или элементов массива

Рассмотрим на примере инвертирования строки
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
38157 / 21093 / 4305
Регистрация: 12.02.2012
Сообщений: 34,675
Записей в блоге: 14
21.09.2014, 18:12
Попытка модифицировать константу через указатель

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
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,851
21.09.2014, 18:33
Неправильное понятие приведения

Для приведения типов данных в 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
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233
22.09.2014, 08:44  [ТС]
Ошибки в логических выражениях

Использование присваивания (=) вместо сравнения (==).
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
Использование символа цифры вместо числа

Например, такой код
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 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.09.2014, 11:19
Выделение памяти без дальнейшего освобождения или неверное освобождение

а) При выделении памяти через оператор 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 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.09.2014, 20:29
Возврат ссылки/указателя на локальную переменную
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 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.09.2014, 22:41
Использование неинициализированной переменной

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

Компилятор о такой ошибке может выдать предупреждающее сообщение такого типа
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
Лишняя точка с запятой
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
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
23.09.2014, 08:04
Неверный тип возвращаемого значения функции 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 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
23.09.2014, 09:18
Отсутствие точки с запятой после определения классового типа
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
Сравнение вещественных чисел при вычислениях

Поскольку арифметические вычисления для чисел с плавающей запятой выполняются с некоторой погрешностью, то их сравнение на равенство будет некорректным, например:
C++
1
 if ( a - b == 0 )
Соответственно и сравнивать их надо с некоторой точностью (которая зависит от поставленной задачи), например
C++
1
 if ( fabs( a - b ) < 1e-3 )
8
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
24.09.2014, 00:01
Сравнение символьных массивов
При сравнение 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
Использование чисел, записанных в других системах счисления

Может показаться, что значения следующих двух переменных одинаковые:
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
Отсутствие возврата значения из функции

Например, следующая функция
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
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233
24.09.2014, 12:32  [ТС]
Оставление символа '\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
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233
24.09.2014, 12:35  [ТС]
Выход за пределы массива
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
13765 / 10960 / 6489
Регистрация: 18.12.2011
Сообщений: 29,233
24.09.2014, 12:38  [ТС]
Лучший ответ Сообщение было отмечено 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
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
Ответ Создать тему
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru