493 / 426 / 56
Регистрация: 29.04.2011
Сообщений: 443
1

Функция, возвращающая измененный массив

05.01.2014, 22:17. Показов 3499. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Как определить функцию, возвращающую модифицированный массив?
Например:
Код
Вход в функцию: {-1, 2, -3, 4}. 
Выход: функция возвращает новый массив: {2, 4}.
В Pascal/Delphi достаточно объявить пользовательский тип "массив" и назначить его функции в качестве возвращаемого типа.
На списках в Лиспе - очень просто (в примере функция возвращает массив неотрицательных чисел):
Lisp
1
2
3
4
5
(defun F (l)
    (cond 
        ((null l) nil)
        ((< (car l) 0) (F (cdr l)))
        (t (cons (car l) (F (cdr l))))))
Или еще проще:
Lisp
1
2
(defun F (l)
    (remove-if 'minusp l))
Результат:
Lisp
1
(F '(-1 2 -3 4 -5 6 7 -8)) ==> (2 4 6 7)
А как это делается на Си? Привожу пример неудачной попытки это сделать (функция remove_if). На выходе получается "мусор". (см. вложенный скриншот). Хотя сама функция работает корректно: так, если организовать внутри функции цикл и вывести массив полученный массив b, то результатом будет верная последовательность: b = {2,4,6,7}.
Как полученный массив правильно передать "основной программе"? Исправьте пример или приведите свой.
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <stdlib.h>
#define N 8
 
// -----------------------------------------------------------------------------
//                                        Вернуть массив положительных элементов
int * remove_if (int *a, int size, int *n) { 
    
    int i,j,b[N];
    
    for (i=0, j=0; i<size; i++){
        if (a[i] >= 0) {
            b[j] = a[i]; 
            j++;
        }
    }
    // for (i=0; i<j; i++) printf("%d ",b[i]); // b = {2,4,6,7}. Результат верный.
    *n = j;     // Число положит. элементов
    return *b;  // Возвр. массив
}
 
// -----------------------------------------------------------------------------
//                                                                       Печать
int print_array (int *a, int n){ // 
    int i; 
    
    printf("\n Array: \n");
    for (i=0; i<n; i++)
        printf(" %d ",a[i]);
    printf("\n "); 
}
 
// -----------------------------------------------------------------------------
int main(){
 
    int i,b[N],n,a[N] = {-1, 2, -3, 4, -5, 6, 7, -8};
    
    
    print_array (a,N);                                         
    *b = remove_if(a, N, &n); 
    printf("\n\n Total positive elems: %d  \n\n",n);
    print_array (b,n);                //for (i=0; i<n; i++) printf("%d ", b[i]);
    
    
    system("PAUSE");
    return 0;
}
Миниатюры
Функция, возвращающая измененный массив  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.01.2014, 22:17
Ответы с готовыми решениями:

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

Функция, принимающая в качестве аргумента массив значений, и возвращающая наибольший элемент в массиве
Помогите написать на СИ &quot;Создайте функцию, которая принимает в качестве аргумента массив значений...

Отсортировать массив по некоторому числовому полю и вывести измененный массив на экран
Есть задание. Структура Journal хранит информацию о студентах группы: Family, Name, Curs, Group,...

Функция, возвращающая матрицу
можно как-то написать фукцию, которая будет возвращать интовский двухмерный массив?

7
Клюг
7674 / 3189 / 382
Регистрация: 03.05.2011
Сообщений: 8,380
06.01.2014, 14:00 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#define N 8
 
// -----------------------------------------------------------------------------
//                                        Вернуть массив положительных элементов
int * remove_if (int *src, int *size) { 
    
    int i,j, *dst;
    dst = malloc((*size)*sizeof(int)); // выделяем память размером с исходный массив
    for (i=0, j=0; i<(*size); i++){
        if (src[i] >= 0) {
            dst[j] = src[i]; 
            j++;
        }
    }
    dst = realloc(dst,j*sizeof(int)); // уменьшаем до нужного размера
    // for (i=0; i<j; i++) printf("%d ",b[i]); // b = {2,4,6,7}. Результат верный.
    (*size) = j;     // Число положит. элементов
    return dst;  // Возвр. массив
};
 
// -----------------------------------------------------------------------------
//                                                                       Печать
void print_array (int *a, int n){ // 
    int i; 
    
    printf("\n Array: \n");
    for (i=0; i<n; i++)
        printf(" %d ",a[i]);
    printf("\n "); 
};
 
// -----------------------------------------------------------------------------
int main(){
 
    int i,*b,n,a[N] = {-1, 2, -3, 4, -5, 6, 7, -8};
    
    
    print_array (a,N);                                         
    n = N;
    b = remove_if(a, &n); 
    printf("\n\n Total positive elems: %d  \n\n",n);
    print_array (b,n);                //for (i=0; i<n; i++) printf("%d ", b[i]);
    free(b);    //  не забывайте освобождать память перед повторным использованием
    getch();
//    system("PAUSE");
    return 0;
}
1
493 / 426 / 56
Регистрация: 29.04.2011
Сообщений: 443
09.01.2014, 19:02  [ТС] 3
Charles Kludge, спасибо, здесь всё понятно!
А как проделать аналогичные действия с матрицей? Просто выделить память под указатель (*b)[] на массив и правильно передать матрицу "основной программе". Моя реализация неработоспособна - программа просто вылетает до завершения.

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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>
#define N 4
 
// -----------------------------------------------------------------------------
//                                                             Печать матрицы
void print_matrix (int (*a)[N], int n, int m){ // или a[][N], или a[N][N]
    
    int i,j;
    
    for (i=0; i<n; i++){
        for (j=0; j<n; j++){
            printf(" %d ",a[i][j]);
        }
        printf("\n");
    }
}
 
// -----------------------------------------------------------------------------
//                                                             Вернуть матрицу
int (* matrix (int (*a)[N], int n, int m))[N]{
    
    int i,j; 
    int (*b)[m] = (int *) malloc(sizeof(int) * n * m);  // выделить память
    b = (*a)[m];                                        // связать с указателем b
    
    return b;   // возвр. матрицу
    //return a;
}
 
// -----------------------------------------------------------------------------
int main(){
    
    int i,j,n,*b, a[N][N] = {{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7}};
    print_matrix(a,N,N);
    
    b = matrix(a,N,N);
    print_matrix(b,N,N);
    
    system("PAUSE"); //getch();
}
0
923 / 639 / 198
Регистрация: 08.09.2013
Сообщений: 1,693
10.01.2014, 00:20 4
Что-то типа такого. Хотя не знаю, насколько оправдано здесь использовать указатели на массив. Я бы использовал int* во всех случаях.
C
1
2
3
4
5
6
7
8
int (* matrix (int (*a)[N], int n, int m))[N]{
 
  int (*b)[N] = (int (*)[N])  malloc(sizeof(int) * n * m);  // выделить память
  memcpy (b, a, n * m * sizeof (int));                          // копируем туда массив
  b[0][0]= 17;
 
  return b;   // возвр. матрицу
}
Если вам надо саму матрицу "a" изменить, просто меняете значения элементов, и возвращаете её же.
1
493 / 426 / 56
Регистрация: 29.04.2011
Сообщений: 443
10.01.2014, 16:29  [ТС] 5
Цитата Сообщение от gng Посмотреть сообщение
Что-то типа такого. Хотя не знаю, насколько оправдано здесь использовать указатели на массив. Я бы использовал int* во всех случаях.
C
1
2
3
4
5
6
7
8
int (* matrix (int (*a)[N], int n, int m))[N]{
 
  int (*b)[N] = (int (*)[N])  malloc(sizeof(int) * n * m);  // выделить память
  memcpy (b, a, n * m * sizeof (int));                          // копируем туда массив
  b[0][0]= 17;
 
  return b;   // возвр. матрицу
}
Если вам надо саму матрицу "a" изменить, просто меняете значения элементов, и возвращаете её же.
Спасибо. Заменил на вашу функцию - теперь программа работает и нулевой элемент изменен. Но куча ворнингов о неправильном объявлении типа.
А возможно сделать как-то проще, без вспомогательной ф-ции memcpy() или вообще без типа "матрицы": ( int (* matrix (int (*a)[N], int n, int m))[N]), т.е. возвращаемое значение функции выразить, как обыкновенный указатель на целый тип: int * matrix (int (*a)[N], int n, int m)?
Миниатюры
Функция, возвращающая измененный массив   Функция, возвращающая измененный массив  
0
923 / 639 / 198
Регистрация: 08.09.2013
Сообщений: 1,693
10.01.2014, 20:30 6
Цитата Сообщение от route66 Посмотреть сообщение
о куча ворнингов о неправильном объявлении типа.
В других функцих также должны быть объявлены соответствующие типы.
C
1
2
3
4
5
6
7
8
int main(){
  int a[N][N] = {{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7}};
 
  print_matrix(a,N,N);
  int (*b)[N] = matrix(a,N,N);
  print_matrix(b,N,N);
  return 0;
}
Цитата Сообщение от route66 Посмотреть сообщение
А возможно сделать как-то проще, без вспомогательной ф-ции memcpy()
Вы выделяете память под новую матрицу. memcpy копирует туда вашу матрицу.
Другой выринт - модифицировать cуществующую матрицу.
Использование memcpy, strcmp и т.д. - это стиль языка Cи. В плюсах часто пишут по-другому - создают классы и исспользуют оператор присваивания "=".
Цитата Сообщение от route66 Посмотреть сообщение
возвращаемое значение функции выразить, как обыкновенный указатель на целый тип
Да. Мне, например, так ближе.
1
493 / 426 / 56
Регистрация: 29.04.2011
Сообщений: 443
12.01.2014, 15:10  [ТС] 7
Цитата Сообщение от gng Посмотреть сообщение

Да. Мне, например, так ближе.
Спасибо, всё работает, как Вы написали.
Теперь пробую передать указатель на матрицу, как обычный указатель на массив.
Но при попытке присвоить значение элементу матрицы b[0][0] - ошибка: "subscripted value is neither array nor pointer nor vector".
Если опустить строку (b[0][0]=17), то print_matrix(c,N,N) вернет матрицу, но с оговоркой компилятора про несовместимость типа указателя:
[Warning] passing argument 1 of 'print_matrix' from incompatible pointer type [enabled by default].
Как это можно исправить?

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int * matrix2 (int (*a)[N], int n, int m){
 
    int * b = malloc(sizeof(int) * n * m);  // выделить память
    memcpy (b, a, n * m * sizeof (int));                 // копируем туда массив
    //b[0][0]= 17;  //subscripted value is neither array nor pointer nor vector
 
    return b;   // возвр. матрицу
}
// -----------------------------------------------------------------------------
int main() {
 
    int a[N][N] = {{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7}};
    print_matrix(a,N,N);
    
    int *c = matrix2(a,N,N);
    print_matrix(c,N,N);
 
}
0
923 / 639 / 198
Регистрация: 08.09.2013
Сообщений: 1,693
12.01.2014, 17:08 8
Вариант 1 - преобразование к типу указателя на массив из N целых чисел. (удобен, если количество столбцов заранее известно)
C
1
int (*b)[N] = (int (*)[N])matrix2(a,N,N);
Вариант 2. - везде используется int*
Тогда, при N столбцах, доступ к элементу (i,j)
C
1
b[i*N+j]
или, что то же самое
C
1
*(b+i*N+j)
При этом N может быть не известен на стадии компиляции.

Выриант 3 - отдельно выделяется память под каждую строку и идет работа с массивом указателей
C
1
2
int **e= malloc (N * sizeof (int*));
for (i= 0; i < N; i++) e[i]= malloc (N * sizeof (int));
1
12.01.2014, 17:08
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.01.2014, 17:08
Помогаю со студенческими работами здесь

Функция, возвращающая длину массива
Нужна функция, возвращающая длину массива. Но я не могу понять, как ее написать, и принцип ее...

Функция работы со строкой, возвращающая указатель
Вот задание из книги: Напишите функцию под име не м s tring_in ( ) , которая принимает два...

Функция digit(x, i), возвращающая i-тый разряд числа x
Нужна функция, для языка СИ digit( x, i ), возвращающая i -тый разряд числа x

Функция, принимающая три числа, и возвращающая среднее из них
функция на вход принимает три числа должен вернуть среднее среди них например, среди 7, 2, 35 -...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

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