Форум программистов, компьютерный форум CyberForum.ru

Не могу найти ошибку - C++

Восстановить пароль Регистрация
 
Gesparo
1 / 1 / 0
Регистрация: 26.09.2012
Сообщений: 23
09.11.2013, 13:09     Не могу найти ошибку #1
Доброго времени суток. На днях написал программу, в логике программы вроде все правильно и подсчеты идут тоже корректные. Но до завершения программа не доходит и вылетает. Возможно я что-то неправильно сделал при работе с памятью.
Суть задачи через каждые 10+-5 с в накопитель поступают заявки(детали), далее они идут в 1 канал, где обрабатываются 10+-7 с, после завершения обработки они поступают во второй накопитель, далее во 2 канал, где обрабатываются 10+-6 с. После окончания обработки во 2 канале мы должны рассмотреть деталь, если она была в системе больше 25 секунд - она завершена, если от 20 до 25 - отправляем её во 2 накопитель или канал, если меньше 20 - в первый накопитель или канал. Программа должна завершится после завершения 400 заявок.

main.cpp:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
using std::ios;
 
#include <cstddef>
using std::nullptr_t;
 
#include <deque>
using std::deque;
 
#include <cstdlib>
using std::rand;
using std::exit;
 
#include <fstream>
using std::ofstream;
 
#include <iomanip>
using std::setw;
 
#include "Detail.h"
 
#include "Channel.h"
 
