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

Указатели и конструкторы - C++

Восстановить пароль Регистрация
 
stawerfar
 Аватар для stawerfar
141 / 55 / 4
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
31.01.2012, 22:30     Указатели и конструкторы #1
Всем доброго времени суток!!!
Выполняя упражнение Лафоре 10 главы №1 написав и проверив всё столкнулся с такой проблемой.
Проще показать чем объяснить ниже код, там я в комментариях в main написал в какой момент перестает работать.

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
#include<iostream>
#include<conio.h>
#include<string>
#include<stdlib.h>
class metring
{
private :
    char* ch_pt;//для хранения выражения введённого пользователем
    int imax_fmas;//максимально количество элементов массива fmas
    float* fmas ;//массив вещественных чисел
public:
    //конструктор без параметров
    metring(void);
    //конструктор содним параметром
    metring(char* ch_c);
    //деструктор для освобождение памяти
    ~metring(void);
    //операция преобразования из объекта класса в float*
    operator float*(void);
    //возврат количества элементов в вещественном массиве
    int* return_imax_fmas(void);
    //получение от пользователя набора чисел 
    void get_number(void);
};
 
//конструктор без параметров
metring::metring(void):imax_fmas(1)
{
    setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
    ch_pt = new char[2];//первый раз выдиляю память под строку
    ch_pt[0]='\0';//принудительное указаник конца строки
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел
}
 
//конструктор содним параметром
metring::metring(char* ch_c)
{
    
    setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
    ch_pt = new char[2];//первый раз выдиляю память под строку
    ch_pt[0]='\0';//принудительное указаник конца строки
    imax_fmas=1;
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел   
 
    
    if(strlen(ch_c)>1)
    {delete []ch_pt;}//освобождаю ранее выделенную память т.к. она не достаточна для хранения новой строки 
    ch_pt = new char [strlen(ch_c)+1];
    ch_pt[0]='\0';//принудительное указаник конца строки
    strcpy(ch_pt,ch_c);
    ch_pt[strlen(ch_c)]='\0';//принудительное указаник конца строки
}
//деструктор для освобождение памяти
metring::~metring(void)//освобождаю память
{delete []ch_pt;delete []fmas;}
//получение от пользователя набора чисел 
void metring::get_number(void)
{
    int ilen = 1;//для хранения длинны строки
    char* ch_pt_temp ;//временный банк для обмена
    char ch_temp[2]="e";//инициализация любым значение отличным от нуля и не равным 13(знаку Enter)
    std::cout<<"Введите числа через запятую\nЧисла могут быть целыми так и вещественными : ";
    //создание строки необходимого размера для хранения строки ch_c
    while(ch_temp[0]!=13)//продолжать пока пользователь не нажмёт клавишу Enter
    {
        ch_pt_temp = new char[strlen(ch_pt)+2];//выделяю память под переменную для обмена
        ch_pt_temp[0]='\0';//принудительное указаник конца строки           
        bool flag=true;//флаг для инкримента счетчика символов
        ch_temp[0] = getche();//отобразить символ и записать его значение в переменную типа char
        if(ilen!=1&&ch_temp[0]!=13)//если ilen!=1 и ch_temp!=Enter 
        {                                   //  то освобождаем память для перевыдиления
            //перед освобождением памяти делаю копию значения строки
            //копируем сиволы в нашу строку с нулевым символом
        
            for(int i = 0, r = strlen(ch_pt_temp); i < strlen(ch_pt)+1;i++,r++)
            {
                ch_pt_temp[r]=ch_pt[i]; 
            }
            ch_pt_temp[strlen(ch_pt_temp)+1];//принудительное завершение строки
            delete []ch_pt;//освобождаю выделенную память
            if(ch_temp[0]==8&&strlen(ch_pt_temp))
            {
                std::cout<<"\x20\x08";//затираем предыдущий символ знаком пробела и перемещаем курсор
                ilen--;//уменьшаем значение количество символов в строке
                flag=false;
            }
            else if(ch_temp[0]==8&&strlen(ch_pt_temp)<=0)
            {
                std::cout<<"\x3A";
            }
            ch_pt=new char[ilen+2];//заного выделяю память 1 для нового сивола другой для знака \0 конца строки
            ch_pt[0]='\0';//принудительное указаник конца строки
            //возвращаю значение строки предшествующие перевыдилинию памяти
            //копируем сиволы в нашу строку с нулевым символом
            int itemplen=(strlen(ch_pt_temp)==ilen-2)?ilen-1:ilen;
            for(int i = 0, r = strlen(ch_pt); i < itemplen;i++,r++)
            {
                ch_pt[r]=ch_pt_temp[i]; 
            }
            if(strlen(ch_pt_temp)!=ilen-2)
            {ch_pt[ilen-1]='\0';}
            
        }
        if(ch_temp[0]!=13&&ch_temp[0]!=8)//если ch_temp!=Enter помещаем символ в строку
        {
            //копируем сиволы в нашу строку с нулевым символом
            for(int i = 0, r = strlen(ch_pt); i < strlen(ch_temp)+1;i++,r++)
            {
                ch_pt[r]=ch_temp[i];    
            }
            
        }
        delete[]ch_pt_temp;//освобождаем память
        if(flag)
        {ilen++;}//инкременация счетчика символов
    }
}
 
//операция преобразования из объекта класса в float*
metring:: operator float*(void)
{
    char* ch_pt_temp ;//временный банк для обмена
    int isecondlen=2,//разряд числа
        idex=0;//индекс массива который представляет одно число
    bool flag= true;//флаг для разрешения выдиления памяти для ch_pt_temp
    
    //разбираем массив т.е. отдиляем числа от запятых, целые от вещественных
    for(int i = 0; i<strlen(ch_pt);i++)
    {
        if(flag)//выделяем каждый раз когда следует отдельное число 
        {
            ch_pt_temp = new char[isecondlen];//выделяю память под переменную для обмена
            ch_pt_temp[0]='\0';//принудительное указаник конца строки
            flag=false;//запрещаем перевыдиление памяти пока не закочится число
        }
        
        if(isecondlen>strlen(ch_pt_temp)&&(strlen(ch_pt_temp)!=0)&&ch_pt[i]!=',')
        {
            char* ch_pt_temp2 = new char[isecondlen+2];//выделяю память для временной переменной
            ch_pt_temp2[0]= '\0';//принудительно инициализирую её первый символ нулём
            //копируем сиволы в нашу строку с нулевым символом
            for(int i = 0, r = strlen(ch_pt_temp2); i < strlen(ch_pt_temp)+1;i++,r++)
            {
                ch_pt_temp2[r]=ch_pt_temp[i];   
            }
            delete []ch_pt_temp;//освобождаю память
            //выделяю памяти больше на одну единицу
            ch_pt_temp = new char[isecondlen+2];//выделяю память под переменную для обмена
            ch_pt_temp[0]= '\0';//принудительно инициализирую её первый символ нулём
 
            //копируем сиволы в нашу строку с нулевым символом
            for(int i = 0, r = strlen(ch_pt_temp); i < strlen(ch_pt_temp2)+1;i++,r++)
            {
                ch_pt_temp[r]=ch_pt_temp2[i];   
            }
            delete []ch_pt_temp2;//освобождаю память
        }
        if(ch_pt[i]!=',')//если символ не является разделительным символом то просто копируем цифру
        {
            ch_pt_temp[idex++]=ch_pt[i];//копируем символ
            ch_pt_temp[idex]= '\0';//принудительное завершение строки
            isecondlen++;//увеличиваем разряд числа
        }
        if(ch_pt[i]==','||(i+1>=strlen(ch_pt)))//если символ разделительный то переобразуем массив ch_pt_temp в float
        {
            
            isecondlen=2;//инициализируем  флаг на 1 следящий за разрядом числа
            flag=true;//разрешаем перевыдиление памяти т.к. число закончилось
            if(imax_fmas)//если не нулевое значение значит нужно перевыделить память для вещественного массива
            {
                float* f_mas_temp = new float[imax_fmas];//создаю временный массив для страховки основного массива fmas
                for(int e =0 ; e<imax_fmas;e++)
                {
                    f_mas_temp[e]=fmas[e];//копирую значения массива
                }
                delete []fmas;//освобождаю память
                fmas = new float[imax_fmas+1];// перевыдиляю память
                for(int e =0 ; e<imax_fmas;e++)
                {
                    fmas[e]=f_mas_temp[e];//копирую значения массива
                }
                delete[]f_mas_temp;//освобождаю выделенную память
            }
            ch_pt_temp[idex]='\0';//принудительно завершаю строку нулевым символом
            idex = 0;//обнуление индекса
            //проверка числа т.е. было оно целым или вещественным путем поиска символа '.'
            for(int k = 0 ; k<strlen(ch_pt_temp);k++)
            {
                if(ch_pt_temp[k]=='.')//если такой символ есть то меняю его на ',' так требует atof
                {ch_pt_temp[k]=',';}
            }
 
            //преобразуем массив символов в вещественное число
            fmas[imax_fmas-1] = atof(ch_pt_temp);
            if(!(i+1>=strlen(ch_pt)))
            {imax_fmas++;}//увеличиваем число элементов в вещественном массиве
            delete[]ch_pt_temp;//освобождение памяти для массива для представления любого числа
        }
        
    }
    return (fmas);//возвращаю массив чисел типа float
}
//возврат количества элементов в вещественном массиве
int* metring:: return_imax_fmas(void)
{return(&imax_fmas);}
 
/**************************************************************************************************************/
int main(void)
{
    //объявление класса
    class metring metring_val;
    //прототип
    float avg(metring&);
    //получение значения от пользователя
    metring_val.get_number();
    // подсчёт среднего значения  вывод результата на экран
    std::cout<<std::endl<<"Средние арефметическое : "<<avg(metring_val)<<std::endl;
    //использования конструктора с одним параметром
    class metring metring_val2 ("1,2,3,4,5,6");
    // подсчёт среднего значения  вывод результата на экран
    std::cout<<std::endl<<"Средние арефметическое : "<<avg(metring_val2)<<std::endl;
/*НЕРАБОТАЕТ ЕСЛИ ДЕЛАТЬ ВОТ ТАК
              metring_val2 ="1,2,3,4,5,6";
    // подсчёт среднего значения  вывод результата на экран
    std::cout<<std::endl<<"Средние арефметическое : "<<avg(metring_val2)<<std::endl;
*/
 
system("pause");
 
return 0;
}
float avg(metring& metring_val)
{
    //подсчитываем среднее арефметическое массива вещественных чисел
    float db_result = 0.0;//для среднего арефметического массива
    float* fres = static_cast<float*>(metring_val);
    for(int i=0;i<*(metring_val.return_imax_fmas());i++)
    {db_result+=fres[i];}
 
    return  db_result/ *(metring_val.return_imax_fmas());
}
В этой строчке
C++
1
metring_val2 ("1,2,3,4,5,6");
я вызываю конструктор с одним параметром , там происходят все необходимые действия т.е выделение памяти для массива символов и вещественного массива, так же инициализация поля для хранения количества чисел в вещественном массиве.
НО каким то чудесным образом когда я передаю объект по ссылке оказывается что поля класса оказываются не инициализированными, ну и в следствии ошибка т.к. я обращаюсь к не пойми каким адресам.
Подскажите в чем дело или как исправить если кто сталкивался с подобной ситуацией.
Заранее спасибо!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.01.2012, 22:30     Указатели и конструкторы
Посмотрите здесь:

Конструкторы C++
конструкторы C++
C++ конструкторы
C++ конструкторы
Конструкторы C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.02.2012, 00:12     Указатели и конструкторы #2
читай, да и вообще ваш код ужасен
stawerfar
 Аватар для stawerfar
141 / 55 / 4
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
01.02.2012, 00:31  [ТС]     Указатели и конструкторы #3
Цитата Сообщение от Jupiter Посмотреть сообщение
читай, да и вообще ваш код ужасен
Код ужасен? И что внем ужасного?
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.02.2012, 00:44     Указатели и конструкторы #4
1. отсутствует конструктор копии(из-за чего проблема и возникла) и оператор присваивания
2. конструкторы
ваш
Цитата Сообщение от stawerfar Посмотреть сообщение
C++
1
2
3
4
5
6
7
metring::metring(void):imax_fmas(1)
{
    setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
    ch_pt = new char[2];//первый раз выдиляю память под строку
    ch_pt[0]='\0';//принудительное указаник конца строки
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел
}

мой
C++
1
2
3
4
5
metring::metring(void) : imax_fmas(1)
{
    ch_pt = new char[imax_fmas + 1]();
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел
}


ваш
Цитата Сообщение от stawerfar Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//конструктор содним параметром
metring::metring(char* ch_c)
{
setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
 ch_pt = new char[2];//первый раз выдиляю память под строку
 ch_pt[0]='\0';//принудительное указаник конца строки
 imax_fmas=1;
 fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел * 
if(strlen(ch_c)>1)
 {delete []ch_pt;}//освобождаю ранее выделенную память т.к. она не достаточна для хранения новой строки 
 ch_pt = new char [strlen(ch_c)+1];
 ch_pt[0]='\0';//принудительное указаник конца строки
 strcpy(ch_pt,ch_c);
 ch_pt[strlen(ch_c)]='\0';//принудительное указаник конца строки
}

мой
C++
1
2
3
4
5
6
7
8
//конструктор содним параметром
metring::metring(const char* ch_c)
{
    imax_fmas = 1;
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел * 
    ch_pt = new char [strlen(ch_c)+1]();
    strcpy(ch_pt, ch_c);
}

setlocale достаточно вызвать один раз в main
3.
Цитата Сообщение от stawerfar Посмотреть сообщение
metring:: operator float*(void)
оператор привидения типа должен только приводить тип, а он у вас ещё какую-то фигню делает
stawerfar
 Аватар для stawerfar
141 / 55 / 4
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
01.02.2012, 01:01  [ТС]     Указатели и конструкторы #5
Дорогой мой собеседник Вы не разобравшись в коде "вешаете ярлыки" типа "код ужасен".
Не фигню делает а если Вы внимательно проследите за мыслью то может увидите что он динамически выделяет память, причем заранее я не знаю какую строку введёт пользователь(длину) Вот по этому и провожу соответствующие манипуляции.
Да и если человек мыслит по другому это ещё не повод говорить ему что его код ужасен.
П.С: мой код соответствуем международному стандарту (в оформлении) так что вот так "Василий"

Добавлено через 4 минуты
Цитата Сообщение от Jupiter Посмотреть сообщение
отсутствует конструктор копии(из-за чего проблема и возникла) и оператор присваивания
Тут Вы тоже не правы я добавлял конструктор копий , и в нём явно указывал как копировать поля класса, но ничего ни изменилось.
Вы бы что бы не быть голословным попробовали показать исправленный рабочий код в моей ситуации.

Добавлено через 5 минут
Я не знаю почему так произошло но когда я использовал strcpy() то при освобождении памяти возникали ошибки мол ещё кто то ссылается на выделенную память. Решение я нашёл сделав тоже самое через цикл.
Да и strcpy() не копирует '\0' , а если этого не делать то функция ctrcar() и strlen() работают не правильно...
Так что вот так вот.
NoMasters
Псевдослучайный
1737 / 1080 / 69
Регистрация: 13.09.2011
Сообщений: 3,093
01.02.2012, 01:05     Указатели и конструкторы #6
Цитата Сообщение от stawerfar Посмотреть сообщение
strcpy() не копирует '\0'
вызывающе неверная информация
Цитата Сообщение от stawerfar Посмотреть сообщение
но когда я использовал strcpy() то при освобождении памяти возникали ошибки мол ещё кто то ссылается на выделенную память.
Казалось бы, причём тут strcpy(), которая никакие указатели никуда не переписывает...
stawerfar
 Аватар для stawerfar
141 / 55 / 4
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
01.02.2012, 01:10  [ТС]     Указатели и конструкторы #7
Цитата Сообщение от NoMasters Посмотреть сообщение
лось бы, причём тут strcpy(), которая никакие указатели никуда не переписывает...
Фигня вопрос для ясности просто Вам надо скопировать код ,изменить все соответсвующие циклы на strcpy() и почитать сообщение об ощибке.

Добавлено через 1 минуту
Цитата Сообщение от NoMasters Посмотреть сообщение
вызывающе неверная информация
Сострил
NoMasters
Псевдослучайный
1737 / 1080 / 69
Регистрация: 13.09.2011
Сообщений: 3,093
01.02.2012, 01:11     Указатели и конструкторы #8
Покажи мне свой конструктор копирования и я скажу, где ты в корне неправ.

Добавлено через 27 секунд
Цитата Сообщение от stawerfar Посмотреть сообщение
Сострил
Документацию читать пробовал?
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
01.02.2012, 01:18     Указатели и конструкторы #9
Цитата Сообщение от stawerfar Посмотреть сообщение
Не фигню делает
дык и выносите это полезное действие в отдельный метод, оператор привидения типов должен только выполнять привидение и ничего более
Цитата Сообщение от stawerfar Посмотреть сообщение
Тут Вы тоже не правы я добавлял конструктор копий , и в нём явно указывал как копировать поля класса, но ничего ни изменилось.
вашего конструктора не видно, значит его нет

Цитата Сообщение от stawerfar Посмотреть сообщение
Да и strcpy() не копирует '\0' , а если этого не делать то функция ctrcar() и strlen() работают не правильно...
Так что вот так вот.
C++
1
2
char* ptr = new char [10]; //в строке мусор
char* ptr = new char [10](); //вся строка заполнена нулями
Цитата Сообщение от stawerfar Посмотреть сообщение
может увидите что он динамически выделяет память, причем заранее я не знаю какую строку введёт пользователь(длину) Вот по этому и провожу соответствующие манипуляции.
Цитата Сообщение от stawerfar Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//конструктор содним параметром
metring::metring(char* ch_c)
{
setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
* * * * ch_pt = new char[2];//первый раз выдиляю память под строку
* * * * ch_pt[0]='\0';//принудительное указаник конца строки
* * * * imax_fmas=1;
* * * * fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел * 
if(strlen(ch_c)>1)
* * * * {delete []ch_pt;}//освобождаю ранее выделенную память т.к. она не достаточна для хранения новой строки 
* * * * ch_pt = new char [strlen(ch_c)+1];
* * * * ch_pt[0]='\0';//принудительное указаник конца строки
* * * * strcpy(ch_pt,ch_c);
* * * * ch_pt[strlen(ch_c)]='\0';//принудительное указаник конца строки
}
ок, здесь то зачем выделять под 2 символа, а только потом уже проверять длину(и удалять), когда можно сразу выделить под длину всей строки
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
01.02.2012, 01:33     Указатели и конструкторы #10
Цитата Сообщение от stawerfar Посмотреть сообщение
//объявление класса
* * * * class metring metring_val;
зачем?
Цитата Сообщение от stawerfar Посмотреть сообщение
//прототип
* * * * float avg(metring&);
почему прототип тут, а не в начале файла? те это не критично, но странно
Цитата Сообщение от stawerfar Посмотреть сообщение
class metring metring_val2 ("1,2,3,4,5,6");
боже боже, это вообще какой язык?
Цитата Сообщение от stawerfar Посмотреть сообщение
//конструктор без параметров
* * * * metring(void);
(void) пишут в си, там это несет смысл, в с++ достаточно ()
Цитата Сообщение от stawerfar Посмотреть сообщение
//возврат количества элементов в вещественном массиве
* * * * int* return_imax_fmas(void);
а что, снаружи можно менять количество элементов? (это к тому, что указатель)
Цитата Сообщение от stawerfar Посмотреть сообщение
#include<conio.h>
выпилить его
Цитата Сообщение от stawerfar Посмотреть сообщение
#include<stdlib.h>
на с++ пишут <cstdlib>

