Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
1

Массивы и функции как параметры

18.06.2013, 18:14. Показов 2628. Ответов 23
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Из главной функции нужно вызвать промежуточную функцию с 3 параметрами - (введённый двумерный массив, кол-во элементов, функция).
Последний параметр действие(функция) которое нужно выполнить над массивом. Например заменить нулем все элементы столбца после минимального элемента.
Сложность у меня вызвало то что промежуточная функция должна выполнить это действие для конкретных элементов.
Например у меня выполнить действие для столбцов у которых последний элемент имеет чётное значение.
Как в промежуточной функции я должен уметь различить это, если я получаю целиков массив в параметрах?
При выполнении действия как то передавать ему нужный столбец как отдельную структуру?

Если писанина вся эта не ясна вот схема вызовов функций:

main -> промежуточная функция (3 параметра), определяются нужные столбцы -> функция(действие над выбранными столбцами)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.06.2013, 18:14
Ответы с готовыми решениями:

Массивы как параметры функции
Доброго времени суток! Никак не могу разобраться, как поменять максимальный и минимальный элемент...

Массивы, как параметры функций
Отрицательные элементы матриц A (5,4) , B (3,2 ) , C (4,4 ) записать в одномерный массив .

Суперглобальные массивы, как параметры методов
Нужно ли их передавать в виде параметров метода? Например, так? public function getUser() ...

Как правильно вызывать функцию, параметры которой - массивы
Добрый день! Помогите правильно реализовать. Задача такая! Например мне в массив строк вводятся...

23
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
20.06.2013, 12:10  [ТС] 2
Люди, ну объясните пожалуйста как это сделать?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
25.06.2013, 10:20 3
Цитата Сообщение от SanAlex Посмотреть сообщение
Например у меня выполнить действие для столбцов у которых последний элемент имеет чётное значение.
Поскольку само действие не указано, придумаю его: умножить каждый элемент такого столбца на 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
// Тип действия над массивом
typedef void (*action)(int **arr, int rows, int col);
 
// Функция, находящая очередной удовлетворяющий условию
// столбец и выполняющая для найденного столбца заданное
// действие
void process_array(int **arr, int rows, int cols, action a)
{
    // Идём по столбцам
    for (int i = 0; i < cols; ++i)
        // Если последний элемент очередного столбца чётный
        if (arr[rows - 1][i] % 2 == 0)
            // Выполняем для него действие
            (*a)(arr, rows, i);
}
 
// Действие, для заданного столбца умножает все его элементы на 2
void mul_2_action(int **arr, int rows, int col)
{
    // Идём по строкам (по элементам столбца)
    for (int i = 0; i < rows; ++i)
        // Умножаем элемент на 2
        arr[i][col] *= 2;
}
1
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
02.07.2013, 00:19  [ТС] 4
Огромное спасибо!
Что бы точно отразить суть задания напишу такой полукод:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void функция действие 1(массив, строка, столбец)
{
      //заменить нулём все элементы столбца.
}
void функция действие 2(массив, строка, столбец)
{
      //умножить все элементы на 2.
}
void промежуточная функция(массив, кол-во элементов, функция действие i-я)
{
      if(удовлетворяет условию)
            функция действие i-я(массив, строка, столбец); //вызов
}
void main
{
      //вызовы промежуточной функции(типа)
 
      промежуточная функция(массив, кол-во элементов, функция действие 1);
      промежуточная функция(массив, кол-во элементов, функция действие 2);
}
Как выше описанный код подогнать под этот?
И вопрос, что за трюк с этим typedef (*action)? Немного не понял.
Спасибо.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
02.07.2013, 12:29 5
Цитата Сообщение от SanAlex Посмотреть сообщение
напишу такой полукод
наверное Вы хотели сказать "псевдокод"?
Цитата Сообщение от SanAlex Посмотреть сообщение
что за трюк с этим typedef (*action)?
C++
1
typedef void (*action)(int **arr, int rows, int col);
action - имя типа, который может хранить указатель на функцию, которая принимает 3 аргумента:
(int **, int, int) и возвращает void.
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
02.07.2013, 14:21 6
SanAlex, а чего подгонять? Мой код и так на 80% соответствует заданию. Вам осталось написать второе действие, а также функцию main, в которой вызывать process_array с соответствующими аргументами.
1
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
15.07.2013, 19:15  [ТС] 7
Ещё такой вопрос: вот вы двумерный массив в списке формальных параметров функции пишете так (**arr)
А разве если просто написать (arr) - это не будет ссылкой на его первый элемент?
Если все же оставить так (**arr), то при вызове какая будет запись массива в фактических параметрах.
Я просто думал когда дело ведётся с массивом, то при описании и вызове его в параметрах, он записывается одинаково -(arr).
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
15.07.2013, 20:00 8
SanAlex, вопроса не понял. Если записать так:
C++
1
void process_array(int arr, int rows, int cols, action a)
то мы не массив будем принимать, а обычную целочисленную переменную.
Учтите, что обычный статический двумерный массив, объявленный как type array[ROWS][COLS], в функцию, ожидающую type **, передать не получится, поскольку типы будут несовместимы (тип массива array - не type **, а type (*)[COLS]). Поэтому передавать туда надо массив указателей, например, динамически выделенный массив массивов:
C++
1
2
3
4
int **arr = new int *[ROWS];
for (int i = 0; i < ROWS; ++i)
    arr[i] = new int [COLS];
