Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.69/714: Рейтинг темы: голосов - 714, средняя оценка - 4.69
Модератор
Эксперт С++
9801 / 8362 / 5091
Регистрация: 18.12.2011
Сообщений: 22,362
1

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

21.09.2014, 17:33. Просмотров 128774. Ответов 67
Метки нет (Все метки)

Оглавление

Ошибки этапа компиляции
Программа не компилируется или компилируется с предупреждениями.
  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"
Ошибки этапа выполнения
Программа прекращает работу с сообщением об ошибке
  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. Перегрузка оператора >>
Ошибки при использовании STL контейнеров
  1. Невалидные ссылки/указатели, при перемещении объектов
  2. Ошибки связанные с итераторами (кэширование размера контейнера)
  3. Ошибки связанные с итераторами (удаление элементов по итератору в циклах)
  4. Ошибки связанные с итераторами (префикс-постфиксные инкременты при удалении элементов в цикле)
34
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.09.2014, 17:33
Ответы с готовыми решениями:

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

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

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

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

67
Комп_Оратор)
Эксперт по математике/физике
8420 / 4182 / 569
Регистрация: 04.12.2011
Сообщений: 12,438
Записей в блоге: 14
19.03.2016, 10:48 61
Цитата Сообщение от Croessmah Посмотреть сообщение
если в потоке не будет '\n', то безнадежно испортим поток.
Я же говорю, для примера написал. Если нет '\n' то должно очистить до конца ведь?
Цитата Сообщение от Croessmah Посмотреть сообщение
так что пришлось делать get два раза, чтобы оно работало.
Это древний и вполне звонкий бубен.
0
1030 / 781 / 369
Регистрация: 30.10.2017
Сообщений: 2,233
05.03.2018, 01:38 62
zss, не совсем понимаю в чем проблемность этой конструкции? cin игнорирует же символ конца строки. На двух компиляторах у меня проблем не возникает, может я просто чего то недопонимаю.

C++
1
2
3
4
cout << "введите n:";
int n; cin >> n;    // вводится число после нажатия Enter
cout << "введите символ:";
char c; cin >> c;   // хотим ввести символ из новой строки, но вместо него вводится '\n'
0
Модератор
Эксперт С++
9801 / 8362 / 5091
Регистрация: 18.12.2011
Сообщений: 22,362
05.03.2018, 06:54  [ТС] 63
QuakerRUS, а попробуйте
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
cout << "введите n:";
int n; cin >> n;    // вводится число после нажатия Enter
cout << "введите символ:";
char c; cin.get(c);   // хотим ввести символ из новой строки, но вместо него вводится '\n'
1
1030 / 781 / 369
Регистрация: 30.10.2017
Сообщений: 2,233
05.03.2018, 16:11 64
zss, на счет этих двух вариантов, да, согласен. cin оставляет в потоке символ конца страницы, а cin.get и cin.getline его считывают и получают пустое значение в итоге. Речь была именно о том варианте, где два cin, он указан в распространенных ошибках.

Добавлено через 1 час 4 минуты
zss, в нижних двух примерах проблема так же будет наблюдаться, когда число вводится перед нажатием Enter

C++
1
// вводится число после нажатия Enter
Добавлено через 3 часа 51 минуту
zss, в исправлении к этой ошибке в шестой строчке тоже старый вариант.

C++
1
2
3
4
5
6
cout << "введите n:";
int n;
(cin >> n).get();   // вводим число и пропускаем один символ
cout << "введите символ:";
char c;
cin> > c;           // вводится символ на новой строке ( !!!  '\n' второй строки еще не прочитали).
Добавлено через 6 минут
zss, я имел ввиду, что
C++
1
cin >> c;
неплохо бы заменить на
C++
1
cin.get(c)
1
Комп_Оратор)
Эксперт по математике/физике
8420 / 4182 / 569
Регистрация: 04.12.2011
Сообщений: 12,438
Записей в блоге: 14
05.05.2020, 12:39 65
Прошу прощения, но не нашёл более подходящей рубрики. Надеюсь Сергей Сергеевич найдёт этому место, если сочтёт нужным.
Ошибка очень простая, но стакан крови может выпить легко)
Бывает что хочется создать счетчики циклов вне цикла. Это бывает оправдано если значения требуются после выполнения циклов.
C++
1
2
3
4
5
int ind(0);
for(; ind<some_size; ++ind)
{
 
}
отлично. Теперь двойной цикл:
C++
1
2
3
4
5
6
7
8
9
10
int a[][3]={{1,2,3}, {2,3,4}};
//где-то определены размеры fsize1 и fsize2
size_t ind1(0), ind2(0);
            for( ; ind1<fsize1; ++ind1)
            {
                for( ; ind2<fsize2; ++ind2)///забыта переустановка счётчика в ноль ind2=0 )))
                {
                     cout<<a[ind1][ind2]<<' ';
                }
            }
