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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 09.04.2010
Сообщений: 297
30.07.2010, 14:34     Перегрузка оператора ++ , деструктор и конструктор копий #1
Привет всем!

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

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

Пишу 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];
 
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.07.2010, 14:34     Перегрузка оператора ++ , деструктор и конструктор копий
Посмотрите здесь:

C++ Конструктор копий по умолчанию.
C++ [C++] классы конструктор копий
Конструктор копий. Оператор присваивания C++
C++ Что такое конструктор копий?
C++ Конструктор копий
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
30.07.2010, 14:46     Перегрузка оператора ++ , деструктор и конструктор копий #2
Вот это дурость!
C++
1
this->buffer = new char[ sz = obj.readed_elements ];
...
C++
1
free ( this->buffer );
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 09.04.2010
Сообщений: 297
30.07.2010, 14:55  [ТС]     Перегрузка оператора ++ , деструктор и конструктор копий #3
Цитата Сообщение от ISergey Посмотреть сообщение
Вот это дурость!
Цитата Сообщение от FireNovel Посмотреть сообщение
Буду признателен за советы и разъяснения
Подскажите, что имеенно, дурость!

Не по теме:

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


Понял, что освобождать нужно через delete
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
30.07.2010, 15:01     Перегрузка оператора ++ , деструктор и конструктор копий #4
Цитата Сообщение от FireNovel Посмотреть сообщение
Подскажите, что имеенно, дурость!
Если используешь выделение памяти в стиле C++ (new/new[]), то и высвобождай ее в стиле C++ (delete/delete[]). Нельзя смешивать функции работы с памятью C с операторами С++.
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 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;
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9371 / 5421 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
30.07.2010, 15:08     Перегрузка оператора ++ , деструктор и конструктор копий #6
Цитата Сообщение от FireNovel Посмотреть сообщение
Подскажите, что имеенно, дурость!
конструкции new / delete в С++ хоть и служат примерно тем же целям, что и malloc() / free() языка С, смешивать их - мягко говоря не лучшая идея. Ну или как ISergey выразился...
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 09.04.2010
Сообщений: 297
30.07.2010, 15:26  [ТС]     Перегрузка оператора ++ , деструктор и конструктор копий #7
С new/delete я уяснил.
А по-поводу такого вопроса:
Цитата Сообщение от FireNovel Посмотреть сообщение
Правильно ли я сделал конструктор копирования? в нем каждый раз делается копия массива buffer.
При прогоне по всем элементам файла такое копирование происходит много раз..
По-моему - это не оптимально
Необходимо ли так копировать, или может есть другой способ? И надо ли ?
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
30.07.2010, 15:31     Перегрузка оператора ++ , деструктор и конструктор копий #8
Цитата Сообщение от FireNovel Посмотреть сообщение
Необходимо ли так копировать, или может есть другой способ? И надо ли ?
Для каждого нового объекта своя копия.. так что по другому не выйдет..

PS. Одно не пойму - чем не устроил стандартный класс ofstream/ifstream?
Input/Output with files
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
30.07.2010, 15:58     Перегрузка оператора ++ , деструктор и конструктор копий #9
FireNovel, тут есть еще интересный момент: в C++ приняты две формы инкремента/декремента - пред- и пост- (прединкремент и постинкремент, и аналогично преддекремент и постдекремент). Поэтому ожидается, что для некоторого класса будут реализованы обе. И сразу же появляются вопросы.....
1. У тебя реализована пред-форма. Что будет делать и как будет работать пост-форма?
2. А каков вообще физический смысл пред- и пост- форм для перемещения "курсора"?
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
31.07.2010, 11:59     Перегрузка оператора ++ , деструктор и конструктор копий #10
Цитата Сообщение от CheshireCat Посмотреть сообщение
У тебя реализована пред-форма. Что будет делать и как будет работать пост-форма?
очевидно, что делать она должна тоже самое, что и постформа. иначе пользователи класса получат не то что ожидают. а работать она будет видимо через предформу
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 09.04.2010
Сообщений: 297
31.07.2010, 19:59  [ТС]     Перегрузка оператора ++ , деструктор и конструктор копий #11
Цитата Сообщение от CheshireCat
в C++ приняты две формы инкремента/декремента - пред- и пост-
Да, я думал об этом, и решил не делать отличия и пока реализовать только префиксную форму.
Цитата Сообщение от ISergey
Я бы использовал std::string..
Наверное так будет проще. Я так и сделал
Цитата Сообщение от ISergey
PS. Одно не пойму - чем не устроил стандартный класс ofstream/ifstream?
Просто, я последнее время, часто начал обращать внимание на производительность, и якобы, низкоуровневые функции ввода/вывода _open(), _lseek () работают быстрее. Вот я и пихаю их куда надо, и куда не надо, тоже пихаю
Не знаю может тут и выгоднее использовать ofstream/ifstream. Пока оставлю как есть.
DeadRipper
64 / 70 / 3
Регистрация: 25.06.2009
Сообщений: 244
31.07.2010, 20:35     Перегрузка оператора ++ , деструктор и конструктор копий #12
Нельзя смешивать функции работы с памятью C с операторами С++.
не могу понять почему нельзя смешивать new/delete c malloc/free, ведь на месте new/delete все равно при компиляции будут функции из msvcrt malloc и free
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 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 Конструкторы и деструкторы.
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 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];
Заранее спасибо!!!
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
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 выделить еще один байт под нуль-терминатор.
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 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-ом?
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
05.08.2010, 14:25     Перегрузка оператора ++ , деструктор и конструктор копий #17
Цитата Сообщение от FireNovel Посмотреть сообщение
Тогда скопируется и последний нулевой байт.
А ты под него место выделил? Насколько я помню, strlen не считает нуль-терминатор. Тогда, в твоем случае, нужно делать так:
C++
1
this->buffer = new char[ sz = strlen ( obj.buffer ) + 1 ]; //Выделяем память под buffer + нуль-терминатор
Цитата Сообщение от FireNovel Посмотреть сообщение
Вот только вопрос - не быстрее, ли будет это сделать for-ом?
В данном случае лучше использовать strcpy. Разницы в скорости ты точно не заметишь (если она есть), а запись выглядит проще и понятней.
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
05.08.2010, 14:28     Перегрузка оператора ++ , деструктор и конструктор копий #18
Цитата Сообщение от FireNovel Посмотреть сообщение
Вот только вопрос - не быстрее, ли будет это сделать for-ом?
for-ом точно не быстрее как максимум также.
а вообще все правильно, самые быстрые варианты будут скорее всего strcpy и memcpy, что по сути одно и тоже, так как они копируют не поэлементно, а блоками памяти.
FireNovel
 Аватар для FireNovel
150 / 73 / 8
Регистрация: 09.04.2010
Сообщений: 297
05.08.2010, 14:51  [ТС]     Перегрузка оператора ++ , деструктор и конструктор копий #19
И еще один вопросик (скорее философский)...
Как определить, что класс готов? Ведь, при разработке его, очень часто, в голову лезут разные идеи. И вроде бы и так сделать можно, и эдак - было бы хорошо организовать...
И потихоньку увязаешь в коде
Посоветуйте пожалуйста как поступить
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.08.2010, 14:53     Перегрузка оператора ++ , деструктор и конструктор копий
Еще ссылки по теме:

Конструктор инициализации, конструктор копирования, деструктор C++
Конструктор копий C++
Конструктор копирования и перегрузка оператора присваивания C++

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
05.08.2010, 14:53     Перегрузка оператора ++ , деструктор и конструктор копий #20
FireNovel, Поставьте одну цель, что должен делать класс, и не расширяйте пока не сделаете класс таким как поставили. Ну а затем уже по личным приоритетам, может что-то доделать, может что-то добавить и т.д.
Yandex
Объявления
05.08.2010, 14:53     Перегрузка оператора ++ , деструктор и конструктор копий
Ответ Создать тему
Опции темы

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