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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.56
SanAlex
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 28
#1

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

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

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

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

main -> промежуточная функция (3 параметра), определяются нужные столбцы -> функция(действие над выбранными столбцами)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.06.2013, 18:14
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Массивы и функции как параметры (C++):

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

Как сделать выходные параметры у функции? - C++
мне нужно чтобы переменная s сохраняла свое значение после работы функции(которая на самом деле процедура, токо я не знал как по другому...

Как вызвать из 1 функции параметры другой? - C++
Всем привет! Собственно, вопрос в названии. Хочу написать 2 функции: первая отводит память под массив, а вторая этот массив...

Какими способами можно использовать функции класса B, как параметры функции Sub класса А? - C++
class A {... void Sub(...); ...} class B : ... { public: float f1(float); float f2(float); ...

Как работают приведенные функции, какие у них параметры? - C++
Доброго времени суток!!! Не знаю, как работают такие функции (какие параметры вводить, и что должно вывести): atoi() itoa() max()

Как задать параметры запуска (аргументы командной строки) функции main? - C++
Как их задать в процессе запуска? т.е. пользователь запускает приложение и указывает параметры запуска при этом. Где про них почитать...

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

Вычислить суммы с данной точностью е, используя указатели на функции, как параметры - C++
Используйте указатели на функции как параметры: \sum_{n=1}^{\infty}\frac{sin \, n}{n} \sum_{n=1}^{\infty}\frac{n}{e^n}

Чтение из файла, название передано как параметры функции main argc & argv - C++
Вообще дано задание - считать из файла чётные строки, название файла должно быть передано как параметр при запуске из командной строки.. ...

Указатели и массивы. Индексация с помощью указателей. Передача массивов в функции. Динамические массивы (обработка матриц) - C++
Для каждого элемента , bij, i= 1,...,n , j=1,...,n определяется свой многоугольник местонахождением соответствующего элемента aij (см....

Как сделать динамические массивы вместо обычных? Используя функции - C++
Как сделать динамические массивы вместо обычных? Используя функции. Для введения одной матрицы нужна одна функция? т.е. чтобы ввести 2...


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

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
16.07.2013, 22:51
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru