LINUX.ORG.RU

Вот такая задачка на Си...


0

0

Пусть будет массив типа:
double g[3][2] = {
{1.2, 2.8},
{3.1, 4.4},
{5.3, 6.5}
};
или вот такой:
double g[3][2][3] = {
{
{1.1, 1.2, 1.3},
{0.1, 0.2, 0.3}
},
{
{0.4, 0.5, 0.6},
{0.7, 0.8, 0.9}
},
{
{11.1, 11.2, 11.3},
{2.5, 2.2, 1.3}
}
};
Задача: Создать функцию которая принимает любой из n-мерных массивов и распечататывает их элементы и значение. Что-то вроде такого:
(по примеру 1го массива)
[0, 0] = 1.2
[0, 1] = 2.8
[1, 0] = 3.1
...

Вот так я хотел это сделать(наивный ;):
void subpr(void* g, const char* s, int level, int size)
{
int i;
for (i = 0; i < size; ++i) {
if (level-1 > 0) {
char buf[50] = "\0";
sprintf(buf, "%s%d, ", s, i);
subpr(g[i], buf, level-1, length(g[i]));
}
else
printf("%s%d] = %g\n", s, i, (double)g[i]);
}
}
И конечно, в итоге компилятор меня послал на все n-букв массива :)

Кто знает как решить такую задачку, и решить ли вовсе?

> Кто знает как решить такую задачку, и решить ли вовсе? 

Да запросто: 

def print_array(arr):
    for il, line in enumerate(arr):
        for iel, el in enumerate(line):
            print "[%s, %s] = %s" % (il, iel, el)

anonymous
()

Бгы! бесмосклые петоноеды даже условие ниасилили понять :D

> n-мерных массивов

в сях _нету_ n-мерных массивов, только одномерные

bugmaker ★★★★☆
()

Или так:

(defun print_array (arr) (loop for il from 0 for line in arr do (loop for iel from 0 for el in line do (format t "[~d, ~d] = ~d ~%" il iel el))))

anonymous
()

Или так:

(defun print_array (arr) (loop for il from 0 for line in arr do (loop for iel from 0 for el in line do (format t "[~d, ~d] = ~d ~%" il iel el))))

anonymous
()

Или так:

(defun print_array (arr) 
   (loop for il from 0
      for line in arr
      do (loop for iel from 0
	    for el in line
	    do (format t "[~d, ~d] = ~d ~%" il iel el))))

anonymous
()

$ cat 1.c
#include <stdio.h>
#include <string.h>

/**
 * Функция печатает содержимое многомерного массива.
 *
 * @param p     Распечатываемый массив
 * @param sz    Массив размерностей измерений распечатываемого массива
 * @param dim   Количество измерений распечатываемого массива
 */
void
subpr(const double *p, const size_t *sz, size_t dim)
{
        size_t idx[dim];
        size_t i;
        size_t n;
        size_t q;

        memset(idx, 0, sizeof(idx));

cont:
        // Вычисляем смещение
        n = 0;
        q = 1;
        for (i=0; i<dim; ++i) {
                n += idx[i]*q;
                q *= sz[i];
        }

        // Печатаем индекс
        printf("[");
        for (i=0; i<dim; ++i)
                printf("%s%u", i ? ", " : "", idx[i]);
        // Печатаем элемент
        printf("] = %f\n", p[n]);

        // Переходим к следующему элементу
        for (i=0; i<dim; ++i) {
                ++idx[i];
                if (idx[i] < sz[i])
                        goto cont;
                else
                        idx[i] = 0;
        }
}

static double g[3][2][3] = {
        {
                {1.1, 1.2, 1.3},
                {0.1, 0.2, 0.3}
        },
        {
                {0.4, 0.5, 0.6},
                {0.7, 0.8, 0.9}
        },
        {
                {11.1, 11.2, 11.3},
                {2.5, 2.2, 1.3}
        }
};

int
main()
{
        size_t sz[] = { 3, 2, 3};
        subpr(g, sz, 3);
        return 0;
}

$ cc 1.c -o 1