int main()
{
    // накопитель 1 и 2
    deque< Detail* > accumulator1 ( 0, nullptr );
    deque< Detail* > accumulator2 ( 0, nullptr );
 
    // канал 1 и 2
    Channel ch1( 10, 7, 0); // 10+-7
    Channel ch2( 10, 6, 0); // 10+-6
 
    // РЕШАТЕЛЬ - этот указатель нужен для решения
    // что нужно делать с деталями, которые
    // выходят из 2 канала после его завершения
    Detail* solver = nullptr;
 
    int numberOfDetil = 1; // нумирация деталей
 
    // время до поступления новой заявки
    int timeToIncomeNewDetail = 0;
 
    // общее кол-во выполненых деталей
    int totalReadyDetails = 0;
 
    // счет времени
    int totalTime = 1;
 
    // создание файла для вывода результата
    ofstream outResultFile( "result.txt", ios::out );
 
    // проверка возможно ли открыть файл
    if( !outResultFile )
    {
        cerr << "File could not be open" << endl;
        exit( 1 );
    }
 
    // название столбцов в файле
 
    // Time - время работы программы ( итерация )
    // NewDetail - отсчет времени до появления новой детали
    // Accumulator1 - кол-во деталей в 1 накопителе
    // Channel1 - статус 1 канала ( 1 - свободен, 2 - работает, 3 - завершил работу )
    // Ch1WorkTime - время работы  1 канала
    // Accumulator2 - кол-во деталей в 2 накопителе
    // Channel2 - статус 2 канала ( 1 - свободен, 2 - работает, 3 - завершил работу )
    // Ch2WorkTime - время работы  2 канала
    // ReadyDetails - кол-во завершенных деталей
 
    outResultFile << setw( 4 ) << "Time" << " | " << setw( 9 ) << "NewDetail" << " | "
        << setw( 12 ) << "Accumulator1" << " | " << setw( 8 ) << "Channel1" << " | "
        << setw( 11 ) << "Ch1WorkTime" << " | " << setw( 12 ) << "Accumulator2" << " | "
        << setw( 8 ) << "Channel2" << " | " << setw( 11 ) << "Ch2WorkTime" << " | "
        << setw( 12 ) << "ReadyDetails" << " | " << endl;
 
    // на первой секунде создаем первую деталь
    accumulator1.push_back ( new Detail( numberOfDetil ) );
 
    // увеличиваем счетчик деталей на 1
    numberOfDetil++;
 
    // генерируем время поступления новой детали
    timeToIncomeNewDetail = 5 + rand() % 11; // 10+-5
 
    // выполняем до тех пор пока не будет выполнено 400 деталей
    while( totalReadyDetails != 400 )
    {
 
//-------------------------------------------------------------------------------------------//
        // работа 2 канала
 
        // если канал 2 завершил свою работу
        if( 3 == ch2.getCurrentStatus() )
        {
            // указатель на деталь передаем РЕШАТЕЛЮ
            solver = ch2.removeDetail();
 
            // если время детали больше 25 секунд удаляем деталь
            if( solver->getTotalWorkTime() > 25 && false == solver->getRepeatStatus() )
            {
                delete solver;
                totalReadyDetails++;
            }
 
            if( true == solver->getRepeatStatus() )
            {
                delete solver;
                totalReadyDetails++;
            }
 
            // если меньше 25 пяти секунд
            if( false == solver->getRepeatStatus() && solver->getTotalWorkTime() <= 25 )
            {
                // ставим статус детали - повторная обработка
                solver->setRepeatStatus( true );
 
                // если её время больше или равна 20 секундам
                // отправляем её во 2 канал( если он свободен )
                // или во 2 накопитель
                if( solver->getTotalWorkTime() >= 20 )
                {
                    if( 1 == ch2.getCurrentStatus() )
                    {
                        ch2.addDetail( solver );
                    }
                    else
                    {
                        accumulator2.push_back( solver );
                        //cout << "acc2_ch2: " << solver->getNumberOfDetaill() << "  ";
                    }
                }
 
                // если её время меньше 20 секунд
                // отправляем её в 1 канал( если он свободен )
                // или в 1 накопитель
                if( solver->getTotalWorkTime() < 20  )
                {
                    if( 1 == ch1.getCurrentStatus() )
                    {
                        ch1.addDetail( solver );
                    }
                    else
                    {
                        accumulator1.push_back( solver );
                        //cout << "acc1_ch2: " << solver->getNumberOfDetaill() << "  ";
                    }
                }
            }
 
            // РЕШАТЕЛЬ "теряет" всю информацию о детали деталь
            solver = nullptr;
        }
 
        // если канал 2 свободен
        if( 1 == ch2.getCurrentStatus() )
        {
            if( !accumulator2.empty() )
            {
                ch2.addDetail( accumulator2.front() );
                accumulator2.pop_front();
            }
        }
//-------------------------------------------------------------------------------------------//
        // Работа 1 канала
 
        // если канал 1 завершил свою работу
        if( 3 == ch1.getCurrentStatus() )
        {
            // если канал 2 свободен - закидываем деталь во 2 канал
            if( 1 == ch2.getCurrentStatus() )
            {
                ch2.addDetail( ch1.removeDetail() );
            }
            // иначе закидываем её во 2 накопитель
            else
            {
                accumulator2.push_back( ch1.removeDetail() );
                //cout << "acc2_ch1: " << accumulator2[ accumulator2.size() - 1 ]->getNumberOfDetaill() << "  ";
            }
        }
        // если канал 1 свободен
        if( 1 == ch1.getCurrentStatus() )
        {
            if( !accumulator1.empty() )
            {
                ch1.addDetail( accumulator1.front() );
                accumulator1.pop_front();
            }
        }
//-------------------------------------------------------------------------------------------//
        // поступления новой детали
 
        // настало время поступления новой детали
        if( 0 == timeToIncomeNewDetail && numberOfDetil != 400)
        {
            // если канал свободен - закидываем деталь в канал
            if( 1 == ch1.getCurrentStatus() )
            {
                ch1.addDetail( new Detail( numberOfDetil ) );
            }
            // иначе закидываем деталь в накопитель
            else
            {
                accumulator1.push_back( new Detail( numberOfDetil ) );
                //cout << "acc1_ch1: " << accumulator1[ accumulator1.size() - 1 ]->getNumberOfDetaill() << "  ";
            }
 
            // генерирем время поступления новой детали
            numberOfDetil++;
            timeToIncomeNewDetail = 5 + rand() % 11; // 10+-5
        }
 
//-------------------------------------------------------------------------------------------//
        // Вывод
 
        outResultFile << setw( 4 ) << totalTime << " | " << setw( 9 ) << timeToIncomeNewDetail << " | "
        << setw( 12 ) << accumulator1.size() << " | " << setw( 8 ) << ch1.getCurrentStatus() << " | "
        << setw( 11 ) << ch1.getWorkTime() << " | " << setw( 12 ) << accumulator2.size() << " | "
        << setw( 8 ) << ch2.getCurrentStatus() << " | " << setw( 11 ) << ch2.getWorkTime() << " | "
        << setw( 12 ) << totalReadyDetails << " | " << endl;
 
//-------------------------------------------------------------------------------------------//
        // Отсчет времени
 
        if( timeToIncomeNewDetail > 0 )
        {
            timeToIncomeNewDetail--;
        }
 
        ch1.timeChanged();
        ch2.timeChanged();
 
        cout << endl;
 
        if( !accumulator1.empty() )
        {
            for( int i = 0; i < accumulator1.size(); i++ )
            {
                accumulator1[ i ]->incrementTotalWorkTime();
                //cout << accumulator2[ i ]->getNumberOfDetaill() << "  ";
            }
        }
 
        cout << endl;
 
        if( !accumulator2.empty() )
        {
            for( int i = 0; i < accumulator2.size(); i++ )
            {
                accumulator2[ i ]->incrementTotalWorkTime();
            }
        }
 
        totalTime++;
    }
 
    cout << "See result in file result.txt." << endl;
 
    return 0;
}
detail.h
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
#ifndef DETAIL_H
#define DETAIL_H
 
 
class Detail
{
    public:
        explicit Detail( int = 0 );
 
        void setNumberOfDetail( int );
        void setRepeatStatus( bool );
 
        int getNumberOfDetaill();
        int getTotalWorkTime();
        bool getRepeatStatus();
 
        void incrementTotalWorkTime();
 
    private:
        int totalWorkTime;
        int numberOfDetail;
        bool repeatStatus;
};
 
#endif // DETAIL_H
detail.cpp
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
#include "Detail.h"
 
#include <iostream>
using std::cout;
using std::endl;
 
Detail::Detail( int value )
{
    totalWorkTime = 0;
 
    setRepeatStatus( false );
    setNumberOfDetail( value );
}
 
void Detail::setNumberOfDetail( int setValue )
{
    numberOfDetail = ( setValue > 0 ) ? setValue : 0;
}
 
void Detail::setRepeatStatus( bool flag )
{
    repeatStatus = flag;
}
 
int Detail::getNumberOfDetaill()
{
    return numberOfDetail;
}
 
int Detail::getTotalWorkTime()
{
    return totalWorkTime;
}
 
bool Detail::getRepeatStatus()
{
    return repeatStatus;
}
 
void Detail::incrementTotalWorkTime()
{
    totalWorkTime++;
}
channel.h
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
#ifndef CHANNEL_H
#define CHANNEL_H
 
class Detail;
 
class Channel
{
    public:
        Channel( int = 1 , int = 0, int = 0 );
        void timeChanged();
 
 
 
        void addDetail( Detail *);
        void setWorkTime( int );
 
        int getWorkTime();
        int getCurrentStatus();
        Detail* removeDetail();
 
    private:
 
        void setCurrentStatus( int );
 
        Detail *currenDetailPtr;
 
        // 1 - свободен
        // 2 - работает
        // 3 - завершен
        int currentStatus;
 
        int workTime;
        int initialValue;
        int rangeValue;
        int timerParametr;
};
 
#endif // CHANNEL_H
channel.cpp
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "Channel.h"
#include "Detail.h"
 
