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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.86
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
#1

Добавить значение в конец динамического массива (имитация функции вектора) - C++

09.12.2012, 11:20. Просмотров 1769. Ответов 19
Метки нет (Все метки)

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
#include <iostream>
 
using namespace std;
 
void show(int **P,int N)  //отображение массива
{
  for (int i=0;i<N;i++) cout<<(*P)[i]<<"  ";
  cout<<endl;
}
 
void create(int **P,int N) //создание массива
{
    *P=new int[N]; //выделяю память
    for (int i=0;i<N;i++) (*P)[i]=i+1; //Заполняю   
}
 
/*ВОТ ТУТ НЕ ЗНАЮ КАК*/
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
  N++; //увеличиваю диапазон значений на один
  int *temp=new int[N]; //временный указатель
  temp=*P; 
  temp[N-1]=x;
  show(&temp,N); //вызывает ошибку
  *P=temp;
}
 
int main()
{
    int *P; //Указатель будет использован как массив
    int N=0; //число элементов в массиве
    cin>>N; 
    ////////////////
 
    create(&P,N); //создание массива с выделением памяти
    show(&P,N); //отображаю массив на экране
    add(&P,N,100); //попытка выделить ячейку памяти в конец массива и поместить туда 100, не затирая остального
 
    delete []P; //освобождение памяти
        
    return 0;
}
Интересует функция add для добавления только одного элемента в конец динамического массива. В коде она не сделана совсем, потому что не знаю почему ошибка и как исправить.
Интересует правильное освобождение памяти при подобном программировании. Возможно я освобождаю не так. Т.е. интересует как правильно освобождать, если выделялась в функциях. Например если я внутри отдельной функции выделю новую ячейку памяти в конец массива, запишу туда элемент, то как правильно освобождать потом. Интуитивно понимаю, что именно этот новый элемент не удалится, если использовать освобождение так как прописано у меня.

Не интересует vector, интересует велосипед.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.12.2012, 11:20     Добавить значение в конец динамического массива (имитация функции вектора)
Посмотрите здесь:

Присвоить значение полям динамического массива структуры C++
Функция: посчитать сумму элементов динамического массива, перераспределить память и добавить сумму в конец C++
Как посмотреть значение динамического массива C++
C++ Добавить в конец массива элементы, расположенные между min и max элементами исходного массива, исключая нули
Как вызвать метод вектора из динамического массива? C++
C++ Добавить строку в конец массива
C++ Передача динамического массива в функции
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 11:46     Добавить значение в конец динамического массива (имитация функции вектора) #2
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
#include <iostream>
 
using namespace std;
 
void show(int **P,int N)  //отображение массива
{
  for (int i=0;i<N;i++) cout<<(*P)[i]<<"  ";
  cout<<endl;
}
 
void create(int **P,int N) //создание массива
{
    *P=new int[N]; //выделяю память
    for (int i=0;i<N;i++) (*P)[i]=i+1; //Заполняю
}
 
/*ВОТ ТУТ НЕ ЗНАЮ КАК*/
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
  N++; //увеличиваю диапазон значений на один
  int *temp=new int[N]; //временный указатель
  for (int i = 0; i < N-1; i++) {
     temp[i]=(*P)[i];            // у вас было  temp=*P; что озночало что выделенная
  }                             // память на tmp  утекала так как его адрес терялся
  temp[N-1]=x;
  show(&temp,N); //вызывает ошибку
  *P=temp;
  delete temp;
}
 
int main()
{
    int *P; //Указатель будет использован как массив
    int N=0; //число элементов в массиве
    cin>>N;
    ////////////////
 
    create(&P,N); //создание массива с выделением памяти
    show(&P,N); //отображаю массив на экране
    add(&P,N,100); //попытка выделить ячейку памяти в конец массива и поместить туда 100, не затирая остального
 
    delete []P; //освобождение памяти
 
    return 0;
}
Миниатюры
Добавить значение в конец динамического массива (имитация функции вектора)  
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 11:57  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #3
Может и работает иногда, но в коде есть ошибка. В вашем, Nixy
Миниатюры
Добавить значение в конец динамического массива (имитация функции вектора)  
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 12:02  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #4
память на tmp утекала так как его адрес терялся
Как же он терялся, если я его носом тыкал на начало другой кучи?)
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 12:07     Добавить значение в конец динамического массива (имитация функции вектора) #5
Цитата Сообщение от daslex Посмотреть сообщение
Как же он терялся, если я его носом тыкал на начало другой кучи?)
а так что темп это адрес скажем 00000 вы выделили под него 5 адресов типа инт каждый по 4 байта последний эллемент бужет 00020, а потом вы делаете как вы говорите тыкание носом, скажем в адрес 00024, это начало массива адресов P, и каким таким образом темп будет помнить о том что его то значения 00000-00020? никаким в этом то и ошибка, фактически у вас стало два массива P старого размера, насчет ошибки, у меня все работает, возможно это ошибки дебага, запускайте без дебага
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 12:09  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #6
Как там терялась понял, но все равно ошибка осталась.
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 12:10     Добавить значение в конец динамического массива (имитация функции вектора) #7
Цитата Сообщение от daslex Посмотреть сообщение
Как там терялась понял, но все равно ошибка осталась.
вы в дебаг режиме запускаете? по пробуйте просто ран
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 13:14  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #8
Ctrl+F5 запускаю.

=============
Там еще одна утечка. Может из-за нее? P утекает. еще не исправил я, может поможет

Добавлено через 4 минуты
не помогло. ошибка

Добавлено через 16 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
  N++; //увеличиваю диапазон значений на один
  int *temp=new int[N+1]; //временный указатель
  int *temp2;
 
  for (int i = 0; i < N; i++)  temp[i]=(*P)[i]; //копирую данные из кучи *P в кучу temp
  temp[N-1]=x; //Дописываю элемент
  show(&temp,N); //вызывает ошибку
 
  //тут проблема!!!
  for (int i = 0; i < N; i++) (*P)[i]=temp[i]; //копирую обратно. 
  *P=temp; //К P не было добавлено выделенной ячейки памяти
  delete temp;
}
так всё как-то не так. Память должна добавиться, но она не будет добавлена. Как быть?

Добавлено через 22 минуты
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
#include <iostream>
 
using namespace std;
 
void show(int **P,int N)  //отображение массива
{
  for (int i=0;i<N;i++) cout<<(*P)[i]<<"  ";
  cout<<endl;
}
 
void create(int **P,int N) //создание массива
{
    *P=new int[N]; //выделяю память
    for (int i=0;i<N;i++) (*P)[i]=i+1; //Заполняю
}
 
/*ВОТ ТУТ НЕ ЗНАЮ КАК*/
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
    N++;
 
    P[N]=new int[sizeof(N)]; //выделяю память для новой ячейки
    (*P)[N-1]=x;    //записываю значение
}
 
int main()
{
    int *P; //Указатель будет использован как массив
    int N=0; //число элементов в массиве
    cin>>N;
    ////////////////
 
    create(&P,N); //создание массива с выделением памяти
    show(&P,N); //отображаю массив на экране
    add(&P,N,100); //попытка выделить ячейку памяти в конец массива и поместить туда 100, не затирая остального
    show(&P,N);
    add(&P,N,200);
    show(&P,N);
 
    return 0;
}
Исправил. при первом добавлении всё норм, а при втором ошибка.
Вопрос с освобождением памяти остался

Добавлено через 14 минут
До 50 теперь норм, дальше ошибка
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
 
using namespace std;
 
void show(int **P,int N)  //отображение массива
{
  for (int i=0;i<N;i++) cout<<(*P)[i]<<"  ";
  cout<<endl;
}
 
void create(int **P,int &N) //создание массива
{
    N++;
    *P=new int[N]; //выделяю память
    for (int i=0;i<N;i++) (*P)[i]=i+1; //Заполняю
    
}
 
/*ВОТ ТУТ НЕ ЗНАЮ КАК*/
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{   
    P[N]=new int[sizeof(int)];
    (*P)[N]=x;  
     N++;
}
 
int main()
{
    int *P; //Указатель будет использован как массив
    int N=0; //число элементов в массиве
    cin>>N;
    ////////////////
 
    create(&P,N); //создание массива с выделением памяти
   
    
    /*Запись в конец по одному значению циклом*/
    show(&P,N);
    for (int i=0;i<40;i++)
    {
      add(&P,N,i+i);
      show(&P,N);
 
    }
    
    
    return 0;
}
как освобождать память теперь?
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 13:21     Добавить значение в конец динамического массива (имитация функции вектора) #9
я не понимаю что ты мудришь? мой код замечательно работает
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
  N++; //увеличиваю диапазон значений на один
  int *temp=new int[N+1]; //временный указатель
  int *temp2;
 
  for (int i = 0; i < N; i++)  temp[i]=(*P)[i]; //копирую данные из кучи *P в кучу temp
  temp[N-1]=x; //Дописываю элемент
  show(&temp,N); //вызывает ошибку
 
  //тут проблема!!!
  for (int i = 0; i < N; i++) (*P)[i]=temp[i]; //копирую обратно. 
  *P=temp; //К P не было добавлено выделенной ячейки памяти
             // а P и не надо оно после этой строки указвает на другое место в памяти, можно перед этим убить
            // предыдущий указатель P
  delete temp;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
  N++; //увеличиваю диапазон значений на один
  int *temp=new int[N]; //временный указатель
  for (int i = 0; i < N-1; i++) {
     temp[i]=(*P)[i];
  }
  temp[N-1]=x;
  delete P;    // освободим Р
  show(&temp,N);
  *P=temp;      // P указывает на облось tmp
  delete temp;  // убиваем tmp
}
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 14:32  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #10
Цитата Сообщение от Nixy Посмотреть сообщение
мой код замечательно работает
В main
C++
1
2
3
4
/*Запись в конец по одному значению циклом*/
    show(&P,N); 
      add(&P,N,5);
      show(&P,N);
неверно

Добавлено через 7 минут
В обоих случаях неверно
1. Не то выводит
2. Ошибка.
==============
поэтому мудрю.

Добавлено через 51 минуту
Цитата Сообщение от Nixy Посмотреть сообщение
delete P; // освободим Р
неправильно освобождаете кучу (мало ли кто-то прочтет, возьмет в привычку и потом будет страдать)
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 14:35     Добавить значение в конец динамического массива (имитация функции вектора) #11
если убрать delete P , то будет работать вот так
Код
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
void add(int**P,int &N,int x) //добавляю один элемент в конец массива
{
  N++; //увеличиваю диапазон значений на один
  int *temp=new int[N]; //временный указатель
  for (int i = 0; i < N-1; i++) {
     temp[i]=(*P)[i];
  }
  temp[N-1]=x;
  show(&temp,N);
  *P=temp;      // P указывает на облось tmp
  delete temp;  // убиваем tmp
}
 
int main()
{
    int *P; //Указатель будет использован как массив
    int N=0; //число элементов в массиве
    cin>>N;
    ////////////////
 
    create(&P,N); //создание массива с выделением памяти
    for (int i = 0; i < 10; i++) {
     add(&P,N,i*100);
    }
 
    delete []P; //освобождение памяти
 
    return 0;
}
Миниатюры
Добавить значение в конец динамического массива (имитация функции вектора)  
Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
09.12.2012, 14:39     Добавить значение в конец динамического массива (имитация функции вектора) #12
daslex, Дам простой совет, сразу приношу извинения, если вам это известно (я не читал все сообщения). Вектор - класс, содержащий динамический массив, в котором есть capacity - это реальная длина дин. массива, а size - его формальная длина, и если size >= capacity вектор создаёт новый дин. массив длины capacity * 2 и помещает в начало старый вектор

Добавлено через 59 секунд
daslex, и ещё, у вас вообще нету ооп, а только функционал, попробуйте написать класс vector
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 14:41     Добавить значение в конец динамического массива (имитация функции вектора) #13
Цитата Сообщение от Ternsip Посмотреть сообщение
daslex, Дам простой совет, сразу приношу извинения, если вам это известно (я не читал все сообщения). Вектор - класс, содержащий динамический массив, в котором есть capacity - это реальная длина дин. массива, а size - его формальная длина, и если size >= capacity вектор создаёт новый дин. массив длины capacity * 2 и помещает в начало старый вектор

Добавлено через 59 секунд
daslex, и ещё у вас вообще нету ооп, а только функционал, попробуйте написать класс vector
тут все в сообщении есть, проблема стоит в правильном освобождении памяти
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 15:05  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #14
Цитата Сообщение от Nixy Посмотреть сообщение
если убрать delete P , то будет работать вот так
Тут как бы с одной стороны мелочь
delete P; //Это как голову отрубили, а остальное всё как Ленин в Мавзолее
delete []P; //Это удаление массива

я об этом.
===============
Вот, что у меня с вашим последним кодом
Миниатюры
Добавить значение в конец динамического массива (имитация функции вектора)  
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 15:29     Добавить значение в конец динамического массива (имитация функции вектора) #15
ужас какой, возможно дело в том что делаем delete tmp, мой компилятор мусором не забрасывает ,а у вас бросает, получается delete P можем оставить но вот после строки *P=tmp tmp удалять нельзя так как получается что мы удалим и все содержимое P. мойже компилятор наоборот ругался на удаление Р а тмп удалять разрешает
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 15:37  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #16
У меня Visual Studio 2005
У вас очевидно новее, поэтому каким-то макаром может исправлять возникающий недочет.

Но, думаю, согласитесь, что сменить компилятор не выход. Если есть проблема, лучше понять почему она возникает.
Надеюсь выход найдется. В любом случае решение есть и наверняка оно до безобразия просто.
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 15:42     Добавить значение в конец динамического массива (имитация функции вектора) #17
у меня совсем не VS ,да вы правы я сам плохо понимаю освобождение памяти, сижу разбираюсь)
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 17:40  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #18
Решил)))
Но почему так выходило не понял всё равно


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
#include <iostream>
using namespace std;
 
void show(int **P,int &N)  //Показываю
{
 for (int i=0;i<N-1;i++) cout<<(*P)[i]<<"  ";
 cout<<endl;
}
 
 
void create(int **P, int &N) //Создаю
{
 *P=new int[N]; // Выделяю память
 for (int i=0;i<N;i++) (*P)[i]=i+1;// Заполняю по порядку
}
 
void Add(int **P,int &N, int x) //Добавляю одно значение в конец массива
{ 
  int *temp=new int[N]; //Выделяю новую память
  for (int i=0;i<N;i++) temp[i]=(*P)[i]; //Записываю туда данные
  delete [](*P); //вот так освобождаю массив, принятый функцией
 
  *P=new int[N+1]; //Выделяю для массива, принятой функцией новую память
  for (int i=0;i<N;i++) (*P)[i]=temp[i];//Записываю в массив значения из временного массива
  (*P)[N-1]=x; //Записываю новое значение в самый конец
 N++; //Увеличиваю число элементов
delete []temp; //освобождаю память от временного массива
}
 
 
void main()
{
 
 int *P=NULL;
 int N=0;
 cin>>N;
 
 
 create(&P,N); //Создал
 show(&P,N); //Показал исходный
 
 for (int i=0;i<100;i++) //Тест добавлений с помощью цикла
 {
 Add(&P,N,i+2); //Добавил один элемент
 show(&P,N); //Показал результат
 }
 delete []P; //Освободил память
 
}
Nixy, В принципе это ваш подход, только код мой. Спасибо за помощь. Интересно, будет ли работать в вашем компиляторе, а-то кто знает. Может обратная ситуация возникает.

Хотелось бы увидеть код попроще.
Nixy
ComfyMobile
400 / 281 / 8
Регистрация: 24.07.2012
Сообщений: 916
09.12.2012, 17:51     Добавить значение в конец динамического массива (имитация функции вектора) #19
работает и у меня, вся суть в этих строках
C++
1
2
3
delete [](*P); //вот так освобождаю массив, принятый функцией
 
  *P=new int[N+1]; //Выделяю для массива, принятой функцией новую память
как вы к ним пришли? озаренее свыше ,или кто подсказал?
даже не в 2 а в одной имено вот в 1 , если правильно удалять Р
C++
1
2
3
4
5
6
7
8
9
10
11
12
void add(int**P,int &N,int x)
{
  N++;
  int *temp=new int[N];
  for (int i = 0; i < N-1; i++) {
     temp[i]=(*P)[i];
  }
  temp[N-1]=x;
  show(&temp,N);
  delete [](*P);
  *P=temp;
}
вот так тоже работает и меньше промежуточных действий
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.12.2012, 18:23     Добавить значение в конец динамического массива (имитация функции вектора)
Еще ссылки по теме:

В конец массива b добавить максимальные элементы всех строк массива a C++
Как добавить элемент в конец массива и расширить его на одну позицию? C++
C++ Почему при создании динамического массива через new ячейки массива имеют значение -842150451?
Как прочесть несколько слов из файла в динамический массив char и добавить новое значение в конец? C++
Добавление элемента в конец динамического массива! C++

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

Или воспользуйтесь поиском по форуму:
daslex
1256 / 501 / 103
Регистрация: 02.08.2011
Сообщений: 2,514
09.12.2012, 18:23  [ТС]     Добавить значение в конец динамического массива (имитация функции вектора) #20
Может кто не поверит - сам.
Маленький опыт есть. Делал блог (там теория C++ 3.1 dos) -пока блог делал, получил чуть-чуть знаний. Дальше методом проб миллиона догадок удалось подобрать))

Добавлено через 25 минут
Цитата Сообщение от Nixy Посмотреть сообщение
вот так тоже работает и меньше промежуточных действий
Что-то мне кажется, что так неправильно и высокая вероятность сбоя.
Yandex
Объявления
09.12.2012, 18:23     Добавить значение в конец динамического массива (имитация функции вектора)
Ответ Создать тему
Опции темы

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