Довольно тупая ошибка, но именно в этом её неуловимость. Всё работает, но не так как нужно.
0
Модератор
Эксперт по электронике
8263 / 6123 / 820
Регистрация: 14.02.2011
Сообщений: 21,256
05.05.2020, 12:49 66
Цитата Сообщение от IGPIGP Посмотреть сообщение
отлично. Теперь двойной цикл:
могу показать и с одинарным,точнее с двумя
C++
1
2
3
4
5
6
7
8
9
10
int ind(0);
for(; ind<some_size; ++ind)
{
 
}
 
for(; ind<some_size; ++ind)
{
 
}
второй просто не сработает

вывод всегда нужно присваивать в шапке цикла начальное значение

C++
1
2
3
4
5
6
7
8
9
10
int ind(0);
for(ind=0; ind<some_size; ++ind)
{
 
}
 
for(ind=0; ind<some_size; ++ind)
{
 
}
кроме отдельных случаев, их нужно коментировать


C++
1
2
3
4
5
6
7
8
9
10
11
int ind(0);
for(ind=0; ind<some_size; ++ind)
{
 if(.....)
  break;
}
 
for(; ind<some_size; ++ind) // продолжаем с места остановки
{
 
}
2
Комп_Оратор)
Эксперт по математике/физике
8420 / 4182 / 569
Регистрация: 04.12.2011
Сообщений: 12,438
Записей в блоге: 14
05.05.2020, 13:16 67
Цитата Сообщение от ValeryS Посмотреть сообщение
огу показать и с одинарным,точнее с двумя
ValeryS, собственно - да. Это ошибка установки счётчика цикла. Во вложенных труднее искать, но смысл один. Там и итераторы могут быть:
В отладке он сегодня сгинул,
ИтератОр не забегинил!
0
С чаем беда...
Эксперт CЭксперт С++
7875 / 3801 / 1044
Регистрация: 18.10.2014
Сообщений: 8,083
17.08.2020, 04:58 68
Наивный подход к записи сложных объектов в бинарный файл

Работа с объектом, как с плоской непрерывной конечной последовательностью байтов, в таких контекстах, как, например, копирование при помощи memcpy или запись в бинарный файл, возможна только в том случае, если объект по своей сути действительно представляет собой тривиальную "плоскую" последовательность байтов. Например, такие типы как int или

C++
1
2
3
4
5
6
7
8
9
10
11
12
struct A
{
  int x, y;
  double z;
};
 
struct B
{
  A a;
  char name[80];
  int data[3];
};
или B [20] являются примерами таких "плоских" типов. Это, в частности, означает то, что такие объекты можно смело записывать в бинарный файл и читать оттуда "одним махом", при помощи единственного вызова функции ввода-вывода1. Например

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{ // Запись
  int i = 1;
  A a = { 10, 20, 30.5 };
  B b[2] = { { { 1, 2 }, "Alice", { 3, 4, 5 } }, { { 6, 7 }, "Bob", { 8, 9, 10 } } };
 
  std::ofstream f("test", std::ios_base::out | std::ios_base::binary);
  f.write((const char *) &i, sizeof i);
  f.write((const char *) &a, sizeof a);
  f.write((const char *) &b, sizeof b);
}
{ // Чтение
  int i = {};
  A a = {};
  B b[2] = {};
 
  std::ifstream f("test", std::ios_base::in | std::ios_base::binary);
  f.read((char *) &i, sizeof i);
  f.read((char *) &a, sizeof a);
  f.read((char *) &b, sizeof b);
 
  std::cout << i << std::endl;
  std::cout << a.x << " " << a.z << std::endl;
  std::cout << b[0].a.x << " " << b[0].a.y << std::endl;
  std::cout << b[1].name << " " << b[1].data[1] << std::endl;
}
Однако как только структура объекта становится более сложной (напр. многоуровневой), такой способ записи запросто может оказаться неприемлем. Очевидным примером типа с нетривиальной внутренней структурой является объект, содержащий указатели на другие объекты или блоки памяти2. Попытка записать такой объект в файл вышеприведенным способом приведет к тому, что в файл запишется лишь значение содержащегося в объекте указателя. Во-первых, запросто может получиться так, что к моменту чтения этого файла сохраненное значение указателя уже не будет корректным/актуальным (память была освобождена и, возможно, выделена в совсем другом месте) 3. Во-вторых, если указуемые данные по своей сути являются составной частью записываемого объекта, то эти данные тоже нужно явно сохранить в файле отдельной операцией записи. Запись указателя никак эти данные не сохраняет.

