Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.93/14: Рейтинг темы: голосов - 14, средняя оценка - 4.93
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
1

Перегрузка оператора ++ , деструктор и конструктор копий

30.07.2010, 14:34. Показов 2542. Ответов 21
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Привет всем!

В продолжение Этой темы появились новые вопросы и непонятки. Буду признателен за советы и разъяснения

Начну с самого начала...

Пишу class - обертку для файла. Цель - упростить операции доступа к содержимому файла.

Приблизительный план: (может, как по другому можно)
класс должен содержать, и выдавать по требованию, такие данные;
текущее положение курсора (номер строки и номер символа в строке)
текущий символ.
Смещешие курсора сделать с помощью операторов ++ и --
На каждый файл отдельный объект.
В конструкторе инициал. поля и загружается часть файла в массив.

Дальше будет видно...

текущие наработки:
file_pos.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
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
#include "io.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <malloc.h> 
#include <fcntl.h>
 
#define BUFF_SIZE 512
 
typedef unsigned int  uint_t;      // 4 - bytes ; 0 to 4,294,967,295 
 
class File_pos
{
    char * file_name;       /* Хранит имя файла */
    char * buffer;          /* Указатель на массив  содержимого файла */
 
    uint_t file_size;       /* Количество символов в файле*/
 
    /* количество элементов в буфере м. быть от 1 до BUFF_SIZE | file_size */
    uint_t readed_elements;  /* если равно file_size то перезагрузка не нужна */
    
    uint_t cur_pos;         /* Текущее полож. курсора, / 1 до file_size */
 
    uint_t line;            /* текущая строка    / от 1 и до 4,294,967,295 */  
    uint_t cursor;          /* позиция в строке  / от 1 и до 4,294,967,295 */
 
    uint_t blocnum;         /* номер прочитанного блока */    
 
    bool need_reload;       /* нужна ли будет "до-загрузка файла" */
 
    bool eof;       /* Ни конец ли файла? */
    //bool bof;       /* Ни начало ли файла */
 
 
    //char * load_file( const char * filename, /* out */ uint_t * count_symb );
    
    char * load_buff ();
  
 
    inline void get_file_size ();
 
    int read_buff ( uint_t buff_size, bool backflag );
 
    
public :
 
    File_pos (const char * filename );
    File_pos (const File_pos &obj ); /* Конструктор копирования */
    ~File_pos ();
 
    File_pos operator++();
    //File_pos operator--();
 
    uint_t  get_Line ()     { return line; }
    uint_t  get_Cursor ()   { return cursor; }
    
    char    get_Symb ()     { return *buffer; } /*Текущий символ */
 
    bool    is_eof ()       { return  eof; }
    
 /* FIXME  Проверить правильно ли определяю начало файла */
    bool    is_begin ()     { return ( cur_pos == 0 ); }
 
 
    //int set_New_file ( const char * filename );
 
  
 
    void Print() 
    { 
        switch ( this->get_Symb() )
        {
        case '\r' :
            printf ("Текущий символ \" \\r\" на позиции Ln (%i) Cur (%i)\n", line, cursor);
            break;
        case '\n' :
            printf ("Текущий символ \" \\n\" на позиции Ln (%i) Cur (%i)\n", line, cursor);
            break;
        case '\t' :
            printf ("Текущий символ \" \\t\" на позиции Ln (%i) Cur (%i)\n", line, cursor);
            break;
        case '\0' :
            printf ("Текущий символ \" \\0\" на позиции Ln (%i) Cur (%i)\n", line, cursor);
            break;
        default :
            printf ( "Текущий символ \" %-2c\" на позиции Ln (%i) Cur (%i)\n",
                    this->get_Symb(), line, cursor ); 
            break;
        }
    }
};

file_pos.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
#include "file_pos.h"
 
/* Конструктор */
File_pos::File_pos (const char * filename )
{
 
    this->file_name = _strdup ( filename );
 
    this->get_file_size();  /* Инициализируем длину файла */
 
    this->blocnum = 0;
 
    cur_pos = 1;
 
    read_buff( BUFF_SIZE, false ); // Загружаем первый блок в память
 
    need_reload = (file_size > readed_elements );
 
    eof = file_size == 0;
    
    line    = 1;
    cursor  = 1;       
}
/*-----------------*/
 
/* Конструктор копирования */
File_pos::File_pos(const File_pos &obj)
{
    size_t sz;
    this->blocnum   = obj.blocnum;
    this->cur_pos   = obj.cur_pos;
    this->cursor    = obj.cursor;
    this->eof       = obj.eof;
    this->file_size = obj.file_size;
    this->line      = obj.line;
    this->need_reload       = obj.need_reload;
    this->readed_elements   = obj.readed_elements;
 
    this->file_name = _strdup ( obj.file_name );
    this->buffer = new char[ sz = obj.readed_elements ];
/*FIXME Добавить оработку исключительных ситуаций */
    
    for (size_t i = 0; i < sz; ++i)
        this->buffer[i] = obj.buffer[i];
 
}
 
 
/*-----Деструктор-----*/
File_pos::~File_pos()
{
/*FIXME Переделать под delete*/
    free ( this->file_name );
    free ( this->buffer );      
    printf ("Destructor... \n" );
}
 
/*--Определяет длину файла--*/
void
File_pos::get_file_size ()
{
    int fh;
    if ( (fh = _open( this->file_name, _O_BINARY | O_RDONLY )) == -1)
    {
        perror("Open File");
        return;
    }
 
    _lseek ( fh, 0L, SEEK_SET );  // Переводим курсор вначало    
 
    /* определяем количество символов в файле */
 
    if ( (this->file_size = _lseek ( fh, 0L, SEEK_END ) ) == 0 )
    {
        puts( "File is empty..." );
        return;
    }
    _close ( fh );
}
 
/*-------------------*/
 
 
/*Читает "кусочек" данный в массив */
int
File_pos::read_buff ( uint_t buff_size, bool backflag )
{
    int fh;
    if ( (fh = _open( this->file_name, _O_BINARY | O_RDONLY )) == -1)
    {
        perror("Open File");
        return -1;
    }
 
    /*FIXME тут как раз и будет разветвление читать вперед или назад */
    /* возможно изменять память нужно с помощью realloc() */
 
    if ( backflag )
    {
        
    }
    else
    {
        size_t bufsz = ( file_size - blocnum * buff_size < buff_size ) ? 
                                    ( file_size - blocnum * buff_size ) : buff_size;  
        
        /* Выделяем память для элементов массива */
/*FIXME Переделать под new*/
        if ( ( this->buffer = (char *) malloc ( bufsz * sizeof ( char ) ) ) == NULL )
        {
            perror ( "Can't allocate memory..." );
            return -2;
        }
        
        if ( ( readed_elements = _read ( fh, buffer, buff_size ) ) == -1)
        {
            perror ( "reading problem..." );
            return NULL;
        }
        ++blocnum;  /*ТОЛЬКО в блоке NEXT */
 
    }
    _close ( fh );
 
    return 0;
}
/*----------------------------*/
 
File_pos
File_pos::operator++ ()
{
    /* если достигли последнего элемента в буфере и есть еще что перезагрузить */
    /*if ( cur_pos == readed_elements && need_reload )
    {
        reload_file();
    }
    else
    */
 
    if ( cur_pos == file_size )    
        this->eof = true;
   
 
    /* Можно ли сместить курсор */
    if ( cur_pos < file_size )
    { 
        if ( this->get_Symb() != '\n')
        {
            ++cursor;
        }
        else
        {
            ++line;
            cursor = 1;            
        }
 
        ++buffer;                
 
        ++cur_pos;           
    }
    
    return *this;
}
 
/*----------------*/

main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include "file_pos.h"
#include "locale.h"
 
int main()
{ 
    setlocale( LC_ALL, "" );
 
    File_pos f1( "test.txt" );
 
    while ( !f1.is_eof() )
    {
        f1.Print();
        ++f1;
    }
 
    system ("PAUSE");
    exit ( EXIT_SUCCESS );
}


Для перемещения по файлу решил перегрузить операторы инкремента и декемента
Сделал смещение вперед (оператор ++) И столкнулся с проблемой:

функция operator++ () возвращает объект и каждый раз при возврате из нее вызывается деструктор, в котором освобождается память (а ее освобождать не нужно).

Решил проблему с помощью Конструктора копий.

И тут, главный, на данном этапе, вопрос

Правильно ли сделал конструктор копирования? в нем каждый раз делается копия массива buffer (даже 2 массива file_name и buffer).
При прогоне по всем элементам файла такое копирование происходит много раз..
По-моему - это не оптимально
Может я не так делаю?
Конструктор копирования
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Конструктор копирования */
File_pos::File_pos(const File_pos &obj)
{
    size_t sz;
    this->blocnum   = obj.blocnum;
    this->cur_pos   = obj.cur_pos;
    this->cursor    = obj.cursor;
    this->eof       = obj.eof;
    this->file_size = obj.file_size;
    this->line      = obj.line;
    this->need_reload       = obj.need_reload;
    this->readed_elements   = obj.readed_elements;
 
    this->file_name = _strdup ( obj.file_name );
    this->buffer = new char[ sz = obj.readed_elements ];
/*FIXME Добавить оработку исключительных ситуаций */
    
    for (size_t i = 0; i < sz; ++i)
        this->buffer[i] = obj.buffer[i];
 
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.07.2010, 14:34
Ответы с готовыми решениями:

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

Конструктор копирования и перегрузка оператора присваивания
Здравствуйте! Возникла следующая проблема: не могу перегрузить оператор присваивания и сделать...

Класс "Матрица": конструктор, деструктор и перегрузка операторов
Матрица – KMatrix Методы: конструкторы, деструктор; ...

Определить конструктор без параметров, конструктор с одним параметром, конструктор с двумя параметрами, деструктор
Создать класс «матрица». Данный класс должен содержать элементы типа int, определяющие число строк,...

21
Maniac
Эксперт С++
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
30.07.2010, 14:46 2
Вот это дурость!
C++
1
this->buffer = new char[ sz = obj.readed_elements ];
...
C++
1
free ( this->buffer );
0
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
30.07.2010, 14:55  [ТС] 3
Цитата Сообщение от ISergey Посмотреть сообщение
Вот это дурость!
Цитата Сообщение от FireNovel Посмотреть сообщение
Буду признателен за советы и разъяснения
Подскажите, что имеенно, дурость!

Не по теме:

Програмиированием занимаюсь в свободное от работы время, потому профи меня не назовешь ;)


Понял, что освобождать нужно через delete
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
30.07.2010, 15:01 4
Цитата Сообщение от FireNovel Посмотреть сообщение
Подскажите, что имеенно, дурость!
Если используешь выделение памяти в стиле C++ (new/new[]), то и высвобождай ее в стиле C++ (delete/delete[]). Нельзя смешивать функции работы с памятью C с операторами С++.
1
Maniac
Эксперт С++
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
30.07.2010, 15:04 5
Чтобы было понятней дополню Nameless One
Тоесть вместо
C++
1
free ( this->buffer )
нужно
C++
1
delete[] this->buffer;
Иначе могут возникнуть проблемы с памятью..

PS.. Вместо этого
C++
1
2
3
4
5
char * file_name;       /* Хранит имя файла */
....
this->file_name = _strdup ( filename );
...
free ( this->file_name );
Я бы использовал std::string..

C++
1
2
3
std::string file_name;       /* Хранит имя файла */
....
this->file_name =  filename;
1
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
30.07.2010, 15:08 6
Цитата Сообщение от FireNovel Посмотреть сообщение
Подскажите, что имеенно, дурость!
конструкции new / delete в С++ хоть и служат примерно тем же целям, что и malloc() / free() языка С, смешивать их - мягко говоря не лучшая идея. Ну или как ISergey выразился...
1
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
30.07.2010, 15:26  [ТС] 7
С new/delete я уяснил.
А по-поводу такого вопроса:
Цитата Сообщение от FireNovel Посмотреть сообщение
Правильно ли я сделал конструктор копирования? в нем каждый раз делается копия массива buffer.
При прогоне по всем элементам файла такое копирование происходит много раз..
По-моему - это не оптимально
Необходимо ли так копировать, или может есть другой способ? И надо ли ?
0
Maniac
Эксперт С++
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
30.07.2010, 15:31 8
Цитата Сообщение от FireNovel Посмотреть сообщение
Необходимо ли так копировать, или может есть другой способ? И надо ли ?
Для каждого нового объекта своя копия.. так что по другому не выйдет..

PS. Одно не пойму - чем не устроил стандартный класс ofstream/ifstream?
Input/Output with files
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
30.07.2010, 15:58 9
FireNovel, тут есть еще интересный момент: в C++ приняты две формы инкремента/декремента - пред- и пост- (прединкремент и постинкремент, и аналогично преддекремент и постдекремент). Поэтому ожидается, что для некоторого класса будут реализованы обе. И сразу же появляются вопросы.....
1. У тебя реализована пред-форма. Что будет делать и как будет работать пост-форма?
2. А каков вообще физический смысл пред- и пост- форм для перемещения "курсора"?
1
Эксперт С++
5043 / 2622 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 1
31.07.2010, 11:59 10
Цитата Сообщение от CheshireCat Посмотреть сообщение
У тебя реализована пред-форма. Что будет делать и как будет работать пост-форма?
очевидно, что делать она должна тоже самое, что и постформа. иначе пользователи класса получат не то что ожидают. а работать она будет видимо через предформу
1
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
31.07.2010, 19:59  [ТС] 11
Цитата Сообщение от CheshireCat
в C++ приняты две формы инкремента/декремента - пред- и пост-
Да, я думал об этом, и решил не делать отличия и пока реализовать только префиксную форму.
Цитата Сообщение от ISergey
Я бы использовал std::string..
Наверное так будет проще. Я так и сделал
Цитата Сообщение от ISergey
PS. Одно не пойму - чем не устроил стандартный класс ofstream/ifstream?
Просто, я последнее время, часто начал обращать внимание на производительность, и якобы, низкоуровневые функции ввода/вывода _open(), _lseek () работают быстрее. Вот я и пихаю их куда надо, и куда не надо, тоже пихаю
Не знаю может тут и выгоднее использовать ofstream/ifstream. Пока оставлю как есть.
0
65 / 71 / 9
Регистрация: 25.06.2009
Сообщений: 244
31.07.2010, 20:35 12
Нельзя смешивать функции работы с памятью C с операторами С++.
не могу понять почему нельзя смешивать new/delete c malloc/free, ведь на месте new/delete все равно при компиляции будут функции из msvcrt malloc и free
0
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
31.07.2010, 21:14 13
Цитата Сообщение от DeadRipper Посмотреть сообщение
не могу понять почему нельзя смешивать new/delete c malloc/free, ведь на месте new/delete все равно при компиляции будут функции из msvcrt malloc и free
Читаем пункт 5.6 FAQ Конструкторы и деструкторы.
1
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
05.08.2010, 13:10  [ТС] 14
Примет!

Собственно, я доделал примерно то, что хотел. И вот, что получилось:
File_pos.7z
file_pos.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "io.h"
#include <fcntl.h>  /* _open() */
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <iostream>
#include <new>
 
#define BUFF_SIZE   5
#define DEBUG_VER
 
typedef unsigned int  uint_t;      // 4 - bytes ; 0 to 4,294,967,295 
typedef std::string   str_t;
 
class File_pos
{
 
private:
    str_t   file_name;       /* Хранит имя файла */
    char *  buffer;          /* Указатель на массив  содержимого файла */
    uint_t  file_size;       /* Количество символов в файле*/
 
    uint_t  glob_pos;         /* Текущее полож. курсора, / 1 до file_size */
    uint_t  line;            /* текущая строка    / от 1 и до 4,294,967,295 */  
    uint_t  cursor;          /* позиция в строке  / от 1 и до 4,294,967,295 */
 
    uint_t  blocnum;         /* номер прочитанного блока */
    bool    eof;            /* Ни конец ли файла? */
   
 
    inline void get_file_size ();
    int read_buff ( char*& p_buf, uint_t bloc_num, uint_t buff_size/*, bool is_back*/ );
    
public :
 
    File_pos (const str_t filename );
    File_pos (const File_pos  &obj ); /* Конструктор копирования */
   ~File_pos ();
 
    File_pos operator++();
    File_pos operator--();
 
    void    set_new_file ( str_t f_name );
 
    uint_t  get_Line()      { return line; }
    uint_t  get_Cursor()    { return cursor; }
    
    char    get_Symb()      { return *buffer; } /*Текущий символ */
    
    bool    is_eof()        { return  eof; } 
    bool    is_begin()      { return ( glob_pos == 0 ); }
   
    void    Print();    
};

file_pos.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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#include "file_pos.h"
 
/* Конструктор */
File_pos::File_pos (const str_t filename )
{
    this->file_name = filename;
 
    this->get_file_size();  /* Инициализируем длину файла */
 
    this->blocnum   = 1;
    this->glob_pos  = 1;
 
    // Загружаем первый блок длиной BUFF_SIZE в память(buffer)
    read_buff ( this->buffer, this->blocnum, BUFF_SIZE );
 
    eof = file_size == 0;
    
    line    = 1;
    cursor  = 1;       
}
/*-----------------*/
 