$ ./1
[0, 0, 0] = 1.100000
[1, 0, 0] = 1.200000
[2, 0, 0] = 1.300000
[0, 1, 0] = 0.100000
[1, 1, 0] = 0.200000
[2, 1, 0] = 0.300000
[0, 0, 1] = 0.400000
[1, 0, 1] = 0.500000
[2, 0, 1] = 0.600000
[0, 1, 1] = 0.700000
[1, 1, 1] = 0.800000
[2, 1, 1] = 0.900000
[0, 0, 2] = 11.100000
[1, 0, 2] = 11.200000
[2, 0, 2] = 11.300000
[0, 1, 2] = 2.500000
[1, 1, 2] = 2.200000
[2, 1, 2] = 1.300000

execve
()
Ответ на: комментарий от anonymous

Гаспада питоноводы и лисперы, прочитайте _внимательно_ первоначальные условия. Нужно распечатать n-мерный массив, а не 2-х мерный.

execve
()
Ответ на: комментарий от execve

Ступил, можно проще.

void
subpr(const double *p, const size_t *sz, size_t dim)
{
        size_t idx[dim];
        size_t i;
        size_t n = 0;

        memset(idx, 0, sizeof(idx));

cont:
        // Печатаем индекс
        printf("[");
        for (i=0; i<dim; ++i)
                printf("%s%u", i ? ", " : "", idx[i]);
        // Печатаем элемент
        printf("] = %f\n", p[n++]);

        // Переходим к следующему элементу
        for (i=0; i<dim; ++i) {
                ++idx[i];
                if (idx[i] < sz[i])
                        goto cont;
                else
                        idx[i] = 0;
        }
}

execve
()
Ответ на: комментарий от execve

Или ещё проще ;)

void
subpr(const double *p, const size_t *sz, size_t dim)
{
        size_t idx[dim];
        size_t i;

        memset(idx, 0, sizeof(idx));

cont:
        // Печатаем индекс
        printf("[");
        for (i=0; i<dim; ++i)
                printf("%s%u", i ? ", " : "", idx[i]);
        // Печатаем элемент
        printf("] = %f\n", *p++);

        // Переходим к следующему элементу
        for (i=0; i<dim; ++i) {
                ++idx[i];
                if (idx[i] < sz[i])
                        goto cont;
                else
                        idx[i] = 0;
        }
}

execve
()
Ответ на: комментарий от anonymous

Не позорься перед питоноедами, это не будет выводить массив с произвольной размерностью.

bugmaker ★★★★☆
()
Ответ на: комментарий от Pi

Плохо влияете на разнузданную толпу и провоцируете нездоровые тенденции, товарищ!

http://eli-project.sourceforge.net/c_html/c.html#m163

http://en.wikipedia.org/wiki/C_(programming_language)

> Theca Array procul C vox per secundum nonnullus dimension ampersand plerumque secundum jugiter no denotement per compilation.

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

Почитал стандарт. Действительно, узнать размер массива в рантайме нельзя...

yz
()

Короче при помощи ваших советов и своей головы, в итоге сделал вот такую функцию:
void subpr(const double* g, const size_t dims[], size_t cdims)
{
int offset = 0;

void pr(const char* s, int level) {
int i;
int c = dims[level];
for (i = 0; i < c; ++i) {
if (level < cdims-1) {
char buf[50] = "\0";
sprintf(buf, "%s%d, ", s, i);
pr(buf, level+1);
}
else {
printf("%s%d] = %g\n", s, i, *(g + offset));
++offset;
}
}
}

pr("[", 0);
}

А вызываю вот так:
const size_t dims[] = {3, 2, 3};
double g[3][2][3] = {
{
{0.1, 0.2, 0.3},
{1.1, 1.2, 1.3},
},
{
{4.5, 3.2, 9.1},
{1.3, 6.7, 2.3},
},
{
{4.2, 3.3, 5.1},
{1.1, 1.7, 4.3},
}
};
subpr(g, dims, length(dims));

anterior
() автор топика
Ответ на: комментарий от gshladgs

> Ты чему детей учишь?

Религиозная ненависть застилает глаза? ;)

Если с goto код будет проще и понятнее, чем без него, то я (и далеко не только я) предпочту goto.

execve
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.