еще куча warning'ов, которые должны быть убраны
да и сам код тот еще

вот компилируемый вариант

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
#include<iostream>
#include<cstdlib>
#include <cstring>
class metring
{
private :
        char* ch_pt;//для хранения выражения введённого пользователем
        int imax_fmas;//максимально количество элементов массива fmas
        float* fmas ;//массив вещественных чисел
public:
        //конструктор без параметров
        metring(void);
        //конструктор содним параметром
        metring(const char* ch_c);
        //деструктор для освобождение памяти
        ~metring(void);
        //операция преобразования из объекта класса в float*
        operator float*(void);
        //возврат количества элементов в вещественном массиве
        int* return_imax_fmas(void);
        //получение от пользователя набора чисел 
        void get_number(void);
};
 
//конструктор без параметров
metring::metring(void):imax_fmas(1)
{
        setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
        ch_pt = new char[2];//первый раз выдиляю память под строку
        ch_pt[0]='\0';//принудительное указаник конца строки
        fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел
}
 
//конструктор содним параметром
metring::metring(const char* ch_c)
{
        
        setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
        ch_pt = new char[2];//первый раз выдиляю память под строку
        ch_pt[0]='\0';//принудительное указаник конца строки
        imax_fmas=1;
        fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел   
 
        
        if(strlen(ch_c)>1)
        {delete []ch_pt;}//освобождаю ранее выделенную память т.к. она не достаточна для хранения новой строки 
        ch_pt = new char [strlen(ch_c)+1];
        ch_pt[0]='\0';//принудительное указаник конца строки
        strcpy(ch_pt,ch_c);
        ch_pt[strlen(ch_c)]='\0';//принудительное указаник конца строки
}
//деструктор для освобождение памяти
metring::~metring(void)//освобождаю память
{delete []ch_pt;delete []fmas;}
//получение от пользователя набора чисел 
void metring::get_number(void)
{
        int ilen = 1;//для хранения длинны строки
        char* ch_pt_temp ;//временный банк для обмена
        char ch_temp[2]="e";//инициализация любым значение отличным от нуля и не равным 13(знаку Enter)
        std::cout<<"Введите числа через запятую\nЧисла могут быть целыми так и вещественными : ";
        //создание строки необходимого размера для хранения строки ch_c
        while(ch_temp[0]!=13)//продолжать пока пользователь не нажмёт клавишу Enter
        {
                ch_pt_temp = new char[strlen(ch_pt)+2];//выделяю память под переменную для обмена
                ch_pt_temp[0]='\0';//принудительное указаник конца строки                       
                bool flag=true;//флаг для инкримента счетчика символов
                ch_temp[0] = getc(stdout);//отобразить символ и записать его значение в переменную типа char
                if(ilen!=1&&ch_temp[0]!=13)//если ilen!=1 и ch_temp!=Enter 
                {                                                                       //      то освобождаем память для перевыдиления
                        //перед освобождением памяти делаю копию значения строки
                        //копируем сиволы в нашу строку с нулевым символом
                
                        for(unsigned i = 0, r = strlen(ch_pt_temp); i < strlen(ch_pt)+1;i++,r++)
                        {
                                ch_pt_temp[r]=ch_pt[i]; 
                        }
                        ch_pt_temp[strlen(ch_pt_temp)+1] = 0;//принудительное завершение строки
                        delete []ch_pt;//освобождаю выделенную память
                        if(ch_temp[0]==8&&strlen(ch_pt_temp))
                        {
                                std::cout<<"\x20\x08";//затираем предыдущий символ знаком пробела и перемещаем курсор
                                ilen--;//уменьшаем значение количество символов в строке
                                flag=false;
                        }
                        else if(ch_temp[0]==8&&strlen(ch_pt_temp)<=0)
                        {
                                std::cout<<"\x3A";
                        }
                        ch_pt=new char[ilen+2];//заного выделяю память 1 для нового сивола другой для знака \0 конца строки
                        ch_pt[0]='\0';//принудительное указаник конца строки
                        //возвращаю значение строки предшествующие перевыдилинию памяти
                        //копируем сиволы в нашу строку с нулевым символом
                        int itemplen=((int)strlen(ch_pt_temp)==ilen-2)?ilen-1:ilen;
                        for(int i = 0, r = strlen(ch_pt); i < itemplen;i++,r++)
                        {
                                ch_pt[r]=ch_pt_temp[i]; 
                        }
                        if((int)strlen(ch_pt_temp)!=ilen-2)
                        {ch_pt[ilen-1]='\0';}
                        
                }
                if(ch_temp[0]!=13&&ch_temp[0]!=8)//если ch_temp!=Enter помещаем символ в строку
                {
                        //копируем сиволы в нашу строку с нулевым символом
                        for(unsigned i = 0, r = strlen(ch_pt); i < strlen(ch_temp)+1;i++,r++)
                        {
                                ch_pt[r]=ch_temp[i];    
                        }
                        
                }
                delete[]ch_pt_temp;//освобождаем память
                if(flag)
                {ilen++;}//инкременация счетчика символов
        }
}
 
//операция преобразования из объекта класса в float*
metring:: operator float*(void)
{
        char* ch_pt_temp ;//временный банк для обмена
        unsigned isecondlen=2,//разряд числа
                idex=0;//индекс массива который представляет одно число
        bool flag= true;//флаг для разрешения выдиления памяти для ch_pt_temp
        
        //разбираем массив т.е. отдиляем числа от запятых, целые от вещественных
        for(unsigned i = 0; i<strlen(ch_pt);i++)
        {
                if(flag)//выделяем каждый раз когда следует отдельное число 
                {
                        ch_pt_temp = new char[isecondlen];//выделяю память под переменную для обмена
                        ch_pt_temp[0]='\0';//принудительное указаник конца строки
                        flag=false;//запрещаем перевыдиление памяти пока не закочится число
                }
                
                if(isecondlen>strlen(ch_pt_temp)&&(strlen(ch_pt_temp)!=0)&&ch_pt[i]!=',')
                {
                        char* ch_pt_temp2 = new char[isecondlen+2];//выделяю память для временной переменной
                        ch_pt_temp2[0]= '\0';//принудительно инициализирую её первый символ нулём
                        //копируем сиволы в нашу строку с нулевым символом
                        for(unsigned i = 0, r = strlen(ch_pt_temp2); i < strlen(ch_pt_temp)+1;i++,r++)
                        {
                                ch_pt_temp2[r]=ch_pt_temp[i];   
                        }
                        delete []ch_pt_temp;//освобождаю память
                        //выделяю памяти больше на одну единицу
                        ch_pt_temp = new char[isecondlen+2];//выделяю память под переменную для обмена
                        ch_pt_temp[0]= '\0';//принудительно инициализирую её первый символ нулём
 
                        //копируем сиволы в нашу строку с нулевым символом
                        for(unsigned i = 0, r = strlen(ch_pt_temp); i < strlen(ch_pt_temp2)+1;i++,r++)
                        {
                                ch_pt_temp[r]=ch_pt_temp2[i];   
                        }
                        delete []ch_pt_temp2;//освобождаю память
                }
                if(ch_pt[i]!=',')//если символ не является разделительным символом то просто копируем цифру
                {
                        ch_pt_temp[idex++]=ch_pt[i];//копируем символ
                        ch_pt_temp[idex]= '\0';//принудительное завершение строки
                        isecondlen++;//увеличиваем разряд числа
                }
                if(ch_pt[i]==','||(i+1>=strlen(ch_pt)))//если символ разделительный то переобразуем массив ch_pt_temp в float
                {
                        
                        isecondlen=2;//инициализируем  флаг на 1 следящий за разрядом числа
                        flag=true;//разрешаем перевыдиление памяти т.к. число закончилось
                        if(imax_fmas)//если не нулевое значение значит нужно перевыделить память для вещественного массива
                        {
                                float* f_mas_temp = new float[imax_fmas];//создаю временный массив для страховки основного массива fmas
                                for(int e =0 ; e<imax_fmas;e++)
                                {
                                        f_mas_temp[e]=fmas[e];//копирую значения массива
                                }
                                delete []fmas;//освобождаю память
                                fmas = new float[imax_fmas+1];// перевыдиляю память
                                for(int e =0 ; e<imax_fmas;e++)
                                {
                                        fmas[e]=f_mas_temp[e];//копирую значения массива
                                }
                                delete[]f_mas_temp;//освобождаю выделенную память
                        }
                        ch_pt_temp[idex]='\0';//принудительно завершаю строку нулевым символом
                        idex = 0;//обнуление индекса
                        //проверка числа т.е. было оно целым или вещественным путем поиска символа '.'
                        for(unsigned k = 0 ; k<strlen(ch_pt_temp);k++)
                        {
                                if(ch_pt_temp[k]=='.')//если такой символ есть то меняю его на ',' так требует atof
                                {ch_pt_temp[k]=',';}
                        }
 
                        //преобразуем массив символов в вещественное число
                        fmas[imax_fmas-1] = atof(ch_pt_temp);
                        if(!(i+1>=strlen(ch_pt)))
                        {imax_fmas++;}//увеличиваем число элементов в вещественном массиве
                        delete[]ch_pt_temp;//освобождение памяти для массива для представления любого числа
                }
                
        }
        return (fmas);//возвращаю массив чисел типа float
}
//возврат количества элементов в вещественном массиве
int* metring:: return_imax_fmas(void)
{return(&imax_fmas);}
 
/**************************************************************************************************************/
float avg(metring&);
 
int main(void)
{
        metring metring_val;
        //получение значения от пользователя
        metring_val.get_number();
        // подсчёт среднего значения  вывод результата на экран
        std::cout<<std::endl<<"Средние арефметическое : "<<avg(metring_val)<<std::endl;
        //использования конструктора с одним параметром
        metring metring_val2 ("1,2,3,4,5,6");
        // подсчёт среднего значения  вывод результата на экран
        std::cout<<std::endl<<"Средние арефметическое : "<<avg(metring_val2)<<std::endl;
/*НЕРАБОТАЕТ ЕСЛИ ДЕЛАТЬ ВОТ ТАК
              metring_val2 ="1,2,3,4,5,6";
        // подсчёт среднего значения  вывод результата на экран
        std::cout<<std::endl<<"Средние арефметическое : "<<avg(metring_val2)<<std::endl;
*/
 
system("pause");
 
return 0;
}
float avg(metring& metring_val)
{
        //подсчитываем среднее арефметическое массива вещественных чисел
        float db_result = 0.0;//для среднего арефметического массива
        float* fres = static_cast<float*>(metring_val);
        for(int i=0;i<*(metring_val.return_imax_fmas());i++)
        {db_result+=fres[i];}
 
        return  db_result/ *(metring_val.return_imax_fmas());
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.02.2012, 21:20     Указатели и конструкторы
Еще ссылки по теме:

Конструкторы и указатели на объект класса C++
C++ Конструкторы
C++ Конструкторы С++

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

Или воспользуйтесь поиском по форуму:
stawerfar
 Аватар для stawerfar
141 / 55 / 4
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
01.02.2012, 21:20  [ТС]     Указатели и конструкторы #11
Да ребята, вот смотрю на Вас и офигиваю Вас просили подсказать решение проблемы. А Вы? Вместо бы того что бы в грязи полоскать и жестко критиковать реально бы подсказали в чём беда.
Я ещё учусь, не забили что мы находимся в разделе для начинающих, мало того чистота письма приходит с опытом.Все что я делал я делал по заданию,ну короче я в шоке с Вас.Так себя ведут только неудачники обиженные на мир, которые "опуская" других подымают свою самооценку.
Yandex
Объявления
01.02.2012, 21:20     Указатели и конструкторы
Ответ Создать тему
Опции темы

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