Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.56
SanAlex
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
18.06.2013, 18:14     Массивы и функции как параметры #1
Из главной функции нужно вызвать промежуточную функцию с 3 параметрами - (введённый двумерный массив, кол-во элементов, функция).
Последний параметр действие(функция) которое нужно выполнить над массивом. Например заменить нулем все элементы столбца после минимального элемента.
Сложность у меня вызвало то что промежуточная функция должна выполнить это действие для конкретных элементов.
Например у меня выполнить действие для столбцов у которых последний элемент имеет чётное значение.
Как в промежуточной функции я должен уметь различить это, если я получаю целиков массив в параметрах?
При выполнении действия как то передавать ему нужный столбец как отдельную структуру?

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

main -> промежуточная функция (3 параметра), определяются нужные столбцы -> функция(действие над выбранными столбцами)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
SanAlex
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
20.06.2013, 12:10  [ТС]     Массивы и функции как параметры #2
Люди, ну объясните пожалуйста как это сделать?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
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;
}
SanAlex
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)? Немного не понял.
Спасибо.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
02.07.2013, 14:21     Массивы и функции как параметры #6
SanAlex, а чего подгонять? Мой код и так на 80% соответствует заданию. Вам осталось написать второе действие, а также функцию main, в которой вызывать process_array с соответствующими аргументами.
SanAlex
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
15.07.2013, 19:15  [ТС]     Массивы и функции как параметры #7
Ещё такой вопрос: вот вы двумерный массив в списке формальных параметров функции пишете так (**arr)
А разве если просто написать (arr) - это не будет ссылкой на его первый элемент?
Если все же оставить так (**arr), то при вызове какая будет запись массива в фактических параметрах.
Я просто думал когда дело ведётся с массивом, то при описании и вызове его в параметрах, он записывается одинаково -(arr).
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
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, ...);
SanAlex
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];
Извините конечно за такое количество вопросов, просто хочу что бы всё мне понятно было)
Спасибо.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
15.07.2013, 20:43     Массивы и функции как параметры #10
Цитата Сообщение от SanAlex Посмотреть сообщение
Далее, допустим такое описание функции
"Такое описание функции" вызовет ошибку компиляции. Необходимо указать тип.
Цитата Сообщение от SanAlex Посмотреть сообщение
это вообще правильно?
А что, собственно, вас смущает? В списке параметров функции как бы объявляются переменный, доступные в этой функции, но переданные в неё извне. Объявление предполагает указание типа и имени идентификатора. Идентификатор в данном случае - arr, а тип его - int **. Вызов же функции предполагает передачу в неё аргументов соответствующего типа. Там достаточно указывать только идентификаторы. Имя идентификатора в списке формальных (указанных при объявлении функции) и фактических (указанных при вызове функции) параметров могут как совпадать, так и не совпадать, это никакой роли не играет.
Цитата Сообщение от SanAlex Посмотреть сообщение
И что написано в этой строке?
А вот тут я уже начинаю чувствовать себя справочником. Так что вы уж сначала хоть минимальный объём теории изучите, а потом с вопросами. Гугл по запросу "C++ new keyword" выдаст всю необходимую информацию. К тому же советую заглянуть в тему с литературой, раз уж действительно хотите разобраться и понять.
SanAlex
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
16.07.2013, 22:02  [ТС]     Массивы и функции как параметры #11
Спасибо. Однако я ничего не понял. Объясните пожалуйста доступным, для новичка, языком что к чему.
Перерыл весь интернет. Передача двумерных массивом как параметра везде описана по разному.
Кто то в параметрах функции пишет этот массив так: (int **arr)
Кто то так: (int arr[][N])
или даже так (int *arr), тогда какой смысл в первом случае?
Кто нибудь может доступно объяснить при каком описании, какой будет вызов (синтаксически).
И какой вариант лучше и почему, или может каждый вариант хорош для конкретного случая?
И в конце концов что из этого всего называется Массивом указателей, что из них массив массивов?
Надеюсь на вашу снисходительность по отношению к моим "непоняткам". Просто такое расхождение в информации разных источником совсем с толку сбило, и запутало.
Спасибо.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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 ); // для любых (на стеке или в куче) одномерных массивов
Но это имитация, а не настоящий двумерный массив.
Nick Alte
Эксперт С++
1591 / 983 / 116
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
16.07.2013, 22:29     Массивы и функции как параметры #13
Для начала надо понимать, что двумерный массив в памяти не отличается от одномерного - всё его содержимое аккуратно и последовательно разложено в одной непрерывной области памяти. Строки такого массива последовательно размещены друг за другом.
Первый случай (int ** arr) - массив указателей на строки двумерного. Такой вспомогательный массив необходимо создавать и заполнять указателями.
Второй случай (int arr[][N]) - по сути, адрес первого элемента, а синтаксически - тот же двумерный массив. Однако при этом функция жёстко заточена под конкретный N.
Третий случай (int *arr) - тоже адрес первого элемента. Функции передаются размеры массива и она вычисляет линейный индекс из номеров строки и столбца (если массив размерностью M на N, то j-й элемент i-й строки имеет линейный индекс i*M + j).
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
16.07.2013, 22:36     Массивы и функции как параметры #14
Цитата Сообщение от Nick Alte Посмотреть сообщение
что двумерный массив в памяти не отличается от одномерного - всё его содержимое аккуратно и последовательно разложено в одной непрерывной области памяти.
для динамически выделяемых это не так.
Цитата Сообщение от Nick Alte Посмотреть сообщение
Третий случай (int *arr) - тоже адрес первого элемента.
Только вот на преобразования типов будет компилятор ругаться. Да и обрабатывать такой двумерный массив в функции будет не достаточно наглядно. В общем, я об этом уже сказал выше, про имитацию.
Nick Alte
Эксперт С++
1591 / 983 / 116
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
16.07.2013, 22:51     Массивы и функции как параметры #15
Цитата Сообщение от Tulosba Посмотреть сообщение
для динамически выделяемых это не так.
Если имеется в виду коллекция выделенных вразнобой строк - так это и не массив уже в изначальном понимании, там даже строки могут быть разной длины при желании. Но если не считать ученических программ, даже при динамическом выделении памяти имеет смысл выделять весь массив одним куском и "имитировать" двумерность.
Цитата Сообщение от Tulosba Посмотреть сообщение
Только вот на преобразования типов будет компилятор ругаться
Это настолько легко обходится передачей первой строки двумерного массива, что я просто не вижу смысла вообще об этом упоминать. Насчёт недостаточно наглядно - зависит от оформления и от содержимого задачи, иногда даже наглядней может выйти.
Ну и по поводу имитации - это вопрос мнений. Собственно, в случае работы со стековыми двумерными массивами компилятор усердно занимается как раз той самой имитацией.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
16.07.2013, 23:06     Массивы и функции как параметры #16
Цитата Сообщение от Nick Alte Посмотреть сообщение
компилятор усердно занимается
вот когда компилятор занимается такими преобразованиями это хорошо, а когда программист - плохо.
Nick Alte
Эксперт С++
1591 / 983 / 116
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
16.07.2013, 23:16     Массивы и функции как параметры #17
Цитата Сообщение от Tulosba Посмотреть сообщение
вот когда компилятор занимается такими преобразованиями это хорошо, а когда программист - плохо.
Не совсем так. Иногда такие преобразования нужны (в случае тех же динамических массивов, например), и их нужно делать именно программисту. И плохо это будет только в том случае, если он станет их делать раз за разом вместо того, чтобы сделать единожды.
SanAlex
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 );
А как этот двумерный массив будет описан в качестве формального параметра в заголовке функции?
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
28.09.2013, 17:36     Массивы и функции как параметры #19
Цитата Сообщение от SanAlex Посмотреть сообщение
А как этот двумерный массив будет описан в качестве формального параметра в заголовке функции?
C++
1
void f( int** a );
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.09.2013, 17:47     Массивы и функции как параметры
Еще ссылки по теме:

Вычислить суммы с данной точностью е, используя указатели на функции, как параметры C++
C++ Чтение из файла, название передано как параметры функции main argc & argv
C++ Массивы, как параметры функций

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

Или воспользуйтесь поиском по форуму:
SanAlex
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
28.09.2013, 17:47  [ТС]     Массивы и функции как параметры #20
Tulosba,
Блин, а как теперь к массиву обращаться внутри функции? Определённому элементу?
Yandex
Объявления
28.09.2013, 17:47     Массивы и функции как параметры
Ответ Создать тему
Опции темы

Текущее время: 18:31. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru