| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Двумерный массив. Совпадение строки и столбца |
| Автор: Kruger2 30.6.2011, 14:11 | ||
| Для заданной матрицы размером 8 на 8 найти такие k, что k-я строка матрицы совпадает с k-м столбцом. Найти сумму элементов в тех строках, которые содержат хотя бы один отрицательный элемент. По первой части проблема в том, что он мне всегда выводит последнюю строку, даже если там нет совпадений. Я так понимаю, что не хватает проверки на ложность или на выход из массива? Но пытался вписать else и прога перестала работать вообще. По всей проге вопрос такой: он мне считает все элементы начиная с 0 (как и полагается в массиве), но когда я пытаюсь сдвинуть цикл for (i=1; i=N-1; i++) всё рушится :( И третий вопрос нафига тут flag? Без него прога не работала, я просто нагло скопировал часть с флагом и поэтому не врубаюсь фигли без него не работает.
|
| Автор: Kruger2 30.6.2011, 15:27 |
| baldina Начал писать и придумал как решить проблему Инициализировал flag нулем, но ничего не изменилось. Всегда выдает, что есть совпадение в последней строке. |
| Автор: baldina 30.6.2011, 15:38 |
а в действительности нет совпадения? |
| Автор: Kruger2 30.6.2011, 15:40 |
| Нет. Бывают совпадения в других строках. А последнюю выводит всегда, вне зависимости от того есть там совпадения или нет. Добавлено @ 15:42 Вот блин, он мне и сложение не правильно дает, каждую строку после первой он начинает не с ноля, а с конечной суммы. Чорд чорд чорд) |
| Автор: baldina 30.6.2011, 16:23 |
посмотрите внимательнее. а лучше - задайте массивы вручную. http://codepad.org/tMdEtddz |
| Автор: newbieone 30.6.2011, 16:34 | ||||||
В условии же сказано о полном равенстве строки и столбца, верно?
А у вас там в алгоритме выводится, что совпадение найдено, если есть хотя бы один такой элемент на позиции i,j, что симметричный ему элемент на j,i имеет то же значение...
Попробуйте вот так, кажется, то, что нужно.
|
| Автор: Kruger2 30.6.2011, 16:44 |
| Всегда выдает: there is no equality =( |
| Автор: baldina 30.6.2011, 16:44 | ||||
...на главной диагонали, i==j
Добавлено через 1 минуту и 55 секунд это проверка совпадения хотябы одного элемента. если надо проверить все, то
|
| Автор: newbieone 30.6.2011, 16:49 | ||||||||
а для случайно сгенерированной матрицы у вас, собственно, никогда и не будет никакой equality. вы смотрите на свою матрицу, на первую строку, потом на первый столбец. все элементы в строке и столбце одинаковые? очевидно, при использовании rand() для заполнения массива - нет.
это вы откуда взяли про главную диагональ? там идет прогонка по всему массиву
Давайте для определенности N=8, i=1, j=0. Рассмотрим 4 строку:
Отнюдь не главная диагональ. |
| Автор: baldina 30.6.2011, 17:00 |
| я имел в виду, что array[i][j] всегда ==array[j][i] при i==j Добавлено через 53 секунды именно поэтому у него всегда последняя строка попадает: там у последнего проверяемого элемента j==i и, соответственно, flag==1 |
| Автор: newbieone 30.6.2011, 17:12 | ||
| Главная диагональ там играет роль именно только в последнем элементе последней строки. На предыдущих же строках главная диагональ алгоритму Kruger2 вообще не важна: flag затирается при переходе от элемента к элементу, первые N-1 элементов могут быть различны, а N-тый элемент строки, в случае равенства N-тому элементу столбца, выставит flag в положение true, что якобы приводит к решению о равенстве строки и столбца (по сути, для положительного ответа программы у автора должны быть равны лишь A последних элементов строки и столбца, где A>=1 и не обязательно равно размеру строки/столбца N).
Ну всё просто, нужно обнулять ваш аккумулятор (sum) в начале каждого прохода по строке. |
| Автор: Kruger2 30.6.2011, 17:53 |
| Видимо я не понимаю задания. У меня получается есть допустим массив: 1 1 1 1 1 2 3 4 1 3 3 2 Вот тут первая строка совпадет с первым столбцом и только такой выдаст нужный ответ? |
| Автор: newbieone 30.6.2011, 17:58 | ||
Kruger2, внимательнее. В общем случае, если вы хотите, чтобы строка совпадала со столбцом, то количество элементов в них должно быть одинаковым (т.е. матрица должна быть квадратной). Иначе как вы, например, для вашего примера:
скажете, равен ли элемент [0][3]=1 элементу [3][0], если у вас четвертая строка отсутствует? Если четвертую строку всё-таки добавить как-то так: 1 1 1 1 1 2 3 4 1 3 3 2 1 6 5 3 то, безусловно, ответом будет k=1 (т.е. только 1 строка и 1 столбец содержат одинаковые элементы). |
| Автор: baldina 30.6.2011, 18:04 |
| newbieone, похоже, вы читаете невнимательно)))) долго объясняете то, что уже говорено |
| Автор: Kruger2 30.6.2011, 18:04 | ||
Ответ, зер из но иквилти. Что не так?) |
| Автор: newbieone 30.6.2011, 18:10 |
| baldina, возможно, между нами имело место быть недопонимание. Kruger2, укажите номер k, для которого k-ая строка вашей матрицы содержит те же элементы (слева направо), что k-ый её столбец (сверху вниз). Я такого не вижу. |
| Автор: Kruger2 30.6.2011, 18:12 |
| Не понимаю, где указать и что |
| Автор: newbieone 30.6.2011, 18:15 | ||||
Да здесь укажите, в виде ответа в теме
У вас первая строка матрицы содержит те же элементы, что и второй её столбец. Это замечательно, но ваша формулировка задания требует:
То есть, номер строки и номер столбца должны быть одинаковыми. Вы можете сравнить 1 строку с 1 столбцом, 2ую строку со 2ым столбцом, но не можете сравнивать 1ю строку со 2 столбцом. Ферштейн? |
| Автор: Kruger2 30.6.2011, 18:17 |
| ферштейн. убился об стену:( |
| Автор: triclosan 30.6.2011, 18:20 |
| Kruger2, так это же реализацию значительно упрощает. |
| Автор: Kruger2 30.6.2011, 18:21 | ||||
Последний вопрос
Вот тут обнуляю сум. Всё стало работать норм кроме одного. Не считает последнюю строку, хотя там есть отрицательное число. Почему же он его не видит?:( Думал, может в последнем цикле фор должно <= но нет)
Добавлено через 1 минуту и 15 секунд triclosan Конечно упрощает. Трудно решать задачу не понимая, чего от тебя хотят |
| Автор: newbieone 30.6.2011, 18:22 | ||||
Попробуйте, ответ должен быть: k=1, k=3.
По поводу второго задания: у вас в первой же строчке приведенного кода i должно меняться от 0 до N, а меняется до N-1, потому и нет последней строки.
|
| Автор: voral 30.6.2011, 18:40 | ||
|
| Автор: Kruger2 30.6.2011, 19:07 |
| newbieone Большой спасибо за помощь, разобрался и всё заработало. Плюсище от меня в репутацию поставьте человеку! =) За код с подробными комментариями я бы вообще пивом угостил, если б мог. как правило приходиться голову ломать, что для чего voral Элегантно. Тоже спасибо, плюс в репу от меня! baldina Тоже спасибо, тоже плюсик |
| Автор: borisbn 30.6.2011, 19:12 | ||
Kruger2, тебе до сотни постов немного осталось. сам и наплюсуешь |
| Автор: newbieone 30.6.2011, 19:26 | ||||||
borisbn, а это критично? Результаты будут верными и для вашего варианта, и для кода voral, а вот алгоритм - оптимальней ли?
Вне зависимости от знака элементов строки будут произведены N сравнений на равенство нулю, N обращений к элементу массива и проверок на отрицательность элемента, 1 присваивание. 2N+1 операция (или даже 3N+1, если обращение к элементу массива и сравнение считать двумя различными), если я нигде не наврал. Теперь здесь:
В худшем случае, когда все элементы отрицательны, имеем N присваиваний и N сравнений. 2N операций (ну или 3N, при тех же условиях, что и выше). Всё, конечно, поменяется, если вы скажете, что операция присваивания требует больше ресурсов, чем операция сравнения, но намного ли? Надо еще учесть, что далеко не всегда будет худший вариант, возможно, только один из элементов будет отрицательным, тогда будем иметь всего N+1 (2N+1) операций против 2N+1 (или 3N+1 соответственно). Тогда исходный алгоритм будет требовать аж на N операций меньше, чем предложенный вами. UPD.: Хотя, если еще чуть подумать, можно вспомнить о short-circuiting, когда первое сравнение даст false и ничего больше вычисляться не будет...
В общем, всё это очень спорно |
| Автор: voral 30.6.2011, 20:12 |
Да нет. Тут все бесспорно. Поправка правильная. В любом случае если вызывает сомнение можно разложить этот if на два - и это будет шустрее чем мой вариант |
| Автор: newbieone 30.6.2011, 20:51 | ||||||
Тестировал для SIZE=15000, заполнение массива случайными числами.
It took: 15.312 seconds
It took: 16 seconds Даже не знаю. |
| Автор: borisbn 30.6.2011, 21:56 |
| >It took: 15.312 seconds код >It took: 16 seconds IMHO всего на 15000 7% выиграша уже не плохо Если это кому-нить нужно |
| Автор: voral 30.6.2011, 22:34 | ||||
Не совсем правильное сравнение. Тут основное время занимает заполнение массива. Вот я почистил код. Каждый вариант запускается по три раза:
В результате у меня получися следующий вывод:
|
| Автор: Dov 1.7.2011, 00:07 | ||
А если как-то так попробовать?
|
| Автор: voral 1.7.2011, 00:26 |
| Да это будет быстрее. |
| Автор: newbieone 1.7.2011, 09:45 |
| Окей, практика показала увеличение производительности. А теперь теоретически это как-то можно объяснить? Я вот на прошлой странице пытался провести сравнение сложности алгоритмов "на бумажке" по количеству машинных операций, но, видимо, оно чего-то (многого) не учитывает. |
| Автор: voral 1.7.2011, 10:02 | ||
Это о последнем алгоритме? Там все просто. Сначала бежим по каждому элементу сторки, прибавляем его у сумме и сравниваем. Как только нашли первый отрицательный элемент, нас уже не интересует есть ли еще отрицательные, по этому мы уходим в продолжение цикла где нет проверок на отрицательность, т.е. избавляемся от лишнй операции на каждую итерацию. (в предыдущем "быстром" варианте мы все равно проверяли флаг на равенство 1 или 0) |
| Автор: newbieone 1.7.2011, 10:22 | ||
voral, я имел ввиду математическое пояснение в терминах теории сложности вычислений (сложности алгоритмов).
Вашего первоначального и того, что предложил borisbn. |
| Автор: voral 1.7.2011, 13:31 | ||||
а вы про этот пост где N расписывали Ну тогда както так: В худшем случае (кагда нет отрицательных числ) мы имеем N сравнений и ни одногоприсваивания В лучшем случае когда первый элемент в строке отрицателен имеем 1 сравнени и так же ни одного присваивания. Итак имеем от 1 до N (в зависимости от позиции отрицательного числа) операций против от N до 2N Добавлено через 4 минуты и 35 секунд А вообще. Если целью поставить быстродействие и если позволяет процедура заполнения матрицы. Добавить еще один одномерный массив. При вводе нового элемента матрицы анализировать существование отрицательного значения и заносить номер строки в массив. Хотя в этом случае (такой ввод) моно собственну и суму здесь же считать. Но это уже теряем гибкость. |
| Автор: newbieone 1.7.2011, 13:47 | ||||
| voral, не могу с вами согласиться. У вас же там в условном операторе два условия через &&, сравнений соответственно будет в два раза больше, плюс вы забываете о сравнениях (о первом из них, второе из-за short-circuiting не будет вычисляться) уже после присваивания... Если пытаться анализировать этим способом, имеем практически одинаковые результаты: N+2 до 2N против N+1 до 2N.
Если первый элемент отрицательней, проведется 2 сравнения, 1 присваивание, и после этого еще N-1 сравнений (т.к. fexists станет равным единице, то первое сравнение даст false и дальше выражение вычисляться не будет). В сумме N+1 сравнений и 1 присваивание, т.е. N+2 операций. Если все положительные, то fexists всегда остается равным нулю и имеем 2N сравнений.
Здесь если существует единственный отрицательный элемент, N сравнений и 1 присваивание, т.е. N+1 операция. Если все отрицательные, N сравнений и N присваиваний, т.е. 2N операций. Другое дело, что способ, судя по практическим результатам, не совсем верен. Практика с теорией расходятся... |
| Автор: voral 1.7.2011, 17:50 | ||||
видимо мы о разном. Я разложил именно поселедний самый шустрый вариант. Этот же случай
я понимаю так. Самое плохое когда нет отрицательных два сравнения, сложение энд т.е. 3N - операций Самое хорошее когда первое отрицательное первая итерация два сравнения, сложение энд и присваивание 4 операции остальные итерации одно сравнение т.е. (N-1)+4 Т.е получаем от N+3 до 3N против N+1 до 2N, (кстати операция операции рознь и && совсем не одно и то же что сравнение) К тому же. У нас диапазон чисел от -1 до 9. При размере матрицы 15000 шанс что в строке не будет отрицательных чисел очень мал. Т.е. скорее всего исходный случай с одним сравнением будет стремиться именно к 2N, В то время как где два сравнения врят ли дотянет до 3N... Думаю если уменьшить размер, или увеличить диапазон чисел.... ТО может быть преимущество перейдет. Это конечно все просто рассуждения можно попробовать посмотреть на практике. Дизасемблировать оба варианта, чтоб посмотреть как это выглядит на асме; и сделать с промежуточным выводом значений... |
| Автор: newbieone 1.7.2011, 18:01 | ||
Хехе, ну вот, а говорили на предыдущей странице, что
|
| Автор: voral 1.7.2011, 18:28 | ||||||
Вот еще небольшой тестик
Результат:
Добавлено через 2 минуты и 54 секунды При размере строки 11 все равно неплохой результат:
|
| Автор: Kruger2 11.7.2011, 12:42 | ||||
| Через несколько глав снова вернулся к этому заданию, но уже в более продвинутом виде. Теперь необходимо решить туже задачу, с динамическим выделением памяти. Тут я взял за основу код уважаемого voral, т.к. удобнее дописать функцию вот основа:
Вот что я добавил:
Значит функция maloc вроде бы написана без синтаксических ошибок, ибо компилятор не матерится. Однако как проверить правильно ли выделяется память я не знаю, поэтому прошу провеhить код функции maloc Далее, то что код функции freememory должен находится не тут я понимаю (ибо выделил память и тут же аннулировал), но где она должна находиться? После main? прямо перед main? Будьте добры, подскажите. |
| Автор: voral 11.7.2011, 14:21 | ||||
При выделении памяти ты заносишь адрес в переменную. Переменная имеет свою область видимости. А также, если она не глобальная, может пропасть при выходе из функции в которой существует. Ты сделал свои обертки для malloc и free. Желательно их вызывать (для одной области) в рамках однной функции - в которой живет переменная хранящая адрес. Однако, могут быть ситуации когда ты передаешь адрес в другую функцию/поток, а из той в которой создал уходишь... Тогда уже там надо позаботиться об освобождении. Например
Переменная Result будет уничтожена. Но память останется выделенной..... |
| Автор: Kruger2 11.7.2011, 14:35 |
| Т.е. мне надо вызвать функцию малок внутри каждой из моих двух функций или вызвать её в мейне перед выполнением двух других функций? Добавлено @ 14:40 и получается освобождать память тоже не надо, т.к. нет глобальных переменных ? |
| Автор: Kruger2 11.7.2011, 14:52 | ||
Вызываю внутри каждой функции сначала inmemory, затем freememory (решил переименовать малок в инмемори, что бы внести ясность) |
| Автор: baldina 11.7.2011, 15:01 | ||||||
сделав обертки, мы получили те же самые malloc и free, концептуально ничего нового. в вопросах управления ресурсами, в т.ч. памятью, важно понятие владельца. именно владелец отвечает за своевременное удаление объекта (освобождение ресурса). выделение ресурса может происходить вне владельца, важно, что бы сразу после выделения установить владельца. на примере умных указателей:
здесь выделение ресурса происходит вне владельца - переменной my_ptr, но владелец устанавливается сразу. освобождение памяти произойдет, кода закончится время жизни my_ptr. если между выделением ресурса и установкой владельца что-то происходит
есть вероятность возникновения исключения, тогда память не будет освобождена. |
| Автор: Kruger2 11.7.2011, 15:12 |
| В общих чертах я это понимаю. Теорию из книги прочитал, теперь пытаюсь перенести теорию на практику. Если я вас правильно понял, мне не нужно освобождать память по окончанию выполнения функции, т.к. локальная переменная сама сотрется при выходе из функции? Хорошо, тогда правильно ли я вызываю функцию динамического распределения памяти? Внутри функции, которая оперирует интересующими меня переменными я вызываю функцию выделения памяти, т.е. всё верно? Потому что я сомневался, может я в мейне должен вызвать функцию malloc(inMemory) перед началом выполнения двух других функций, но это получается нелогичным, т.к. память выделиться на все последующие функции и захламится мусором этих самых функций и при этом не произойдет очистки памяти. Верно? |
| Автор: baldina 11.7.2011, 15:17 | ||||||
| Kruger2, тут какая-то каша в коде. давай вернемся к задаче. требуется написать управление памятью и доступом для квадратной матрицы. определим операции 1. создать матрицу порядка N 2. получить доступ (для чтения или установки значения) к элементу (i,j) матрицы 3. освободить занимаемую матрицей память пусть у нас будет
предлагаю структуру сделать такой:
тогда data должен указывать на память размером size*size, а элемент (i,j) в data находится по индексу i*size+j остальное, думаю, сам реализуешь. ЗЫ: с использованием классов это можно сделать намного изящнее Добавлено через 3 минуты и 14 секунд
совсем не вызываешь это не вызов, а объявление |
| Автор: Kruger2 11.7.2011, 15:22 | ||
Это зря, структуры не изучал ещё. Совершенно непонял
Матрица у меня уже есть, зачем мне её ещё раз создавать, зачем мне функция получения значения элемента? Брр, стало только хуже. Я хоть немного понимал, что я и как делаю. У меня была задача состоящая из двух функций, по идее мне достаточно было выделить память под эти две функции, что бы решить новое задание. Но теперь весь код каша? А в каком месте то каша? сейчас есть 4 функции, 2 из них решают основное задание, а 2 другие это выделение памяти и очистка. Вроде до каши ещё далеко |
| Автор: baldina 11.7.2011, 15:26 | ||||
локальная сотрется, а то что было выделено при помощи malloc - нет. что бы динамическое распределение происходило так же просто и естественно, как это делается для локальных переменных, потредуется класс, в конструкторе которого выделяешь память, а в деструкторе освобождаешь.
Добавлено через 4 минуты и 52 секунды
ок, зайдем с другого конца. вот зачем: что бы разделить задачу на части, упростить её. сейчас имеешь сотню строк кода, сильно связанного между собой. а будешь иметь ту же сотню, но в отдельных функциях, каждая - неск. строк, совершенно независимых. допустим, структуры еще не изучал. классы тем более. давай обойдемся тем что есть. 1. вместо структуры будем использовать две переменные - указатель на выделяемую память и порядок матрицы. я предлагаю использовать одномерный массив для матрицы. это гораздо проще в выделении памяти, а лдя доступа будем использовать очень простую функцию |
| Автор: Kruger2 11.7.2011, 15:35 | ||
Неужели нельзя в рамках моей программы выделить память, без подключения структур? Я до них ещё не добрался.
Мда, тут вызвать никак не получается При попытке вызвать функцию посредством inMemory (b) пишет expected primary-expression before ')' token, что за праймери экспрешен?( |
| Автор: baldina 11.7.2011, 15:36 | ||||
посмотри что получилось: теперь все операции с матрицей мы можем осуществлять через эти (очень простые) функции. можешь добавить проверки выхода индексов за границы. можешь добавить отладочную печать. на вызывающий код это не повлияет. Добавлено через 1 минуту и 28 секунд
ну вообще-то у тебя в программе b определена как int, а inMemory требует int** |
| Автор: Kruger2 11.7.2011, 15:38 |
| даже функцию блин вызвать не могу) |
| Автор: baldina 11.7.2011, 15:41 |
| Kruger2, тут две проблемы: пока ты не очень ориентируешься в языке и стараешься решить задачу целиком. первое подтянешь, со вторым я тебе сейчас помогаю. |
| Автор: Kruger2 11.7.2011, 15:44 | ||||||
| Мы будто говорим каждый сам с собой Меня интересует в первую очередь два вопроса. Верны ли сами функции inMemory и freeMemory и будет ли верным такой вызов?
Добавлено через 1 минуту и 59 секунд baldina, Да я вроде литературу читаю, простые задачи решаю, но как то ориентироваться лучше не начинаю. Хоть бери об стенку убейся, как только появляется задание выходящее за рамки того что описано в книге, я словно пытаюсь по китайски заговорить:*( Добавлено через 6 минут и 14 секунд Вообщем то тоже неверно, программа рушится Добавлено через 7 минут и 59 секунд Но у меня то двумерная матрица Добавлено через 14 минут и 34 секунды Ладно. Пробую разобраться:
get_m помоему все таки лишняя, разве нет? у меня ведь объявлена матрица, получается я работаю не с ней, а с той что тут будет создана void_st //функция установки значения элемента, вообще не понимаю что за установка значения. мы же не рандомную матрицу создаем. create matrix создает одномерный массив, тут кажись вся моя функция с проверкой должна подходить, нет?
а destroy_matrix вроде как должна подходить моя же функция? |
| Автор: baldina 11.7.2011, 16:43 | ||||
по правде говоря, она не совсем правильная. мне показалось проще и быстрее перейти к обсуждению моего варианта, чем ковыряться в адресах и звездочках. по порядку. 1. что такое многомерный массив в С/С++? это одномерный массив, строки которого расположены последовательно в памяти (ничего необычного, ведь компьютерная память одномерная). Именно такое расположение я и предлагаю. Это проще для восприятия, чем "массив массивов". 2. неважно, что как расположено. мы пользуемся определенным интерфейсом - функциями create, get, set... Этот подход нам позволяет в процессе решения конкретной задачи не вникать в устройство массива, а в процессе проектирования интерфейсных функций не думать о всей задаче. поэтому get_m не лишняя. технически можно без нее обойтись, можно вообще все написать в единственной функции и в одну строчку, но с точки зрения грамотного проектирования и удобства использования она нужна. 3. ну поскольку она в итоге вызывает тот же malloc, то примерно да. точнее, если взять мою функцию и добавить туда проверки и сообщения, будет 'правильная' версия Kruger2 теперь рассмотрим
здесь есть две основные проблемы 1. параметры в С/С++ передаются по значению, поэтому если нужно инициализировать int**, то передавать приходится int***
2. К выделенному таким образом массиву нельзя обращаться A[i][j], т.к. элементы массива теперь не расположены последовательно. нужно так: (A[i])[j]; уже не так красиво, как раньше, правда? |
| Автор: Kruger2 11.7.2011, 16:57 | ||
| Всё равно ни черта не понимаю. Пойду ещё искать литературу. Добавлено через 7 минут и 24 секунды Вот я копировал отсюда, немнго меняя под себя. получается тут неправильный код выложили?)
|
| Автор: baldina 11.7.2011, 17:10 | ||
| Kruger2, есть простой выход. вообще он не очень хороший, но в данном случае наверно лучший. сделай
|
| Автор: Kruger2 11.7.2011, 17:23 | ||
так? |
| Автор: voral 11.7.2011, 17:33 | ||||||||||||
Во первых вы ни как не используете эту память, по-этому я не могу сказать где вам надо. В данном случае правильный ответ: "нигде ни выделять ни освобождать". Во вторых у вас все неправильно. Давайте прочитаем по русски этот код:
обявляем две переменные типа int. пытаемся объявить (не вызвать) функцию, которая в качестве аргумента принимает указатель на указатель на переменную типа int пытаемся объявить (не вызвать) функцию, которая в качестве аргумента принимает указатель на указатель на переменную типа int Все не более. Отбрасываем ошибку, с попыткой объявить функцию
Опять не увязка: 1 ваша процедура ждет указатель на указатуль...... 2 Места для переменных типа int уже зарезервированы, и нет смысла выделять память (а еслибы все же нужно было то надо было писать "&b" Правим
Теперь все, вроде так. Но! Вызывая inMemory(b) ; вы в конечном итоге инициализируете переменную b, адресом массива указателй переменная c при этом неинициализирована! А вы хотите освободить память по адресу хранящемуся в этой переменной!!! Ноона ни чего не содержит! Еще раз правим.
Вот теперь вы память выделили, а потом освободили. Осталось придумать зачем она вам тут сдалась... В данной задаче единственное применение для этих функций. Зарезервировать место под матрицу; заполнить ее программно (сейчас у нас это константа); найти решение; освободить память.. Т.е. по сути, это должно быть в main
Если вы где то зарезервировали память, то вы обязаны ее освободить - иначе "утечка памяти". То, о чем я вам говори касается лишь освобождения памяти под автоматическую переменную хранящую адрес выделенной вами памяти. |
| Автор: baldina 11.7.2011, 17:41 |
смотрите сами: http://codepad.org/KAP0hVsz |
| Автор: Kruger2 11.7.2011, 17:47 | ||
voral,
При вызове функции freeMemory программа рушится. Добавлено через 1 минуту и 29 секунд baldina, Посмотрел, код рабочий. Следовательно у меня вызов кривой. Добавлено через 2 минуты и 28 секунд Но нет освобождения памяти. И в примере выше при попытке высвободить память программа рушится. |
| Автор: voral 11.7.2011, 17:51 | ||
На всякий случай
|
| Автор: Kruger2 11.7.2011, 17:52 |
| Самое обидное что в книге кернигана и ричи 2 строки по динамическому распределению памяти, а у харви дейтела "как програмировать на си" вообще ничего) Судя по содержанию вспоминают они о нем только в структурах |
| Автор: baldina 11.7.2011, 18:09 |
плохо смотрели. не годный код. |
| Автор: voral 11.7.2011, 18:11 | ||
тут и я немного прощелкал. Дело в том как передан параметр в inMemory. Пока сам руками не написал не осознал
|
| Автор: baldina 11.7.2011, 18:34 |
зачем +1 ? |
| Автор: voral 11.7.2011, 18:48 |
Посыпаю голову пеплом - набацал в спешке. Тут, естественно, это совершенно не нужно. |
| Автор: voral 11.7.2011, 23:00 | ||||||||||||
Итак, почему не работало варианте с фунцнкцией
Это вроде как раз у Кернигана нормально расписано. Параметры функции являются локальными переменными в этой функции. Т.е. в данном случае мы скоипировали значение переменной b в функции main в переменную Array функции inMemory. (т.е. NULL). Далее этой локальной переменной присвоили значение адреса выделеной malloc памяти и вышли из функции. Но этот адрес выделенной памяти не передался обратно в процедуру main. и b так и осталась равна NULL. Демонтрирую (количество звездочек снизил, чтоб не мешались)
Вывод:
Чтобы это обойти нужно передавать параметр не по значению, а по ссылке.
вывод:
Кстати до кучи. Наглядное пояснение, а можно ли не освобождать память. В примере выше убираю строку free(b). И натравливаю на бинарник утилиту для определения утечек valgrind
в использовании нпри выходе 8 байт в одном блоке был один аллок, 0 освобождений, 8 байт занято - это и есть вредная утечка памяти |
| Автор: Kruger2 13.7.2011, 10:47 |
| Спасибо. Почитаю ещё литературу, потом буду дальше вас мучить |
| Автор: krot100500 27.12.2011, 00:11 | ||||
| Всем привет!) Благодоря этой темке я слегка разобрался в указателях) за это вам почет и уважуха) Вообщем попал сюда как получил задание на курсач(такое-же как и у автора) ну вообщем вот мой код для массива 3 на3 можете сказать что тут не так плиз) я подозреваю что что-то с выводом функции, голову уже сломал всю
Добавлено через 4 минуты и 20 секунд
зачем тут операнд return? |
| Автор: voral 27.12.2011, 09:20 |
Хм... А это разве я писал? Впрочем очевидно: Это функция проверки условия задачи. Если элемент A[i][j] не равен A[j][i] значит желаемое условие нарушено и дальнейшая проверка элементов не нужна. Следовательно выходим из функции. |
| Автор: voral 27.12.2011, 10:32 | ||
Форматирование кода - неуд. Строка 13: Зачем? Строка 32: Что делает? Строка 51: в этой области видимости есть переменная. Память под массив не выделена и массив не заполнен. Этот массив в этой функции не имеет ни какого отношение к массиву в функции input Больше пока не смотрел..... Добавлено @ 10:34 В догонку массив a в функции input не имеет отношения к массиву a в функции main. Добавлено @ 10:36 А так же в конце программы не освобождается память. |
| Автор: voral 27.12.2011, 11:13 |
| кстати. Небольшой "секрет". Цикл в 10 строке тоже ни чего не делает.... Вообще. Если отключить оптимизацию просто посчитает до 3. Но ни чего не сделает из того, что вы ожидаете |
| Автор: krot100500 27.12.2011, 12:58 |
| ну вообщем функция void input -вводит массив, взят текс тупо из методички void subzero -функция нахождение элемента ниже 0 и сумма всех элементов этой строки void out функция тоже взята из методы ) выводит массив заданый в inpute Добавлено через 5 минут и 54 секунды в исходники из методички я особо не разбирался просто коррекция под свой вариант) динамическое распределение памяти для меня лес темный(( примерно понял операнд малок( по Герберту Шилдту) но там не было сказано про освобождение памяти я об этом узнал тока тут) ЗЫ Voral свой код всегда узнать можно)) я взял твой код для статического распределения попытался в нем разобраться) вроде как понял что-то) непонял тока почему цикл тока для J есть (в comparline) Добавлено через 10 минут и 51 секунду ну вообщем как я понял из лекций прога в кратце будет иметь вид #include тут все необходимые библиотеки input{ввод масива с клавы} comp{кстрока=кстолбцу} subzero{вычисление суммы с отриц элементом} out{вывод на экран} main{в нем как раз обрашение на функции } |
| Автор: voral 27.12.2011, 13:25 | ||||||||
Что ожидалось от этих функций я догадался. Но беда в том, что только в функции comp и subzero может попасть массив из-вне. В main, input и out переменные, ссылающиеся на массив, хоть и называются одинаково. Тем не менее это совершенно разные переменные. И только в input эта переменная ссылается на выделенный кусок памяти. В остальных случаях идет обращение к мусору и как результат сегфолт. Почитай внимательно по ключевой фразе "область видимости".
В твоем коде по сути нет ошибок с "выделением динамической памяти" как таковым. Основные ошибки: 1 непонимание области видимости переменных 2. расстановка точки с запятой где ни попадя. Пример:
В результате этого кода будет выведено 1 раз слово "first" и 4 раза слово "second" В итоге в input у тебя выделяется память под массив массивов. И один раз (вместо 3) для массива.
Да нашел. Эта функция вызывается из цикла по i. А i передается в функцию в качестве параметра. |
| Автор: krot100500 27.12.2011, 22:47 |
| т.е как я понял для того чтобы функция "работала с массивом a[i][j]", к примеру, subzero должна иметь параметр не (int i), а (int a) и соответственo нужно вводить 2-й for? |
| Автор: voral 27.12.2011, 23:33 | ||
Как раз subziro у тебя все правильно принимает в качестве параметра указатель на массив массивов переданный из функции main. Беда в том, что в ф-ии main переменная а ни на чего не указывает. Короче вот почти твой код с коментариями. У меня не винда, так что не прверял виндозависимые строки, но дожно быть все ок.
|
| Автор: krot100500 28.12.2011, 21:35 | ||
как я понял строка 3 вводит указатель mainArray и присваевает ему значение input(который сам по-сути является именем-указателем функции) строка 4 придает функции out параметр mainArroy, и благодаря этому функция out будут работать как-бы с массивом из input а вот дальше чуток уже напряжка) с момента инициальзации i; мы получается освобождаем память от mainArroy или от input на которую она и является указателем? |
| Автор: krot100500 28.12.2011, 22:07 | ||||||
Чуть не забыл: чтобы функция к примеру comp работала с моим массивом что нужно сделать? а то написал а он при любых раскладах выдает результат 1 и все*(
как нас учили первые 2 строки должны быть такими:
Добавлено через 10 минут и 9 секунд Чуток пораскинув своим упрямым мозгом пришла мысль:
у нас тут как раз и присваиваются значения? и чтобы comp работала с моим массивом надо её так-же объявлять? |
| Автор: voral 29.12.2011, 00:03 |
| Передача параметра у вас была правильно сделана в первом варианте ф-ии comp. Ваш второй вариант этой ф-ии говорит о том что вы совершенно не просекли разницы между вашей ф-ией out и моей. К тому же у вас отсутствует цикл по j. В том моем коде в начале топика есть цикл по обоим индексам, хотя в приведенной вами функции только по одному. Но на то были причины. У вас же цикл только по одному индексу. А j может принять, на момент использование, совершенно разное значение, которое зависит "от фазы луны и расположния звезд".... Вообще, думаю, для вас самый быстрый метод понимание и решения вашей ошибки в этой задаче. Будет внимательное прочтение книги Кернигана и Ритчи "Язык программирования Си" (с первой страницы). У вас проблемы не с указателями и выделением памяти, а в еще более базовых понятиях. Вы слишком спишите. Указатели вам пока рано. Я б, конечно мог, разжевать данный конкретный пример. Но одно из двух: либо вы все равно ни чего не поняли либо мне бы пришлось почти полностью здесь воспроизвести вышеупомянутую книгу (по крайней мере до указателей) |
| Автор: krot100500 29.12.2011, 00:20 |
у меня он есть тока в другом ... не в том который скинул*) а спишу ибо застрял с этой задачкой*( это курсовое задание на выполнение которого осталось 1 ночь и 2 дня) бьюсь я с ним уже месяц, прочитал книгу Герберта Шилдта но там слишком непонятно... методичку от нашего препода- там ошибка на ошибке, которые вижу даже я))) что уж говорить о лекциях) ЗЫ язык си у нас начался совсем недавно) для примера мы написали пока-что 4-ре лабы) 1)прога для вывода на экран "привет мир"*) . . . 4)прога для рандомного заполнения масива 5 на 5) а курсовая работа совершенно другово порядка) Книгу Кернига скачал вчера пока не читал*печаль* |
| Автор: krot100500 29.12.2011, 22:19 | ||
Прочитал Кернигана(не всего) и вот что получилось печаль в том что прога вылетает*( все та-же печаль с указателем |
| Автор: krot100500 29.12.2011, 22:53 |
| не тот выкинул*) |
| Автор: voral 30.12.2011, 01:07 |
| Жесть. У вас stroka - это не переменная типа int!!! Это указатель. И операция stroka = stroka + 1 означает что вы смещаете укзатедь в памяти |
| Автор: krot100500 30.12.2011, 02:47 | ||||
| 3-е сутки без сна дают о себе знать) я запустил прогу она брякнулась но не сохранил*(( int main(void)
вопросик: в func передан индекс массива i? т.е. если не выходя из блока main я буду использовать func я буду использовать как бы массив i? или нужно будет делать это так
а то как то в литературе непонятно) или это бессоница?*) |
| Автор: krot100500 30.12.2011, 03:14 | ||
| Я ВКУРИЛ!!!!!Еххааа Voral СПАСИБИЩЕ!!!) метод проб и ошибок рулит))) я заного прочитал все в этом топике и на 10 раз пришла истина*)
|
| Автор: krot100500 30.12.2011, 03:56 |
| Печаль случилась*((( при увеличении массива до 8Х8 выдает фейловые рез-ты ошибку не найти*( постинкримент изменил на прединкремент(comp ф-я) |
| Автор: voral 30.12.2011, 09:05 | ||||
Если бы вы очень внимательно сравнили свою исходную функцию out и мой вариант. То у вас бы в коде было на две серьезных ошибки меньше. Править не буду, но прокомментирую ваш код:
Добавлено через 8 минут и 4 секунды Еще раз повторю: в последнем ваше коде переменная a в функции main, переменная a в функции comp и переменная a в функции sum это абсолютно разные переменные ни когда не обменивающиеся значениями. И лишь по теории случайности с вероятностью 1 к бесконечности могут указать на один и тот же адрес в памяти и в этом случае возможно ваша программа отработает правильно. Добавлено через 13 минут и 53 секунды
Он рулит ровно до тех пор пока вы не осознаете, что самый быстрый путь - зачастую самый длинный. Читайте Кернигана и Ритчи! Если бы вы сразу после первого поста начали чтение вы бы уже впитали те главы, что достаточны для решения вышей задачи. И сейчас бы уже имели готовое решение. |
| Автор: krot100500 1.1.2012, 23:08 |
| Спасибки еще раз что потратил стока времени на объяснения) Мне это все-равно не помогло*( через годик, примерно ,вернусь разбирать заного, если голову не отобьют и востановят в универе( |
| Автор: krot100500 4.1.2012, 16:43 | ||
| урра мне дали еще времени)ЗЫ я увидел свои ошибки) вот исправил ошибки) сделал так что функции комп и сум работали с массивом) мояя ошибка была как раз в том что надо-было указать в параметрах не цикл а указатель на функцию ввода массива, и соответственно слегка подправить эти функции
ЗЫ Кернигана и Ричи прочитал всего, но непонял) Понял тока когда прочитал Шилдта и потыкался в тексте проги) |
| Автор: voral 4.1.2012, 17:14 | ||||
В строках 30 и 31. Что за наворот:
Возможно будет короче:
Так надо не на скорость и объем читать. Пока что то не понял не читаешь следующую главу. А разбираешься/читаешь непонятную до просветления. |
| Автор: krot100500 4.1.2012, 21:43 | ||||||
| тоже вариант)но я как востпринял так и написал) ЗЫ теперь похоже на истину? и кстате спомощью ф-ии
мы выделяем память под указатели на элементы массива так? а
выделяет память под сами элементы массива? Добавлено через 1 минуту и 20 секунд
мне просто более понятно языком Шилдт'a *) |
| Автор: voral 9.1.2012, 16:08 | ||
Как ни странно в обоих случаях выделяем память под элементы массива. Но! В первом случае элементы массива - это указатели на одномерные массивы. Во втором случае - это значения типа int. По сути дела "двумерный" массив используемый в коде представляет из себя SIZE массивов элементов типа int (имеющих SIZE элементов). Плюс один массив элементов типа int* т.е. указателей на те самые массивы int (имеющий SIZE элементов). Естественно элементы массива о котором говориться непосредственно в задаче (т.е. не "вспомогательный" массив) хранятся только в памяти выделемой строкой которая приведена во второй цитате. |
| Автор: krot100500 11.1.2012, 11:32 |
| У меня вот и возникал вопрос) зачем нам нужна динамика если известно количество элементов*) |
| Автор: voral 11.1.2012, 11:53 |
| все зависит от задачи. |
| Автор: krot100500 11.1.2012, 13:33 |
| ну так мы используем динамику когда, как правило неизвестно кол-во элементов) а тут задано что 8 на 8 ) и соответсвенно будет выделяться памяти под 64элемента типа инт Добавлено через 5 минут и 15 секунд *изначально неизвестно, и задается уже во время запуска. |
| Автор: voral 11.1.2012, 15:29 |
| учебные задачи не в счет ;) Точнее смотря, что изучаете разбирая данную задачу. Если динамические массивы сгодится, если циклы то можно и избавиться от динамического выделения. |