#include <cstddef>
using std::nullptr_t;
 
#include <cstdlib>
using std::rand;
 
#include <iostream>
using std::cout;
using std::endl;
 
Channel::Channel( int value, int range, int parametr )
{
    initialValue = ( value > 0 ) ? value : 1;
 
    rangeValue = ( range >= 0 ) ? range : 0;
 
    timerParametr = ( parametr >= 0 ) ? parametr : 0;
 
    currenDetailPtr = nullptr;
    setCurrentStatus( 1 );
    setWorkTime( 0 );
}
 
void Channel::timeChanged()
{
    int temp = 0;
 
    temp = getWorkTime();
 
    // отсчет времени работы канала
    if( 2 == getCurrentStatus() && getWorkTime() > 0 )
    {
        // оставшееся время -1
        setWorkTime( --temp );
 
        // суммарное время сущестования детали увеличено на 1
        currenDetailPtr->incrementTotalWorkTime();
    }
 
    // работа канала завершена
    if( 0 == getWorkTime() && 2 == getCurrentStatus() )
    {
        setCurrentStatus( 3 ); // завершен
    }
 
}
 
Detail* Channel::removeDetail()
{
    setWorkTime( 0 );
 
    setCurrentStatus( 1 );
 
    return currenDetailPtr;
}
 
void Channel::addDetail( Detail *newDetail )
{
    currenDetailPtr = newDetail;
 
    if( rangeValue >= 0 )
    {
        if( 0 == timerParametr )
        {
           setWorkTime( ( initialValue - rangeValue ) + rand() % ( 2 * rangeValue + 1 ) );
        }
        if ( 1 == timerParametr )
        {
            setWorkTime(initialValue + rangeValue);
        }
        if ( 2 == timerParametr )
        {
            setWorkTime(initialValue - rangeValue);
        }
    }
 
    setCurrentStatus( 2 );
}
 
void Channel::setWorkTime( int number )
{
    workTime = ( number >= 0 ) ? number : 0;
}
 
void Channel::setCurrentStatus( int number )
{
    currentStatus = ( number >= 1 && number <=3 ) ? number : 0;
}
 
int Channel::getWorkTime()
{
    return workTime;
}
 
int Channel::getCurrentStatus()
{
    return currentStatus;
}
Буду премного благодарен, если кто-то разыщет мою ошибку и тем, кто просто подскажет что можно улучшить в этой программе, для уменьшения вероятности возникновения ошибки.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.11.2013, 13:09     Не могу найти ошибку
Посмотрите здесь:

C++ Не могу найти ошибку
C++ Не могу найти ошибку
C++ Не могу найти ошибку!
C++ Не могу найти ошибку
C++ не могу найти ошибку
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
09.11.2013, 15:06     Не могу найти ошибку #2
Итак, насчет
using std::cout;
using std::endl;
using std::cerr;
using std::ios;
Я предвкушая, как сейчас сюда напишут прямо противоположное, но все же:
Зачем писать столько лишнего кода, если можно написать using namespace std; ? Да, это несет некоторые риски, и не безопасно (теоретически), в отличии от написанного тобой, но блин, ты же не промышленный код какой пишешь, все таки, и нужно понимать, когда стоит писать лишнее, а когда нет. тут явно не стоит.

