Ru-MaNGOS

Ru-MaNGOS (http://mangos.ytdb.ru/index.php)
-   Новичкам (http://mangos.ytdb.ru/forumdisplay.php?f=40)
-   -   Динамические массивы в С++ (http://mangos.ytdb.ru/showthread.php?t=6549)

lovepsone 26.12.2012 13:01

Динамические массивы в С++
 
Нужна помощь и пояснения!
Вот мой говнокод:
Код:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <ctime> // для time
#include <cstdlib> // для srand

int main()
{
        //std::srand(static_cast<unsigned int>(std::time(0)));
        setlocale(LC_ALL, "rus");
        int m,n;
        printf("Введите размерность массива:\n"
                        "Кол-во строк = ");

        std::scanf("%d",&n);
        printf("Кол-во столбцов = ");
        std::scanf("%d",&m);

        int** mas = new int*[n];

        for (int i = 0; i < m; i++)
                mas[i] = new int[m];

        for (int i = 0; i < n; i++)
        {
                for(int j = 0; j < m; j++)
                        mas[i,j] = (int*)(40 - (std::rand() % 31));
        }

        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < m; j++)
                        printf("%d ", mas[i,j]);
                printf("\n");
        }

        for (int i = 0; i < m; i++)
                delete mas[i]; // вот тут ошибка
        delete [] mas;

        system("pause");
        return 0;
}

При освобождении памяти происходит ошибка!
Компилю в 10 визуалке;

Vladimir 26.12.2012 16:03

Код:

for (int i = 0; i < m; i++)
delete mas[i]; // вот тут ошибка

почему m если при создании
int** mas = new int*[n];

lovepsone 26.12.2012 16:24

Цитата:

Сообщение от Vladimir (Сообщение 30233)
Код:

for (int i = 0; i < m; i++)
delete mas[i]; // вот тут ошибка

почему m если при создании
int** mas = new int*[n];

Вроде мы сразу освобождаем колонки (чтобы освободить память необходимо выполнить цикл для освобождения одномерных массивов), а потом строки. Или нет?
Даже если заменить на переменную n, все ровно происходит ошибка кучи, типо куча повреждена!

И еще вопрос: как заполнить матрицу, что бы строки не повторялись? Я попробовал использовать srand(), но толку ноль!

Йоха 28.12.2012 12:41

В современном состоянии языка с++ использовать в прикладных целях голые указатели - моветон!

В данном случае нужно использовать std::vector

Твою программу можно переписать например так:
Код:

#include <conio.h>
#include <iostream>
#include <iomanip>
#include <vector>

int _tmain(int argc, _TCHAR* argv[])
{
        std::vector<std::vector<int>> mas;
        int n, m;
        std::cout << "Enter array size - n m : " << std::endl;
        std::cin >> n >> m;

        srand((unsigned int)time(NULL));
        for (int i = 0; i < n; i++) {
                std::vector<int> tmp;
                for(int j = 0; j < m; j++)
                        tmp.push_back(40 - rand() % 31);
                mas.push_back(tmp);
        }

        for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++)
                        std::cout << std::setw(4) << mas[i][j];
                std::cout << std::endl;
        }

        _getch();
        return 0;
}

Или такой вариант заполнения матрицы без использования временных переменных:
Код:

        srand((unsigned int)time(NULL));
        mas.resize(n);
        for (int i = 0; i < n; i++) {
                mas[i].resize(m);
                for (int j = 0; j < m; j++)
                        mas[i][j] = 40 - rand() % 31;
        }

А по поводу твоей программы - это просто тихий ужас!

Ошибка №1
Код:

int** mas = new int*[n];
for (int i = 0; i < m; i++)
mas[i] = new int[m];

У тебя выделен массив длиной n, а заполняешь его ты в цикле по m !

Ошибка №2
Код:

mas[i,j] = (int*)(40 - (std::rand() % 31));
Обращение к двумерным массивам в с++ пишеттся как mas[i][j].
То что написал ты - это вызов оператора запятая.
Собственно этот код эквивалентен следующему:
Код:

mas[j] = (int*)(40 - (std::rand() % 31));
Потом, тут само присвоение неправильно, ты на место указателя записываешь число.

Ошибка №3
Код:

for (int i = 0; i < m; i++)
delete mas[i]; // вот тут ошибка

Ты выделял память под массив, а удаляешь как одну переменную.
Надо писать delete[] mas[i];
Ну и как уже заметили, цикл идет по m, хотя массив длиной n.

Ну с учетом всех косяком, исправил твою прогу:
Код:

int main()
{
        srand((unsigned int)(time(NULL)));
        setlocale(LC_ALL, "rus");
        int m,n;
        printf("Введите размерность массива:\nКол-во строк = ");
        scanf_s("%d",&n);
        printf("Кол-во столбцов = ");
        scanf_s("%d",&m);

        int** mas = new int*[n];
        for (int i = 0; i < n; i++)
                mas[i] = new int[m];

        for (int i = 0; i < n; i++)
                for(int j = 0; j < m; j++)
                        mas[i][j] = 40 - rand() % 31;

        for (int i = 0; i < n; i++) {
                for(int j = 0; j < m; j++)
                        printf("%d ", mas[i][j]);
                printf("\n");
        }

        for (int i = 0; i < n; i++)
                delete[] mas[i];
        delete[] mas;
        return 0;
}

Все работает как и ожидается.

И напоследок, у тебя в программе смесь языков С и С++, все этим пережитки прошлого в виде printf и scanf... У С++ есть iostream для ввода вывода

lovepsone 28.12.2012 18:42

Спасибо за все. В моем случаи использовать вектор не надо.
Цитата:

Сообщение от Йоха (Сообщение 30264)
И напоследок, у тебя в программе смесь языков С и С++, все этим пережитки прошлого в виде printf и scanf... У С++ есть iostream для ввода вывода

Вы имеете ввиду std::cin и std::cout? В ошибке №2 описался и не заметил(просто скомпилилось)...
Разберу код который вы написали и все осмыслю...

П.С.
Я тока изучаю с++

Йоха 29.12.2012 08:25

Цитата:

Сообщение от lovepsone (Сообщение 30271)
В моем случаи использовать вектор не надо.

Это обязательное условие задачи - не использовать vector ? Если так то ок, иначе настоятельно рекомендую не использовать new и delete, для указателей - смарт поинтеры, для динамических массивов vector или подобное (list, deque ... в зависимости от условий задачи)

Цитата:

Сообщение от lovepsone (Сообщение 30271)
В ошибке №2 описался и не заметил(просто скомпилилось)...

К несчастью в с++ полно возможностей описаться, при этом с точки зрения компилятора код будет корректным, но работать это все будет совсем не так как задумывалось.

Кстати еще насчет динамических массивов: двумерный массив размерностью m на n можно создать так :
Код:

int *mas = new int[m * n];
и дальше использовать как обычно:
Код:

mas[i][j] = 1;

lovepsone 29.12.2012 10:07

Цитата:

Сообщение от Йоха (Сообщение 30273)
Кстати еще насчет динамических массивов: двумерный массив размерностью m на n можно создать так :
Код:

int *mas = new int[m * n];
и дальше использовать как обычно:
Код:

mas[i][j] = 1;

Попробуем использовать....


Текущее время: 16:20. Часовой пояс GMT +3.

ru-mangos.ru - Русское сообщество MaNGOS