process_array(arr, ...);
0
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
15.07.2013, 20:34  [ТС] 9
silent_1991
Да я видимо не понятно описал вопрос.
Ну вообщем.
каков будет синтаксис, если:
1) Массив в списке формальных параметров
2) Тот же массив в списке фактических (при вызове)

Далее, допустим такое описание функции
C++
1
2
3
4
void SumFunc(**arr)
{
     //операторы
}
и вот такой вот вызов:

C++
1
SumFunc(arr);
это вообще правильно?
Это называется передача "Массива указателей?"
Такой же синтаксис пойдёт и для n-мерного массива?

И что написано в этой строке?
C++
1
int **arr = new int *[ROWS];
Извините конечно за такое количество вопросов, просто хочу что бы всё мне понятно было)
Спасибо.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
15.07.2013, 20:43 10
Цитата Сообщение от SanAlex Посмотреть сообщение
Далее, допустим такое описание функции
"Такое описание функции" вызовет ошибку компиляции. Необходимо указать тип.
Цитата Сообщение от SanAlex Посмотреть сообщение
это вообще правильно?
А что, собственно, вас смущает? В списке параметров функции как бы объявляются переменный, доступные в этой функции, но переданные в неё извне. Объявление предполагает указание типа и имени идентификатора. Идентификатор в данном случае - arr, а тип его - int **. Вызов же функции предполагает передачу в неё аргументов соответствующего типа. Там достаточно указывать только идентификаторы. Имя идентификатора в списке формальных (указанных при объявлении функции) и фактических (указанных при вызове функции) параметров могут как совпадать, так и не совпадать, это никакой роли не играет.
Цитата Сообщение от SanAlex Посмотреть сообщение
И что написано в этой строке?
А вот тут я уже начинаю чувствовать себя справочником. Так что вы уж сначала хоть минимальный объём теории изучите, а потом с вопросами. Гугл по запросу "C++ new keyword" выдаст всю необходимую информацию. К тому же советую заглянуть в тему с литературой, раз уж действительно хотите разобраться и понять.
1
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
16.07.2013, 22:02  [ТС] 11
Спасибо. Однако я ничего не понял. Объясните пожалуйста доступным, для новичка, языком что к чему.
Перерыл весь интернет. Передача двумерных массивом как параметра везде описана по разному.
Кто то в параметрах функции пишет этот массив так: (int **arr)
Кто то так: (int arr[][N])
или даже так (int *arr), тогда какой смысл в первом случае?
Кто нибудь может доступно объяснить при каком описании, какой будет вызов (синтаксически).
И какой вариант лучше и почему, или может каждый вариант хорош для конкретного случая?
И в конце концов что из этого всего называется Массивом указателей, что из них массив массивов?
Надеюсь на вашу снисходительность по отношению к моим "непоняткам". Просто такое расхождение в информации разных источником совсем с толку сбило, и запутало.
Спасибо.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
16.07.2013, 22:29 12
Двумерный массив может быть представлен по-разному:
1. Созданный на стеке:
C++
1
int a[10][20]; // размер должен быть известен на момент компиляции
2. Созданный в куче:
C++
1
2
3
4
int** a = new int*[10]; // Выделяем массив указателей на строки (одномерные массивы)
for( int i=0; i<10; ++i ) {
   a[i] = new int[20] // Выделяем одномерный массив под каждую строку.
}
3. Варианты имитации двумерного массива на одномерном.
Выделяем одномерный массив 10*20, а потом интерпретируем его как двумерный в своих вычислениях.