Насчет ошибок. Нужно так в некотором месте:
C++
1
2
3
4
5
6
7
8
9
if( solver->getTotalWorkTime() > 25 && false == solver->getRepeatStatus() ) {
                delete solver;
                totalReadyDetails++;
            }
            else if( true == solver->getRepeatStatus() ) {
                delete solver;
                totalReadyDetails++;
            }
            else if( false == solver->getRepeatStatus() && solver->getTotalWorkTime() <= 25 ) {
Тут у тебя была ошибка, ведь в предыдущих if'ах solver могли удалить, поэтому нужно использовать else, а не просто if...if...if (ну ты понял)

А еще у тебя цикл зацикливается на 399, проверил бы, походу упустил чего-то (у тебя прибавление счетчика происходит только в первых двух начальных if'ах, а дальше нет, но программа как раз по тем другим веткам и идет вроде).
А тут наверняка опечатка(эт я так, не страшно=))
C++
1
numberOfDetil
Gesparo
1 / 1 / 0
Регистрация: 26.09.2012
Сообщений: 23
09.11.2013, 15:32  [ТС]     Не могу найти ошибку #3
Насчет использования using std:: . Не буду вдаваться в подробности, но поверь, мне так надо)
Насчет if else спасибо, действительно неправильная логика работы была( но проблему от не решила )
Насчет цикла - это очень интересно, так как я не меняя логики работы смог однажды сделать 400 деталей, после 2 запуска, я смог сделать 106 деталей, теперь запуская программу я могу сделать 4 детали. При этом код программы не менялся. Что-то тут явно не так, только вот что именно пока не нашел
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
09.11.2013, 17:00     Не могу найти ошибку #4
Цитата Сообщение от Gesparo Посмотреть сообщение
Насчет цикла - это очень интересно, так как я не меняя логики работы смог однажды сделать 400 деталей, после 2 запуска, я смог сделать 106 деталей, теперь запуская программу я могу сделать 4 детали
А не влияет ли на это эта строчка:
C++
1
timeToIncomeNewDetail = 5 + rand() % 11;


Я, может, не разобрался(не особо и старался, если честно), но попробуй timeToIncomeNewDetail сделать константой, и проверить.
Иначе по памяти где-то гуляешь, и тогда я тебе не завидую. Хотя тут в принципе не так сложно, просто выводи в цикле в некоторых местах промежуточную информацию, и сравнивай ее для нескольких запусков. Так сможешь найти место, где начинает расходиться. Это если ты с дебагером не очень дружишь, как и я...

Добавлено через 36 секунд
Цитата Сообщение от Gesparo Посмотреть сообщение
Насчет цикла - это очень интересно, так как я не меняя логики работы смог однажды сделать 400 деталей, после 2 запуска, я смог сделать 106 деталей, теперь запуская программу я могу сделать 4 детали
А не влияет ли на это эта строчка:
C++
1
timeToIncomeNewDetail = 5 + rand() % 11;


Я, может, не разобрался(не особо и старался, если честно), но попробуй timeToIncomeNewDetail сделать константой, и проверить.
Иначе по памяти где-то гуляешь, и тогда я тебе не завидую. Хотя тут в принципе не так сложно, просто выводи в цикле в некоторых местах промежуточную информацию, и сравнивай ее для нескольких запусков. Так сможешь найти место, где начинает расходиться. Это если ты с дебагером не очень дружишь, как и я...
Gesparo
1 / 1 / 0
Регистрация: 26.09.2012
Сообщений: 23
09.11.2013, 17:55  [ТС]     Не могу найти ошибку #5
Цитата Сообщение от monolit Посмотреть сообщение
А не влияет ли на это эта строчка:
C++
1
timeToIncomeNewDetail = 5 + rand() % 11;
Тут точно все в порядке. Скорей всего я действительно где-то по памяти гуляю.
И тут у меня возникает вопрос. Что лучше работа с указателем или с ссылкой?
Я имею ввиду channel.h
C++
1
Detail *currenDetailPtr;
или лучше все переделать для
C++
1
Detail &currenDetailPtr;
monolit
179 / 179 / 21
Регистрация: 24.03.2011
Сообщений: 641
Завершенные тесты: 1
09.11.2013, 19:42     Не могу найти ошибку #6
Да как удобней, так и работай.)
Yandex
Объявления
09.11.2013, 19:42     Не могу найти ошибку
Ответ Создать тему
Опции темы

Текущее время: 16:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru