Динамическое выделение памяти

Уровень сложности:

Задача на динамическое выделение памяти. Изначально есть указатель на массив с одним элементом. Пользователь вводит число. Если оно больше 0 записываем его в массив. Далее пользователь вводит второе число, тут уже,  если оно больше 0, надо пере выделять память для 2-х элементов массива и записать в массив второе число. И так далее…  для 3-х элементов, для 4-х…  пока пользователь не введет отрицательное число.

Пример работы программы:

Исходный код программы показан ниже:

#include <iostream>

using namespace std;

int main()
{
    setlocale(LC_ALL, "rus");  

    int *p = new int[1];
    int *p2;//для копирования данных из массива p перед удалением памяти
    int a = 0;//число, которое вводит пользователь
    int nSize = 0;//размер динамического массива, который будет увеличиваться на 1, при вводе положительного числа

    while(a >= 0){

        cout << "\nВведите целое число: ";
        cin >> a;

        if(a < 0){
            break;//если введено отрицательное число - break
        }

        if(nSize == 0)
        {
            p[nSize] = a;
            cout << p[nSize];
            nSize++;//1
        }
        else
        {
            p2 = new int [nSize + 1];
            for(int i = 0; i < nSize; i++)
            {
                p2[i] = p[i];//скопировали массив          
            }
            p2[nSize] = a;

            delete [] p; //чистим память

            p = new int[nSize + 1]; //выделяем новую память                    

            for(int i = 0; i < (nSize+1); i++)
            {
                p[i] = p2[i]; //копируем данные из временного массива
                cout << p[i] << " ";//и отображаем все его элементы на экран
            }  
            delete [] p2;//чистим память временного массива

            nSize++;//увеличиваем на 1
        }      
    }

        delete [] p;//чистим память перед завершением программы
    return 0;
}


Смотрим результат работы программы:

CppStudio.com
Введите целое число: 3
3
Введите целое число: 4
3 4 
Введите целое число: 5
3 4 5 
Введите целое число: 6
3 4 5 6 
Введите целое число: 7
3 4 5 6 7 
Введите целое число: 8
3 4 5 6 7 8 
Введите целое число: 5
3 4 5 6 7 8 5 
Введите целое число: 4
3 4 5 6 7 8 5 4 
Введите целое число: 0
3 4 5 6 7 8 5 4 0 
Введите целое число: 0
3 4 5 6 7 8 5 4 0 0 
Введите целое число: 7
3 4 5 6 7 8 5 4 0 0 7 
Введите целое число: -1
Следующие статьи помогут вам в решении данной задачи:
Автор: Marienko L.
Дата: 12.01.2014
Поделиться:

Комментарии

  1. Lee Amstrong

    Вот. Запилил без копирования памяти (за некоторыми оговорками). Кратко опишу как работает. Выделяем кусок памяти n-байт, столько, что бы хватило для одного числа. При записи, проверяем, если наш кусочек заполнен, то выделяем еще.
    В чем отличие от метода, который приведен в решении. Там, если закончилось место, то выделяется новый массив, а старый копируется туда, что как бы некоторые накладные расходы. В моем же методе, если место закончилось то к уже выделенному кусочку довыделяется еще память (по типу откусывания кусочков от палки).

    Оговорка заключается в том, что если за нашей памятью память, используемая кем-то другим, или даже другим элементом нашей программы (скажем там, палку откусил кто-то другой), то идет все таки копирование в новую область памяти, но это уже забота ОС.

    #include <iostream>
    #include <cstdlib>
    #include <assert.h>
    #include <limits>
    
    int main(int argc, char const *argv[]) {
       //выделяем память для 1-го инта
       void* memory = malloc(sizeof(int));
       assert(memory); //Кидаем исколючение если не удалось выделить память
       size_t capacity = 1; //вместительность выделенного кусочка памяти
       size_t elements = 0; //Количество элементов на нашем кусочке
    
       while (true) {
          int num;
          std::cout << "Введите число: ";
          std::cin >> num;
          //сработает, если мы попытаемся ввести буквы, вместо числа, или число которое не поместится в int
          if (std::cin.fail()) {
             std::cout << "Шота сломалось :(" << '\n';
             break;
          }
          if (num < 0) {
             break;
          }
          if (capacity == elements) {
             capacity++;
             //Временный указатель, по предупреждению анализатора pvs-Studio:
             // V701 realloc() possible leak: when realloc() fails in allocating memory,
             //original pointer 'memory' is lost. Consider assigning realloc() to a temporary pointer.
             void* tempPtr = realloc(memory, sizeof(int)*capacity); //++capasity вначале увеличит свое значение, а потом уже пойдет в функцию
             assert(tempPtr); //То же, что и 1й ассерт
             memory = tempPtr;
          }
          //Приводим к типу int, для дальнейшей записи в него числа
          int* int_memory = reinterpret_cast<int*>(memory);
    
          int_memory[elements] = num;
          elements++;
          std::cout << "Записанные числа: ";
          for (size_t i = 0; i < elements; i++) {
             std::cout << int_memory[i] << " ";
          }
          std::cout << '\n';
          std::cout << "Кусочек памяти занимает: " << sizeof(int) * capacity << " байт\n";
       }
       //Освобождаем память
       free(memory);
       return 0;
    }

    А еще я так и не понял как пофиксить предупреждение статического анализатора, но вроде все работает:

    <code class="cpp hljs">↑ <a href="https://www.viva64.com/en/w/V522/" target="_blank">V522</a> There might be dereferencing of a potential null pointer 'int_memory'. Check lines: 39, 10.</code>
  2. Alexander Trousevich

    // Language: rust. Details: rust-lang.org
    
    
    use std::io;
    
    fn read_integer() -> u32 {
        let mut buf: String = String::new();
        io::stdin().read_line(&mut buf).expect("Invalid Input");
        buf.trim().parse().expect("Not a number")
    }
    
    fn main() {
        let mut ans: Vec<u32> = Vec::new();
        loop {
            let n = read_integer();
            match n {
                0 => break,
                _ => ans.push(n)
            }
        }
        for i in ans {
            println!("{}", i)
        }
    }
  3. Alex Pir

    Ребят помогите плиз у меня проблема из чисткой памяти, вот код (Не судите строго ,я только начинающий Вот код):

    #include <iostream>
    using namespace std;
    
    int main()
    
    {
    	int size = 1;
    	int *arr = new int[size] {};
    	int *arr2 = new int[size + 1];
    	int a;
    	cin >> a;
    	for (int l = 0; a >= 0; l++)
    	{
    		
    		cout << "Enter value: ";
    		cin >> a;
    		cout << "Array: ";
    		for (int i = 0; i < size + l; i++)
    		{
    
    			arr2[i] = arr[i];
    			arr2[l] = a;
    			arr[i] = arr2[i];
    			cout << arr2[i] << "\t";
    
    		}
    			cout << endl;
    	}
    
    	
    }
    
    

     

  4. Программист

    Dentchik 2016(Just Do it)

    Просто и доступно  , просто если бы обявили

    int arr[1];//то получили бы мусор в ячейках с индексом > 0
    #include<bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        int* arr = new int[1];
        int cur , raz = 0;
        do
        {
            cin >> cur;
            if(cur >= 0)
            {
                arr[raz] = cur;
                raz++;
            }
            
        }while(cur >= 0);
        for(int i = 0;i < raz;i++)
            cout << arr[i] << " ";
        delete [] arr;
    }
    • Gosha

      Многие тут допускают одну и туже ошибку.
      Динамическая память не означает, что она резиновая. Сколько выделили через new, таким размером и можно пользоваться.
      За границами выделенных адресов под массив, могут находится другие данные, при затирании которых, программа перестанет работать.
      Просто такая программа слишком примитивна и в ней мало данных, поэтому эта проблема не проявляется, и кажется что программа работает корректно.
      Чтобы увеличить динамический массив на один элемент его нужно удалить, а потом выделить заново память на один элемент больше.
      Естественно перед удалением данные надо куда-то сохранить, а это приводит к необходимости завести еще один динамический буферный массив,  в этом и есть смысл задачи.
      Т.е. те у кого один динамический массив сразу уже не в теме.

  5. Eduard_P

    Eduard_P

    Решение несложное, комментарии писались дольше чем сам код.

    Заняло 30мин.

    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    /*
     * 
     */
    int main(int argc, char** argv) {
        int*array;//основной массив
        int*array1;//вспомогательный массив
        int n=1, i, j;
        for(i=0; i<n; i++){ //основной цикл
            array = new int[n];//декларация основного массива
            for(j=0; j<n; j++) {*(array+j)=*(array1+j);}//копирование данных с воспом. в основнай
            if(i>0){delete array1;}//удаление  вспомогательного массива начиная со второг цикла
            array1 = new int[n];//декларация вспомогательного массива
            cout << "Введите целое число: ";//вывод на экран запроса
            cin >> *(array+i);//ввод пользователем данных
            if (*(array+i)>=0){//остановка вывода массива при отрицательном вводе
                for (j=0; j<n; j++){ cout << *(array+j) << " ";}//вывод данных основного массива
            }
            cout << "\n";//перевод строки
            if (*(array+i)>=0) n++;//прибавление цикла в случае положит числа
            for(j=0; j<n; j++) {*(array1+j)=*(array+j);}//копирование данных с основного в воспомог. массив
            delete array;//удаление основного массива
        }
        delete array1;
    
        return 0;
    }
    
    
  6. fishb0ne

    #include <iostream>
    #include <cstdlib>
    
    int main()
    {
        int *vect = (int *) malloc(1), num, count = 0;
        do
        {
            count++;
            std::cout<<"\nВведите целое число: ";
            std::cin>>num;
            if (num > 0)
            {
                realloc(vect,count * sizeof(int));
                vect[count-1] = num;
            }
            else count--;
            for (int i = 0; i < count; i++)
                std::cout<<vect[i] << " ";
        } while (num >= 0);
        free(vect);
        return 0;
    }

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.