/* Конструктор копирования */
File_pos::File_pos(const File_pos &obj)
{
    try 
    {        
        this->blocnum       = obj.blocnum;
        this->glob_pos      = obj.glob_pos;
        this->cursor        = obj.cursor;
        this->eof           = obj.eof;
        this->file_name     = obj.file_name ;
        this->file_size     = obj.file_size;
        this->line          = obj.line;        
 
        register size_t sz  = 0;
        this->buffer        = new char[ sz = strlen ( obj.buffer ) ];
    
        for (size_t i = 0; i < sz; ++i)
            this->buffer[i] = obj.buffer[i];
    }
    catch ( std::bad_alloc )
    {
        printf ( "error: in operator 'new' \n");
    }
    catch ( ... )
    {
        printf ( "error in copy constructor\n");
    }
}
 
/*-----Деструктор-----*/
File_pos::~File_pos()
{
    delete [] this->buffer;
 
/*#ifdef DEBUG_VER
    printf ("Destructor... \n" );
#endif*/ 
 
}
 
/*-- Определяет длину файла --*/
void
File_pos::get_file_size ()
{
    int fh;
 
    /* открываем файл для чтени в бинарном режиме */
    if ( (fh = _open( this->file_name.c_str(), _O_BINARY | O_RDONLY )) == -1)
    {
        perror("Open File...");
        return;
    }
 
    _lseek ( fh, 0L, SEEK_SET );  // Переводим курсор вначало файла   
 
    
    /* определяем количество символов в файле */
 
    if ( (this->file_size = _lseek ( fh, 0L, SEEK_END ) ) == 0 )    
        puts( "File is empty..." );        
    
    _close ( fh );
}
 
/*-------------------*/
 
 
// Читает "кусочек" данных в массив 
int
File_pos::read_buff ( char * & p_buf, uint_t bloc_num, uint_t buff_size )
{
 
#ifdef DEBUG_VER
    printf ( " .... read to buffer ....  \n" );
#endif
 
    int fh;
 
    if ( (fh = _open( this->file_name.c_str(), _O_BINARY | O_RDONLY )) == -1)
    {
        perror("Open File");
        return -1;
    }
 
    register size_t bufsz;
 
    /* Определяем необходимое количество выделяемой памяти bufsz */
    _lseek ( fh, (long) ( (bloc_num-1) * buff_size ) , SEEK_SET );
    bufsz = _lseek ( fh, 0L , SEEK_END );
 
    if ( bufsz >= buff_size )
        bufsz = buff_size;
        
    try
    {
        /* Выделяем память для элементов массива */
        p_buf = new char [ bufsz + 1 ] ;
        
    }catch ( std::bad_alloc &ba )
    {
        std::cout << ba.what() << " in func read_buff()  ...\n" ;
        return -2;
    }
 
    // переводим курсор на поз. начала чтения
    _lseek ( fh, (long) ( (bloc_num-1) * buff_size ) , SEEK_SET );
 
    
    register int rd_elem = 0;
    /* Считываем данные в массив p_buf и запоминаем */
    if ( ( rd_elem = _read ( fh, p_buf, bufsz ) ) == -1)
    {
        perror ( "reading problem..." );
        return -3;
    }
 
    *( p_buf + rd_elem ) = '\0';
 
    _close ( fh );
 
    return 0;
}
/*----------------------------*/
 
 
File_pos
File_pos::operator++ ()
{
    if ( glob_pos == file_size + 1 )
    {
        this->eof = true;
        return *this;
    }
   
    /* Определяем номера строки и курсор по текущему символу.*/    
    if ( this->get_Symb() == '\n')  /* тут можно поставить '\r' и тогда glob_pos + 2 */
    {
        ++line;
        cursor = 1;
    }
    else
    {
        ++cursor;
    }
    
 
    /* если достигли последнего элемента в буфере
       и есть еще что перезагрузить */
    if ( this->glob_pos == blocnum*BUFF_SIZE && file_size - glob_pos > 0)    
        read_buff ( this->buffer, ++blocnum, BUFF_SIZE );
 
 
    if ( this->glob_pos != (blocnum-1)*BUFF_SIZE )
        ++this->buffer;
 
    ++glob_pos;
    
    return *this;
}
/*----------------*/
 
 
File_pos
File_pos::operator-- ()
{
    /* Начинаем конструирование нового объекта 
    Поскольку, из текущего элемента никакой полезной инфо. нет
    потому, сразу переводим курсор на преыдущий символ     */
 
 
    /* Если находимся на границе блока то загружаем символы в массив*/
    if ( glob_pos == (blocnum-1)*BUFF_SIZE+1 && glob_pos != 1)
    {        
        read_buff ( this->buffer, --blocnum, BUFF_SIZE );
        buffer += BUFF_SIZE-1;        
    }
    else
    {
        --buffer;
    }
 
    --glob_pos; 
 
    /* Дальше формируем номера сроки и курсора */
 
    /*Если новый символ '\n' значит нужно подсчитать
      количество символов в предыдущей строке 
      Иначе просто уменьшаем позицию курсора*/
    if ( this->get_Symb() == '\n' )
    {
        /* Подсчитываем количество символов в предыдущей строке */
        --line;
        uint_t tmp_glob_pos  = this->glob_pos; // Позиция '\n'
        uint_t tmp_blnum    = this->blocnum;
 
        char * p_buf;
 
        /* Если находимся на границе блока то загружаем символы в массив*/
        if ( tmp_glob_pos == (blocnum-1)*BUFF_SIZE+1 )        
            read_buff ( p_buf, --tmp_blnum, BUFF_SIZE );
        else        
            p_buf = this->buffer-1;
        
 
        --tmp_glob_pos;
 
        /* Ищем позицию предыдущего символа '\n' */
        while ( *(p_buf) != '\n' &&  tmp_glob_pos >= 1 )
        {
            if ( tmp_glob_pos == (tmp_blnum-1)*BUFF_SIZE+1 && tmp_glob_pos != 1 )
            {
                read_buff ( p_buf, --tmp_blnum, BUFF_SIZE );
                p_buf += BUFF_SIZE-1;
                --tmp_glob_pos;
                continue;
            }
 
            --p_buf;
            --tmp_glob_pos;
        }
 
        /* Вычисляем длину предыдущей строки */
        cursor = this->glob_pos - tmp_glob_pos;       
    }
    else
    {
        --cursor;
    }
 
    return *this;
}
/*-------------------------*/
 
// Меняем исходный файл
void
File_pos::set_new_file ( str_t f_name )
{
    this->file_name = f_name;
    this->blocnum   = 1;
    
    this->get_file_size();
 
    read_buff ( this->buffer, this->blocnum, BUFF_SIZE );
    
    this->line      = 1;
    this->cursor    = 1;
    this->glob_pos   = 1;
    this->eof       = file_size == 0;    
}
/*----------------*/
 
/*--- Печатает текущий символ и его позицию ---*/
void
File_pos::Print()
{ 
    //printf ("На позиции %2.i ) -> " );
    switch ( this->get_Symb() )
    {
    case '\r' :
        printf ("Текущий символ \" \\r\" на позиции Ln (%3.i ) Cur (%3.i )", line, cursor);
        break;
    case '\n' :
        printf ("Текущий символ \" \\n\" на позиции Ln (%3.i ) Cur (%3.i )", line, cursor);
        break;
    case '\t' :
        printf ("Текущий символ \" \\t\" на позиции Ln (%3.i ) Cur (%3.i )", line, cursor);
        break;
    case '\0' :
        printf ("Текущий символ \"EOF\" на позиции Ln (%3.i ) Cur (%3.i )", line, cursor);
        break;
    default :
        printf ( "Текущий символ \" %-2c\" на позиции Ln (%3.i ) Cur (%3.i )",
                this->get_Symb(), line, cursor ); 
        break;
    }
    printf ( " | Глоб. поз. (%3.i )\n", glob_pos );
}

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
#include "file_pos.h"
#include "locale.h"
 
int main()
{ 
    setlocale( LC_ALL, "" );
 
    File_pos f1( "test.txt" );
 
    while ( !f1.is_eof() )
    {
        f1.Print();
        ++f1;
    }
    
    while ( !f1.is_begin() )
    {
        //++i;
        f1.Print();
        --f1;
    }
 
    f1.set_new_file( "test2.txt" );
 
    while ( !f1.is_eof() )
    {
        f1.Print();
        ++f1;
    }
    
    while ( !f1.is_begin() )
    {
        //++i;
        f1.Print();
        --f1;
    }
 
    system ("PAUSE");
    exit ( EXIT_SUCCESS );
}