В первом случае передавать массив в функцию надо так:
C++
1
void f( int a[10][20] );
// первую размерность можно убрать и будет так (что эквивалентно):
C++
1
void f( int a[][20] );
Во втором случае надо так:
C++
1
void f( int** a );
Ну, а в третьем, возможен и такой вариант:
C++
1
void f( int* a ); // для любых (на стеке или в куче) одномерных массивов
Но это имитация, а не настоящий двумерный массив.
1
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
16.07.2013, 22:29 13
Для начала надо понимать, что двумерный массив в памяти не отличается от одномерного - всё его содержимое аккуратно и последовательно разложено в одной непрерывной области памяти. Строки такого массива последовательно размещены друг за другом.
Первый случай (int ** arr) - массив указателей на строки двумерного. Такой вспомогательный массив необходимо создавать и заполнять указателями.
Второй случай (int arr[][N]) - по сути, адрес первого элемента, а синтаксически - тот же двумерный массив. Однако при этом функция жёстко заточена под конкретный N.
Третий случай (int *arr) - тоже адрес первого элемента. Функции передаются размеры массива и она вычисляет линейный индекс из номеров строки и столбца (если массив размерностью M на N, то j-й элемент i-й строки имеет линейный индекс i*M + j).
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
16.07.2013, 22:36 14
Цитата Сообщение от Nick Alte Посмотреть сообщение
что двумерный массив в памяти не отличается от одномерного - всё его содержимое аккуратно и последовательно разложено в одной непрерывной области памяти.
для динамически выделяемых это не так.
Цитата Сообщение от Nick Alte Посмотреть сообщение
Третий случай (int *arr) - тоже адрес первого элемента.
Только вот на преобразования типов будет компилятор ругаться. Да и обрабатывать такой двумерный массив в функции будет не достаточно наглядно. В общем, я об этом уже сказал выше, про имитацию.
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
16.07.2013, 22:51 15
Цитата Сообщение от Tulosba Посмотреть сообщение
для динамически выделяемых это не так.
Если имеется в виду коллекция выделенных вразнобой строк - так это и не массив уже в изначальном понимании, там даже строки могут быть разной длины при желании. Но если не считать ученических программ, даже при динамическом выделении памяти имеет смысл выделять весь массив одним куском и "имитировать" двумерность.
Цитата Сообщение от Tulosba Посмотреть сообщение
Только вот на преобразования типов будет компилятор ругаться
Это настолько легко обходится передачей первой строки двумерного массива, что я просто не вижу смысла вообще об этом упоминать. Насчёт недостаточно наглядно - зависит от оформления и от содержимого задачи, иногда даже наглядней может выйти.
Ну и по поводу имитации - это вопрос мнений. Собственно, в случае работы со стековыми двумерными массивами компилятор усердно занимается как раз той самой имитацией.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
16.07.2013, 23:06 16
Цитата Сообщение от Nick Alte Посмотреть сообщение
компилятор усердно занимается
вот когда компилятор занимается такими преобразованиями это хорошо, а когда программист - плохо.
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
16.07.2013, 23:16 17
Цитата Сообщение от Tulosba Посмотреть сообщение
вот когда компилятор занимается такими преобразованиями это хорошо, а когда программист - плохо.
Не совсем так. Иногда такие преобразования нужны (в случае тех же динамических массивов, например), и их нужно делать именно программисту. И плохо это будет только в том случае, если он станет их делать раз за разом вместо того, чтобы сделать единожды.
0
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
28.09.2013, 16:23  [ТС] 18
Tulosba
вы писали:
2. Созданный в куче:
Код C++
1
2
3
4
int** a = new int*[10]; // Выделяем массив указателей на строки (одномерные массивы)
for( int i=0; i<10; ++i ) {
a[i] = new int[20] // Выделяем одномерный массив под каждую строку.
}

массив передаётся в функцию так:

1
void f( int** a );
А как этот двумерный массив будет описан в качестве формального параметра в заголовке функции?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.09.2013, 17:36 19
Цитата Сообщение от SanAlex Посмотреть сообщение
А как этот двумерный массив будет описан в качестве формального параметра в заголовке функции?
C++
1
void f( int** a );
1
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
28.09.2013, 17:47  [ТС] 20
Tulosba,
Блин, а как теперь к массиву обращаться внутри функции? Определённому элементу?
0
28.09.2013, 17:47
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.09.2013, 17:47
Помогаю со студенческими работами здесь

Двумерные массивы как формальные и фактические параметры функций
Нужна помочь в решение такой задачи: Задан двумерный массив (n × m). В каждом его строке...

Целесообразно ли передавать большие массивы как параметры в метод?
В классе есть метод и несколько массивов, с которыми метод выполняет операции. Для разных случаев -...

Оптимизация кода, функции и методы как параметры функции
Грубо говоря - есть множество циклов которые привязаны к проверочным функциям, поскольку сами по...

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru