Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Двумерный массив. Совпадение строки и столбца, и сумма строки с отрицательным элементом 
V
    Опции темы
baldina
Дата 11.7.2011, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(voral @  11.7.2011,  14:21 Найти цитируемый пост)
Ты сделал свои обертки для malloc и free.  Желательно их вызывать (для одной области) в  рамках однной функции - в которой живет переменная хранящая адрес.

сделав обертки, мы получили те же самые malloc и free, концептуально ничего нового.
в вопросах управления ресурсами, в т.ч. памятью, важно понятие владельца. именно владелец отвечает за своевременное удаление объекта (освобождение ресурса). выделение ресурса может происходить вне владельца, важно, что бы сразу после выделения установить владельца.
на примере умных указателей:
Код

auto_ptr<int> my_ptr (new int);

здесь выделение ресурса происходит вне владельца - переменной my_ptr, но владелец устанавливается сразу. освобождение памяти произойдет, кода закончится время жизни my_ptr. если между выделением ресурса и установкой владельца что-то происходит
Код

int *ptr = new int;
.... // тут еще какой-то код
auto_ptr<int> my_ptr (ptr);

есть вероятность возникновения исключения, тогда память не будет освобождена.
PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



   В общих чертах я это понимаю. Теорию из книги прочитал, теперь пытаюсь перенести теорию на практику. 
   Если я вас правильно понял, мне не нужно освобождать память по окончанию выполнения функции, т.к. локальная переменная сама сотрется при выходе из функции? 

   Хорошо, тогда правильно ли я вызываю функцию динамического распределения памяти? Внутри функции, которая оперирует интересующими меня переменными я вызываю функцию выделения памяти, т.е. всё верно? Потому что я сомневался, может я в мейне должен вызвать функцию malloc(inMemory) перед началом выполнения двух других функций, но это получается нелогичным, т.к. память выделиться на все последующие функции и захламится мусором этих самых функций и при этом не произойдет очистки памяти. Верно?
PM MAIL   Вверх
baldina
Дата 11.7.2011, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Kruger2, тут какая-то каша в коде.
давай вернемся к задаче. требуется написать управление памятью и доступом для квадратной матрицы.
определим операции
1. создать матрицу порядка N
2. получить доступ (для чтения или установки значения) к элементу (i,j) матрицы
3. освободить занимаемую матрицей память

пусть у нас будет
Код

struct matrix {...}; // матрица
void create_matrix (matrix*, int n); // функция инициализации матрицы и выделения памяти
void destroy_matrix (matrix*); // функция освобождения памяти
int get_m (const matrix*, int i, int j); // функция получения значения элемента 
void set_m (matrix*, int i, int j, int value); // функция установки значения элемента 

предлагаю структуру сделать такой:
Код

struct matrix {
  int size;
  int *data;
}; 

тогда data должен указывать на память размером size*size, а элемент (i,j) в data находится по индексу i*size+j
остальное, думаю, сам реализуешь.
ЗЫ: с использованием классов это можно сделать намного изящнее

Добавлено через 3 минуты и 14 секунд
Цитата(Kruger2 @  11.7.2011,  15:12 Найти цитируемый пост)
 правильно ли я вызываю функцию динамического распределения памяти

совсем не вызываешь
Цитата(Kruger2 @  11.7.2011,  14:52 Найти цитируемый пост)
      void inMemory(int** b);

это не вызов, а объявление

PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Цитата(baldina @  11.7.2011,  15:17 Найти цитируемый пост)
остальное, думаю, сам реализуешь.


Это зря, структуры не изучал ещё.

Совершенно непонял
Цитата(baldina @  11.7.2011,  15:17 Найти цитируемый пост)
struct matrix {...}; // матрица
void create_matrix (matrix*, int n); // функция инициализации матрицы и выделения памяти
void destroy_matrix (matrix*); // функция освобождения памяти
int get_m (const matrix*, int i, int j); // функция получения значения элемента 
void set_m (matrix*, int i, int j, int value); 


Матрица у меня уже есть, зачем мне её ещё раз создавать, зачем мне функция получения значения элемента?

