如何改变数组的“几何”?

时间:2013-12-28 15:29:36

标签: c arrays pointers ansi

如何将数组的“几何”从一维更改为二维(从线性数组到平方矩阵)?

在我的代码中,我有一个函数返回data,定义为:

unsigned long *data = malloc(sizeof(unsigned long) * 9);

接收data的函数正在使用该指针作为调用另一个函数的参数:

sumOfColTwo(data);

但我希望该函数能够访问数组,就好像它是一个3x3矩阵一样。例如,要计算我希望能够执行的列的总数:

void sumOfColTwo(<some-declaration-here>) {
    for (i=0; i<3; i++)
        sum += data[1][i]
}

换句话说,给定一个线性数组:

A B C D E F G H I

我想以逻辑方式“访问”以下两种形式之一:

A B C          A D G
D E F    or    B E H
G H I          C F I

[我正在使用ANSI C(C89)]

修改

根据评论中的要求,以下是我如何生成原始data

unsigned long *load_input(void) {

    unsigned long *data = malloc(sizeof(unsigned long) * 9);

    unsigned char i, parsed;
    for (i=0; i<9; i++) {
        parsed = scanf("%lu", &data[i]);
    }

    /* Return the appropriate value (eventually freeing unused memory) */
    if (parsed == 1) {
        return data;
    } else {
        free(data);
        return NULL;
    }
}

4 个答案:

答案 0 :(得分:2)

虽然我认为不是“改变”几何,而是“重新解释”它,但是遵循一些方法。

这样做:

void print1dAs2d(unsigned long * _data) 
{
  unsigned long (*data)[3][3] = (unsigned long (*)[3][3]) _data; /* Hide away the dirty cast. */

  for (size_t i = 0; i < 3; ++i)
  {
    for (size_t j = 0; j < 3; ++j)
    {
      printf("%lu ", (*data)[i][j]);
    }

    printf("\n");
  }
}

比如这样称呼:

int main(void)
{
  unsigned long data[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

  print1daAs2d(data);

  return 0;
}

为NxM矩阵设置这个通用(假设至少为C99)是这样的:

void print1dAs2d_NxM(size_t n, size_t m, unsigned long * _data) 
{
  unsigned long (*data)[n][m] = (unsigned long (*)[n][m]) _data; /* Hide away the dirty cast. */

  for (size_t i = 0; i < n; ++i)
  {
    for (size_t j = 0; j < m; ++j)
    {
      printf("%lu ", (*data)[i][j]);
    }

    printf("\n");
  }
}

对于C89,使用纯指针算术的经典方法:

void print1dAs2d_NxM(size_t n, size_t m, unsigned long * data) 
{
  for (size_t i = 0; i < n; ++i)
  {
    for (size_t j = 0; j < m; ++j)
    {
      printf("%lu ", *(data + i*m + j);
    }

    printf("\n");
  }
}

这种老式的C89兼容方法在没有任何演员的情况下相处得很好......但是有趣的是。 ; - )

答案 1 :(得分:1)

样品

#include <stdio.h>
#include <stdlib.h>

unsigned long sumOfColTwo(unsigned long *data){
    unsigned long sum = 0;
    unsigned long (*datap)[3] = (unsigned long (*)[3])data;
    int i;
/*
    for (i=0; i<3; i++)
        sum += datap[i][1];
*/
    for (i=0; i<3; i++){
        printf("%d %lu \n", i, datap[i][1]);
        sum += datap[i][1];
    }
    return sum;
}

int main(){
    unsigned long *data = malloc(sizeof(unsigned long) * 9);
    int i;
    for(i = 0 ; i < 9 ; ++i)
        data[i] = i;
    printf("%lu\n", sumOfColTwo(data));
    free(data);
    return 0;
}

答案 2 :(得分:1)

如果您想以下列之一访问9值数组:

A B C          A D G
D E F    or    B E H
G H I          C F I

然后你将自己简化为计算数组下标。这是C89代码,它将完成这项工作。它被硬编码为3x3矩阵,因为这是给出的示例。要概括为NxM矩阵并不是很难。

#include <stdio.h>

static void sum_by_rows(int data[9])
{
    int i, j;
    for (i = 0; i < 3; i++)
    {
        int sum = 0;
        for (j = 0; j < 3; j++)
            sum += data[i*3+j];
        printf("Sum row %d = %d\n", i, sum);
    }
}

static void sum_by_cols(int data[9])
{
    int i, j;
    for (i = 0; i < 3; i++)
    {
        int sum = 0;
        for (j = 0; j < 3; j++)
            sum += data[j*3+i];
        printf("Sum col %d = %d\n", i, sum);
    }
}

int main(void)
{
    int data[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' };
    int i, j;

    printf("By rows\n");
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
            printf("A[%d][%d] = %c (%d)\n", i, j, data[i*3+j], data[i*3+j]);
    }

    printf("By cols\n");
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
            printf("A[%d][%d] = %c (%d)\n", i, j, data[j*3+i], data[j*3+i]);
    }

    sum_by_cols(data);
    sum_by_rows(data);
    return 0;
}

输出:

By rows
A[0][0] = A (65)
A[0][1] = B (66)
A[0][2] = C (67)
A[1][0] = D (68)
A[1][1] = E (69)
A[1][2] = F (70)
A[2][0] = G (71)
A[2][1] = H (72)
A[2][2] = I (73)
By cols
A[0][0] = A (65)
A[0][1] = D (68)
A[0][2] = G (71)
A[1][0] = B (66)
A[1][1] = E (69)
A[1][2] = H (72)
A[2][0] = C (67)
A[2][1] = F (70)
A[2][2] = I (73)
Sum col 0 = 204
Sum col 1 = 207
Sum col 2 = 210
Sum row 0 = 198
Sum row 1 = 207
Sum row 2 = 216

使用3x4阵列的更一般情况:

#include <stdio.h>

enum { N_ROWS = 3, N_COLS = 4 };

static void sum_by_rows(int data[N_ROWS * N_COLS])
{
    int i, j;
    for (i = 0; i < N_ROWS; i++)
    {
        int sum = 0;
        for (j = 0; j < N_COLS; j++)
            sum += data[i*N_COLS+j];
        printf("Sum row %d = %d\n", i, sum);
    }
}

static void sum_by_cols(int data[N_ROWS * N_COLS])
{
    int i, j;
    for (i = 0; i < N_COLS; i++)
    {
        int sum = 0;
        for (j = 0; j < N_ROWS; j++)
            sum += data[i*N_ROWS+j];
        printf("Sum col %d = %d\n", i, sum);
    }
}

int main(void)
{
    int data[N_ROWS * N_COLS];
    int i, j;

    for (i = 0; i < N_ROWS * N_COLS; i++)
        data[i] = 'A' + i;

    printf("By rows\n");
    for (i = 0; i < N_ROWS; i++)
    {
        for (j = 0; j < N_COLS; j++)
            printf(" %c", data[i*N_COLS+j]);
        putchar('\n');
    }

    printf("By cols\n");
    for (i = 0; i < N_COLS; i++)
    {
        for (j = 0; j < N_ROWS; j++)
            printf(" %c", data[j*N_ROWS+i]);
        putchar('\n');
    }

    sum_by_cols(data);
    sum_by_rows(data);
    return 0;
}

输出:

By rows
 A B C D
 E F G H
 I J K L
By cols
 A D G
 B E H
 C F I
 D G J
Sum col 0 = 198
Sum col 1 = 207
Sum col 2 = 216
Sum col 3 = 225
Sum row 0 = 266
Sum row 1 = 282
Sum row 2 = 298

我注意到必须使用古老的C89标准会让你感到困惑。如果可以使用C99和VLA(可变长度数组),则可以执行更多有趣的数组操作。

答案 3 :(得分:1)

给定x个行数和y个列数并假设偏移量为零(对于行和列都将第一个索引设为零),然后计算行顺序偏移量(问题中的左矩阵)为:

row_order offset = <row index> * x + <column index>

按列顺序执行的计算(问题中的右边矩阵)将是:

column order offset = <column index> * y + <row index> 

where <row index> is the index into the row you want to access and
      <column index> is the column you want to access. 

然后,您可以通过指针(*(数据+偏移))或索引(数据[偏移])访问数据。