Нетривиальная внутренняя структура может возникнуть в объекте и неявным образом. Например, наличие в классе виртуальных методов или виртуальных базовых классов - это уже явное противопоказание против попыток тривиальной записи соответствующих объектов в бинарный файл, даже если в некоторых реализациях такие попытки могут приводить к работоспособным результатам 4.

Также примерами типов с нетривиальной внутренней структурой являются типы, о внутренней структуре которых нам формально ничего не известно (и не должно быть известно). Например, внутренняя структура стандартных классов std::string или std::vector является деталью реализации и нас совершенно не касается. Это означает, что пытаться записывать в файл объекты типа std::string через

C++
1
2
std::string s = "Hello World";
f.write((const char *) &s, sizeof s); // <-- Это бессмысленно и неработоспособно
является совершенно бесполезным и неработоспособным способом записи 5. Понятно, что это относится и к пользовательским типам, содержащим в себе такие нетривиальные типы в качестве подобъектов

C++
1
2
3
4
5
6
7
8
9
struct C
{
  int i;
  std::string name;
  std::vector<int> data;
};
...
C c;
f.write((const char *) &c, sizeof c); // <-- Это бессмысленно и неработоспособно
В этом примере такой наивный способ записи бессмыслен и неработоспособен по причине того, что класс C содержит в себе подобъекты типа std::vector и str::string.

Для того, чтобы правильно записать в файл такой сложный объект необходимо разработать специальный протокол/формат сериализации, т.е. аккуратно последовательно сохранить в файл все отдельные "кусочки" информации, которые в будущем позволят точно восстановить объект из файла в процессе чтения. Как правило это не получится сделать одной операцией записи/чтения. Таких операций понадобится несколько. Например, запись в бинарный файл и последующее чтение из бинарного файла объекта типа std::string может выглядеть следующим образом

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <string>
#include <fstream>
#include <iostream>
 
void write(std::ofstream &f, const std::string &s)
{
  std::string::size_type length = s.length();
  f.write((const char *) &length, sizeof length);
  
  if (length > 0)
    f.write(s.c_str(), length);
}
 
std::string read(std::ifstream &f)
{
  std::string s;    
  
  std::string::size_type length = 0;
  f.read((char *) &length, sizeof length);
  
  if (length > 0)
  {
    s.resize(length);
    f.read(s.data(), length);
  }
  
  return s;
}
 
int main() 
{
  { // Запись
    std::string s = "Hello World";
    std::string t; // Пустая строка
 
    std::ofstream f("test", std::ios_base::out | std::ios_base::binary);
    write(f, s);
    write(f, t);
  }
  { // Чтение
    std::ifstream f("test", std::ios_base::in | std::ios_base::binary);
    std::string s = read(f);
    std::string t = read(f);
 
    std::cout << '\"' << s << '\"' << std::endl;
    std::cout << '\"' << t << '\"' << std::endl;
  }
}
Аналогичным образом, из индивидуальных кусочков можно собирать функции записи чтения для объектов любого уровня сложности.

---

1) При этом, разумеется, нужно помнить, что такой способ записи работоспособен/портабелен только в рамках одной стабильной реализации (компилятора) языка С++ и набора настроек этого компилятора. Смена компилятора (или просто смена настроек компилятора) запросто может привести к изменению расположения элементов таких типов в памяти, размеров этих элементов и других деталей их бинарного представления, что приведет к тому, что ранее записанный бинарный файл станет нечитаемым (или потребует нетривиальных усилий для чтения).

2) Объект может содержать и указатели на самого себя

3) Однако если вы абсолютно стопроцентно уверены, что значение указателя останется актуальным с момента записи и до момента чтения, то указатель можно записывать в бинарный файл. Понятно, что такое возможно только для короткоживущих файлов: временных scratch-файлов или swap-файлов, как их обычно называют.

4) Можно добавить, что типы, не удовлетворяющие стандартному свойству std::is_trivially_copyable не совместимы с тривиальным способом записи. Однако требование std::is_trivially_copyable является лишь необходимым, не не достаточным условием возможности такой записи. Классы с указателями внутри запросто могут удовлетворять std::is_trivially_copyable, но все равно требовать нетривиальной записи.

5) Не все стандартные типы являются такими "черными ящиками". Например, объекты стандартного класса std::array являются агрегатами и их можно смело записывать в файл "одним махом". Разумеется, при условии, что элементы массива std::array тоже допускают такой способ записи.
5
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.08.2020, 04:58

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

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

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

Самые распространённые фамилии
Здравствуйте! Для реализации автоподстановки фамилии нужно как-то выявить, например, 1 (10, 15,...

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

Найти и вывести самые распространенные женские те мужские имена
О каждом студенте факультета доступна следующая информация: фамилия, имя, отчество, пол, возраст,...

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.