Брр, стало только хуже. Я хоть немного понимал, что я и как делаю. У меня была задача состоящая из двух функций, по идее мне достаточно было выделить память под эти две функции, что бы решить новое задание. Но теперь весь код каша? А в каком месте то каша? сейчас есть 4 функции, 2 из них решают основное задание, а 2 другие это выделение памяти и очистка. Вроде до каши ещё далеко  smile 
PM MAIL   Вверх
baldina
Дата 11.7.2011, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(Kruger2 @  11.7.2011,  15:12 Найти цитируемый пост)
локальная переменная сама сотрется при выходе из функции? 

локальная сотрется, а то что было выделено при помощи malloc - нет.
что бы динамическое распределение происходило так же просто и естественно, как это делается для локальных переменных, потредуется класс, в конструкторе которого выделяешь память, а в деструкторе освобождаешь.
Код

struct my {
  int *ptr;
  my () { ptr = new int[10]; }
 ~my () { delete [] ptr; }
};

int main ()
{
   my m; // здесь вызывается конструктор, память выделяется


  // <- здесь (неявно) вызывается деструктор, память освобождается
}


Добавлено через 4 минуты и 52 секунды
Цитата(Kruger2 @  11.7.2011,  15:22 Найти цитируемый пост)
Матрица у меня уже есть, зачем мне её ещё раз создавать, зачем мне функция получения значения элемента?

ок, зайдем с другого конца. 
вот зачем:
что бы разделить задачу на части, упростить её. сейчас имеешь сотню строк кода, сильно связанного между собой.
а будешь иметь ту же сотню, но в отдельных функциях, каждая - неск. строк, совершенно независимых.
допустим, структуры еще не изучал. классы тем более. давай обойдемся тем что есть.

1. вместо структуры будем использовать две переменные - указатель на выделяемую память и порядок матрицы.
я предлагаю использовать одномерный массив для матрицы. это гораздо проще в выделении памяти, а лдя доступа будем использовать очень простую функцию

Это сообщение отредактировал(а) baldina - 11.7.2011, 15:27
PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Неужели нельзя в рамках моей программы выделить память, без подключения структур? Я до них ещё не добрался.
Цитата(baldina @  11.7.2011,  15:17 Найти цитируемый пост)
Цитата(Kruger2 @  11.7.2011,  14:52 )
      void inMemory(int** b);

это не вызов, а объявление


Мда, тут вызвать никак не получается 

При попытке вызвать функцию посредством

 inMemory (b) пишет   expected primary-expression before ')' token, 
что за праймери экспрешен?(
PM MAIL   Вверх
baldina
Дата 11.7.2011, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Код

int *matrix;
int size;

int get_m (int i, int j) { return matrix[i*size+j]; }
void set_m (int i, int j, int value) { matrix[i*size+j] = value; }
void create_matrix (int n) { size = n; matrix = malloc (size*size); }
void destroy_matrix () { size=0; free (matrix); }

посмотри что получилось: теперь все операции с матрицей мы можем осуществлять через эти (очень простые) функции.
можешь добавить проверки выхода индексов за границы.
можешь добавить отладочную печать.
на вызывающий код это не повлияет.

Добавлено через 1 минуту и 28 секунд
Цитата(Kruger2 @  11.7.2011,  15:35 Найти цитируемый пост)
 inMemory (b) пишет   expected primary-expression before ')' token, 

ну вообще-то у тебя в программе b определена как int, а inMemory требует int**
PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



даже функцию блин вызвать не могу)
PM MAIL   Вверх
baldina
Дата 11.7.2011, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Kruger2, тут две проблемы: пока ты не очень ориентируешься в языке и стараешься решить задачу целиком. первое подтянешь, со вторым я тебе сейчас помогаю.
PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Мы будто говорим каждый сам с собойsmile Всё это прекрасно и я благодарен, но я не понимаю как мне это реализовать в рамках моего задания. Зачем там создается матрица, когда она у меня есть и так?

Меня интересует в первую очередь два вопроса. Верны ли сами функции inMemory и freeMemory и будет ли верным такой вызов?

Код

void compareLine(int i)
{
    int j;
    int** b;
    int** c;
     inMemory(b);
    for (j=0;j<SIZE;++j)
        if (A[i][j]!=A[j][i])
            return;
    printf("K=%d\n",i+1);
       freeMemory(c);
}


Добавлено через 1 минуту и 59 секунд
baldina
Да я вроде литературу читаю, простые задачи решаю, но как то ориентироваться лучше не начинаю. Хоть бери об стенку убейся, как только появляется задание выходящее за рамки того что описано в книге, я словно пытаюсь по китайски заговорить:*(

Добавлено через 6 минут и 14 секунд
Вообщем то тоже неверно, программа рушится

Добавлено через 7 минут и 59 секунд
Цитата(baldina @  11.7.2011,  15:26 Найти цитируемый пост)
я предлагаю использовать одномерный массив для матрицы

Но у меня то двумерная матрица

Добавлено через 14 минут и 34 секунды
Ладно. Пробую разобраться:

Код

int *matrix;
int size;

int get_m (int i, int j) { return matrix[i*size+j]; }
void set_m (int i, int j, int value) { matrix[i*size+j] = value; }
void create_matrix (int n) { size = n; matrix = malloc (size*size); }
void destroy_matrix () { size=0; free (matrix); }


get_m помоему все таки лишняя, разве нет? у меня ведь объявлена матрица, получается я работаю не с ней, а с той что тут будет создана
void_st //функция установки значения элемента, вообще не понимаю что за установка значения. мы же не рандомную матрицу создаем.
create matrix создает одномерный массив, тут кажись вся моя функция с проверкой должна подходить, нет? 
Код

 Array = (int **)malloc(SIZE*sizeof(int* ));
         if(!Array) 
     {
       printf("Memory not allocated. \n");
      return;
     }
     int i;
     for (i=0; i< SIZE; i++)
     {
       Array[i]= (int *) malloc(SIZE*sizeof (int ));
       if (!Array[i])
       {
         printf("Memory not allocated2 \n");
         return;
       }
     }


а destroy_matrix вроде как должна подходить моя же функция?
PM MAIL   Вверх
baldina
Дата 11.7.2011, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(Kruger2 @  11.7.2011,  15:44 Найти цитируемый пост)
моя функция с проверкой должна подходить

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

по порядку.
1. что такое многомерный массив в С/С++? это одномерный массив, строки которого расположены последовательно в памяти (ничего необычного, ведь компьютерная память одномерная). Именно такое расположение я и предлагаю. Это проще для восприятия, чем "массив массивов".
2. неважно, что как расположено. мы пользуемся определенным интерфейсом - функциями create, get, set... Этот подход нам позволяет в процессе решения конкретной задачи не вникать в устройство массива, а в процессе проектирования интерфейсных функций не думать о всей задаче. поэтому get_m не лишняя. технически можно без нее обойтись, можно вообще все написать в единственной функции и в одну строчку, но с точки зрения грамотного проектирования и удобства использования она нужна.
3. 
Цитата(Kruger2 @  11.7.2011,  15:44 Найти цитируемый пост)
кажись вся моя функция с проверкой должна подходить

ну поскольку она в итоге вызывает тот же malloc, то примерно да. точнее, если взять мою функцию и добавить туда проверки и сообщения, будет 'правильная' версия Kruger2
теперь рассмотрим 
Код

void inMemory (int** Array)
{
Array = (int **)malloc(SIZE*sizeof(int* ));
         if(!Array) 
     {
       printf("Memory not allocated. \n");
      return;
     }
     int i;
     for (i=0; i< SIZE; i++)
     {
       Array[i]= (int *) malloc(SIZE*sizeof (int ));
       if (!Array[i])
       {
         printf("Memory not allocated2 \n");
         return;
       }
     }

здесь есть две основные проблемы
1. параметры в С/С++ передаются по значению, поэтому если нужно инициализировать int**, то передавать приходится int***
Код

void inMemory (int*** Array)
{
  *Array = (int **)malloc(SIZE*sizeof(int* ));
  ...

2. К выделенному таким образом массиву нельзя обращаться A[i][j], т.к. элементы массива теперь не расположены последовательно.
нужно так: (A[i])[j];
уже не так красиво, как раньше, правда?  

PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Всё равно ни черта не понимаю. Пойду ещё искать литературу.

Добавлено через 7 минут и 24 секунды
Вот я копировал отсюда, немнго меняя под себя. получается тут неправильный код выложили?)

Код

/*   allocate2D
/*   function to dynamically allocate 2-dimensional array using malloc.
/*
/*   accepts an int** as the "array" to be allocated, and the number of rows and
/*   columns.
*/
void allocate2D(int** array, int nrows, int ncols) {
     
     /*  allocate array of pointers  */
     array = ( int** )malloc( nrows*sizeof( int* ) );
     
     /*  allocate each row  */
     int i;
     for(i = 0; i < nrows; i++) {
          array[i] = ( int* )malloc( ncols*sizeof( int ) );
     }

}

/*   deallocate2D
/*   corresponding function to dynamically deallocate 2-dimensional array using 
/*   malloc.
/*
/*   accepts an int** as the "array" to be allocated, and the number of rows.  
/*   as with all dynamic memory allocation, failure to free malloc'ed memory
/*   will result in memory leaks
*/
void deallocate2D(int** array, int nrows) {
     
     /*  deallocate each row  */
     int i;
     for(i = 0; i < nrows; i++) {
          free(array[i]);
     }
     
     /*  deallocate array of pointers  */
     free(array);
     
}

/*   EXAMPLE USAGE:    
int** array1;

allocate2D(array1,1000,1000); //allocates a 1000x1000 array of ints

deallocate2D(array1,1000);    //deallocates the same array
*/

PM MAIL   Вверх
baldina
Дата 11.7.2011, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Kruger2, есть простой выход. вообще он не очень хороший, но в данном случае наверно лучший.
сделай 
Код

  int (*A)[SIZE];
  A = (int (*)[SIZE])malloc (SIZE*SIZE);
и обращайся A[i][j] Более сложное попробуешь, когда почитаешь
PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Код

void inMemory (int (*Array)[SIZE])
{
    
         Array = (int (*)[SIZE])malloc(SIZE*SIZE);
         if(!Array) 
     {
       printf("Memory not allocated. \n");
      return;
     }
    }



так?
PM MAIL   Вверх
voral
Дата 11.7.2011, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Цитата(Kruger2 @  11.7.2011,  14:35 Найти цитируемый пост)
Т.е. мне надо вызвать функцию малок внутри каждой из моих двух функций или вызвать её в мейне перед выполнением двух других функций?

Во первых вы ни как не используете эту память, по-этому я не могу сказать где вам надо. В данном случае правильный ответ: "нигде ни выделять ни освобождать".

Во вторых у вас все неправильно. Давайте прочитаем по русски этот код:
Код

      int b, c;
      void inMemory(int** b);
....
      void freeMemory(int** c);

обявляем две переменные типа int.
пытаемся объявить (не вызвать) функцию, которая в качестве аргумента принимает указатель на указатель на переменную типа int
пытаемся объявить (не вызвать) функцию, которая в качестве аргумента принимает указатель на указатель на переменную типа int

Все не более.
Отбрасываем ошибку, с попыткой объявить функцию
Код

      int b, c;
      inMemory(b);
....
      freeMemory(c);

Опять не увязка:
1 ваша процедура ждет указатель на указатуль......
2 Места для переменных типа int уже зарезервированы, и нет смысла выделять память (а еслибы все же нужно было то надо было писать "&b"
Правим
Код

      int **b, **c;
      inMemory(b);
....
      freeMemory(c);

Теперь все, вроде так. Но! Вызывая inMemory(b) ; вы в конечном итоге инициализируете переменную b, адресом массива указателй
переменная c при этом неинициализирована! А вы хотите освободить память по адресу хранящемуся в этой переменной!!! Ноона ни чего не содержит!
Еще раз правим.
Код

      int **b = NULL;
      inMemory(b);
....
      freeMemory(b);


Вот теперь вы память выделили, а потом освободили. Осталось придумать зачем она вам тут сдалась... В данной задаче единственное применение для этих функций. Зарезервировать место под матрицу; заполнить ее программно (сейчас у нас это константа); найти решение; освободить память.. Т.е. по сути, это должно быть в main


Цитата(Kruger2 @  11.7.2011,  14:35 Найти цитируемый пост)
и получается освобождать память тоже не надо, т.к. нет глобальных переменных ?

Если вы где то зарезервировали память, то вы обязаны ее освободить - иначе "утечка памяти". То, о чем я вам говори касается лишь освобождения памяти под автоматическую переменную хранящую адрес выделенной вами памяти.

Это сообщение отредактировал(а) voral - 11.7.2011, 17:34
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0782 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.