Просьба уделить немного внимания и указать на какую-нибуть лажу
Может стоит что-то добавить?

И вопросик:
как лучше средствами C++ (может в STL есть) скопировать два массива?
я сделал так
Цитата Сообщение от Copy consuctor
C++
1
2
3
this->buffer = new char[ sz = strlen ( obj.buffer ) ];
        for (size_t i = 0; i < sz; ++i)
            this->buffer[i] = obj.buffer[i];
Заранее спасибо!!!
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
05.08.2010, 14:09 15
Цитата Сообщение от FireNovel Посмотреть сообщение
И вопросик:
как лучше средствами C++ (может в STL есть) скопировать два массива?
С помощью std::copy (требует хедер algorithm):
C++
1
std::copy(obj.buffer, obj.buffer + sz, this->buffer);
Добавлено через 55 минут
Кстати, если buffer здесь - стандартная строка Си с нуль-терминатором, то я бы использовал strcpy. Только тогда тебе нужно для this->buffer выделить еще один байт под нуль-терминатор.
1
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
05.08.2010, 14:20  [ТС] 16
Цитата Сообщение от Nameless One Посмотреть сообщение
С помощью std::copy (требует хедер algorithm):
C++
1
std::copy(obj.buffer, obj.buffer + sz, this->buffer);
В моем случае нужно написать
C++
1
2
this->buffer = new char[ sz = strlen ( obj.buffer ) ];    
std::copy(obj.buffer, obj.buffer + sz + 1, this->buffer);
Тогда скопируется и последний нулевой байт.
Вот только вопрос - не быстрее, ли будет это сделать for-ом?
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
05.08.2010, 14:25 17
Цитата Сообщение от FireNovel Посмотреть сообщение
Тогда скопируется и последний нулевой байт.
А ты под него место выделил? Насколько я помню, strlen не считает нуль-терминатор. Тогда, в твоем случае, нужно делать так:
C++
1
this->buffer = new char[ sz = strlen ( obj.buffer ) + 1 ]; //Выделяем память под buffer + нуль-терминатор
Цитата Сообщение от FireNovel Посмотреть сообщение
Вот только вопрос - не быстрее, ли будет это сделать for-ом?
В данном случае лучше использовать strcpy. Разницы в скорости ты точно не заметишь (если она есть), а запись выглядит проще и понятней.
1
Эксперт С++
5043 / 2622 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 1
05.08.2010, 14:28 18
Цитата Сообщение от FireNovel Посмотреть сообщение
Вот только вопрос - не быстрее, ли будет это сделать for-ом?
for-ом точно не быстрее как максимум также.
а вообще все правильно, самые быстрые варианты будут скорее всего strcpy и memcpy, что по сути одно и тоже, так как они копируют не поэлементно, а блоками памяти.
2
150 / 73 / 27
Регистрация: 09.04.2010
Сообщений: 297
05.08.2010, 14:51  [ТС] 19
И еще один вопросик (скорее философский)...
Как определить, что класс готов? Ведь, при разработке его, очень часто, в голову лезут разные идеи. И вроде бы и так сделать можно, и эдак - было бы хорошо организовать...
И потихоньку увязаешь в коде
Посоветуйте пожалуйста как поступить
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.08.2010, 14:53 20
FireNovel, Поставьте одну цель, что должен делать класс, и не расширяйте пока не сделаете класс таким как поставили. Ну а затем уже по личным приоритетам, может что-то доделать, может что-то добавить и т.д.
0
05.08.2010, 14:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.08.2010, 14:53
Помогаю со студенческими работами здесь

Конструктор инициализации, конструктор копирования, деструктор
Я сделал почти задание по перегрузке операторов. Осталось одно, тоесть три: конструктор...

Создать класс "Вектор" и реализовать конструктор по умолчанию, конструктор копирования и деструктор
Всем доброго времени суток! нужна ваша помощь! нужно создать класс вектор и реализовать...

Конструктор копий
привет, как сделать конструктор копий myclass a(b); value myclass{ private: int a,b; public: ...

Конструктор копий
Добрый день! Пытаюсь разобраться с конструктором копий, а именно: когда его использовать и как...

Конструктор копий
Можно ли вызвать в конструкторе копий, конструктор, если объекту нечего передавать? Класс -...

Конструктор копий
Добрый день, изучая работу со списками и классы, дошел до такой проблемы: Нужно было создать...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru