C码字练习.08.数组与指针 - 北方连萌

C码字练习.08.数组与指针

行和,列和,总和的指针求法

C中数组和指针有着紧密的关系
例如数组名可以同时看作指向数组首个元素的指针
对于一维数组

a[i] == *(a + i)

对于二维数组

a[i][j] == *(*(a + i) + j)

所以行和,列和,总和除了数组求法,也有指针求法

#include <stdio.h>
#define COL 3
#define ROW 2
int main(void)
{
   int i, j, t, t1 = 0, cc = 0, cr = 0;
   int ar[ROW][COL] = {{1,2,3},{4,5,6}};

   for (i = 0; i < COL; i++)
   {
      t = 0;
      for (j = 0; j < ROW; j++)
      {
         t += *(*(ar + j) + i);
      }
      cc++;
      printf("sum of column %d = %d\n", cc, t);
   }

   for (i = 0; i < ROW; i++)
   {
      t = 0;
      for (j = 0; j < COL; j++)
      {
         t += *(*(ar + i) + j);
      }
      cr++;
      printf("sum of row %d = %d\n", cr, t);
   }

   for (i = 0; i < ROW; i++)
   {
      t = 0;
      for (j = 0; j < COL; j++)
      {
         t += *(*(ar + i) + j);
      }
      t1 += t;
   }
   printf("sum in total = %d\n", t1);

   return 0;
}
sum of column 1 = 5
sum of column 2 = 7
sum of column 3 = 9
sum of row 1 = 6
sum of row 2 = 15
sum in total = 21

拷贝数组(一维)

数组不能被整个操作,只能对其中单个元素进行操作
另外如果不对数组初始化,则数组中全部是随机(?)值
具体如下

#include <stdio.h>
void copy_arr(int a[], int b[], int c);
void copy_ptr(int a[], int b[], int c);
void copy_ptrs(int * a, int * b, int * c);
int main(void)
{
   int a[] = {1,2,3,4,5};
   int b[5];
   int c[5];
   int d[5];
   int e[5];
   int i;
   int *pt = a;

   for (i = 0; i < 5; i++)
   {
      printf("%d ", b[i]);
   }
   putchar('\n');

   copy_arr(a, b, 5);
   for (i = 0; i < 5; i++)
   {
      printf("%d ", b[i]);
   }
   putchar('\n');putchar('\n');

   for (i = 0; i < 5; i++)
   {
      printf("%d ", c[i]);
   }
   putchar('\n');
   
   copy_ptr(a, c, 5);
   for (i = 0; i < 5; i++)
   {
      printf("%d ", c[i]);
   }
   putchar('\n');putchar('\n');

   for (i = 0; i < 5; i++)
   {
      printf("%d ", d[i]);
   }
   putchar('\n');
   
   copy_ptrs(a, d, a + 5);
   for (i = 0; i < 5; i++)
   {
      printf("%d ", d[i]);
   }
   putchar('\n');putchar('\n');

   for (i = 0; i < 5; i++)
   {
      printf("%d ", e[i]);
   }
   putchar('\n');
     
   copy_ptrs(pt + 1, e, pt + 4); //用指针实现部分拷贝
   for (i = 0; i < 3; i++)
   {
      printf("%d ", e[i]);
   }
   putchar('\n');putchar('\n');

   return 0;
}
//数组方法
void copy_arr(int a[], int b[], int c)
{
   int i;

   for (i = 0; i < c; i++)
   {
      b[i] = a[i];
   }
}
//指针方法
void copy_ptr(int a[], int b[], int c)
{
   int i;

   for (i = 0; i < c; i++)
   {
      *(b + i) = *(a + i);
   }
}
//递增指针直至其指向数组界外的下一个元素(下两个及以后的不可)
void copy_ptrs(int * a, int * b, int * c)
{
   while (a < c)
   {
      *b = *a;
      //如果对指针加1,则增加1个存储单位(此处int即4字节)
      //在数组中,也表示指针指向了下一个元素
      a++;
      b++;
   }
}
4200656 0 16 0 0 
1 2 3 4 5 

8259424 0 -1152394762 32762 8 
1 2 3 4 5 

4199744 0 8 0 0 
1 2 3 4 5 

8259416 0 -1152394762 32762 4206600 
2 3 4 

拷贝数组(二维)

使用拷贝一维数组的函数拷贝每一行
递增指针指针进行换行
但要注意此处指针指向的是一个数组(即一整行),声明形式为

type (*name)[index];

括号不可去掉,否则

type * name[index];

表示的是指针数组(数组里的元素都是指针)

具体如下,可以看到函数完全不用动,只要在主程序里用对指针即可

#include <stdio.h>
void copy_ptr(int a[], int b[], int c);
void print_array(int a[][3], int b);
int main(void)
{
   int (*start)[3];
   int (*b0)[3];
   int b[3][3];
   int a[3][3] = {
      {1,4,9},
      {3,5,7},
      {2,6,0}
   };
   start = a;
   b0 = b;
   while (start < a + 3)
   {
      copy_ptr(*start, *b0, 3);
      b0++;
      start++;
   }
   print_array(a, 3); //打印a
   putchar('\n');
   print_array(b, 3); //打印b作对照


   return 0;
}

void copy_ptr(int a[], int b[], int c)
{
   int i;

   for (i = 0; i < c; i++)
   {
      *(b + i) = *(a + i);
   }
}

void print_array(int a[][3], int b)
{
   int i, j;
   
   for (i = 0; i < b; i++)
   {
      for (j = 0; j < 3; j++)
      {
         printf("%d ", a[i][j]);
      }
      putchar('\n');
   }
}
1 4 9 
3 5 7
2 6 0

1 4 9
3 5 7
2 6 0

找出数组最值

Fortran版:

见此

#include <stdio.h>
void min(double a[], int b);
void max(double a[], int b);
void reverse(double * a, int b);
int main(void)
{
   double b[] = {44.12,55.45,1.25,12.56,12.14,77.25};
   min(b, sizeof(b) / sizeof(*b));
   max(b, sizeof(b) / sizeof(*b));
   reverse(b, sizeof(b) / sizeof(*b));

   return 0;
}

void min(double * a, int b)
{
   double min = *a;
   int i, d;
   
   for (i = 0; i < b; i++)
   {
      if (a[i] < min)
      {
         min = a[i];
         d = i;
      }
      else
      {
         continue;
      }
   }
   printf("min = a[%d] = %f\n", d + 1, min);
   
}

void max(double * a, int b)
{
   double max = a[0];
   int i, d;
   
   for (i = 0; i < b; i++)
   {
      if (a[i] > max)
      {
         max = a[i];
         d = i;
      }
      else
      {
         continue;
      }
   }
   printf("max = a[%d] = %f\n", d + 1, max);
   
}

void reverse(double * a, int b)
{
   int i;

   printf("Array entered in reverse order:\n");
   for (i = b; i > 0; i--)
   {
      printf("%.2f ", *(a + i - 1));
   }
}
min = a[3] = 1.250000
max = a[6] = 77.250000
Array entered in reverse order:
77.25 12.14 12.56 1.25 55.45 44.12

矩阵的加法,标量倍,乘法

向函数传入数组,一维时元素个数单独传入

func_d1(int x[], int y);

二维及更高的数组只有最左边的括号是可以空的,用来传入一维上的元素个数

func_d3(int x[][2][3][4], int y);

当然使用变长数组传入每个维度的值的话会显得明了一些

func_vla(int x, int y, int z, int a[x][y][z])

具体如下

#include <stdio.h>
void matrix_addition(int m, int n, int a[m][n], int b[m][n], int c[m][n]);
void scalar_multiplication(int m, int n, int t, int a[m][n], int b[m][n]);
void matrix_multiplication(int m, int n, int p, int a[m][n], int b[n][p], int c[m][p]);
int main(void)
{
   //使用复合字面量,省略声明数组
   matrix_addition(2, 2, (int[][2]){{1,2},{3,4}}, (int[][2]){{5,6},{7,8}}, (int[][2]){});
   putchar('\n');
   scalar_multiplication(2, 2, 4, (int[][2]){{5,6},{7,8}}, (int[][2]){});
   putchar('\n');
   matrix_multiplication(4, 3, 4, (int[4][3]){2,3,7,7,8,9,2,3,7,7,8,9}, (int[3][4]){2,3,7,7,8,9,2,3,7,7,8,9}, (int[4][4]){});
   return 0;
}

void matrix_addition(int m, int n, int a[m][n], int b[m][n], int c[m][n])
{
   int i, j;

   for (i = 0; i < m; i++)
   {
      for (j = 0; j < n; j++)
      {
         *(*(c + i) + j) = *(*(a + i) + j) + *(*(b + i) + j);
      }
   }
   for (i = 0; i < m; i++)
   {
      for (j = 0; j < n; j++)
      {
         printf("%-5d ", c[i][j]);
      }
      putchar('\n');
   }
}

void scalar_multiplication(int m, int n, int t, int a[m][n], int b[m][n])
{
   int i, j;

   for (i = 0; i < m; i++)
   {
      for (j = 0; j < n; j++)
      {
         *(*(b + i) + j) = (*(*(a + i) + j)) * t ;
      }
   }
   for (i = 0; i < m; i++)
   {
      for (j = 0; j < n; j++)
      {
         printf("%-5d ", b[i][j]);
      }
      putchar('\n');
   }
}

void matrix_multiplication(int m, int n, int p, int a[m][n], int b[n][p], int c[m][p])
{
   int i, j, k;

   for (i = 0; i < m; i++)
   {
      for (j = 0; j < p; j++)
      {
         for (k = 0; k < n; k++)
         {
            c[i][j] += a[i][k] * b[k][j];
         }
      }
   }
   for (i = 0; i < m; i++)
   {
      for (j = 0; j < p; j++)
      {
         printf("%-5d ", c[i][j]);
      }
      putchar('\n');
   }
}
6     8
10    12

20    24
28    32

77    82    76    86
141   156   137   154
77    82    76    86
141   156   137   154

逐行传入/整体传入

#include <stdio.h>
void save(int m, double a[m]);
void print_array(int m, int n, double a[m][n]);
double row_average(int m, double a[m]);
double all_average(int m, int n, double a[m][n]);
double max(int m, int n, double a[m][n]);

int main(void)
{
   double c[3][5];
   double (*pt)[5];
   int i;

   pt = c;
   for (i = 0; i < 3; i++)
   {
      save(5, *(pt + i));
      fflush(stdin); //不保存第五项以后的输入
   }
   putchar('\n');
   printf("Matrix you entered:\n");
   print_array(3, 5, pt);
   putchar('\n');
   //pt是指向一维数组的指针,对其解引用(*pt)就是矩阵的第一行,对pt做加法就可以指向下几行
   for (i = 0; i < 3; i++)
   {
      printf("Average of row %d:\n", i + 1);
      printf("%.2f\n", row_average(5, *(pt + i)));
      putchar('\n');
   }
   printf("Average of all elements:\n");
   printf("%.2f\n", all_average(3, 5, pt));
   putchar('\n');
   printf("Maximum in all elements:\n");
   printf("%.2f\n", max(3, 5, pt));

   return 0;
}
//逐行保存
void save(int m, double a[m])
{
   int i;
   
   printf("Please enter %d numbers.\n", m);
   a:
   for (i = 0; i < m; i++)
   {
      while (scanf("%lf", &a[i]) != 1)
      {
         printf("%d numbers, please.\n", m);
         fflush(stdin); //防无限循环
         goto a;
      }
   }
}
//逐行求平均
double row_average(int m, double * a)
{
   int i;
   double z = 0;

   for (i = 0; i < m; i++)
   {
      z += *(a + i);
   }
   
   return z / m;
}
//全矩阵求平均
double all_average(int m, int n, double a[m][n])
{
   int i, j, s = 0;
   
   for (i = 0; i < m; i++)
   {
      for (j = 0; j < n; j++)
      {
         s += a[i][j];
      }
   }

   return (double)s / (m * n);
}
//打印矩阵
void print_array(int m, int n, double a[m][n])
{
   int i, j;
   
   for (i = 0; i < m; i++)
   {
      for (j = 0; j < n; j++)
      {
         printf("%.2f ", a[i][j]);
      }
      putchar('\n');
   }
}
//全矩阵求最大值
double max(int m, int n, double a[m][n])
{
   int i, j;
   double maximum = a[0][0];

   for (i = 0; i <= m; i++)
   {
      for (j = 0; j <= n; j++)
      {
         if (a[i][j] > maximum)
         {
            maximum = a[i][j];
         }
         else
         {
            continue;
         }
      }
   }

   return maximum;
}
Please enter 5 numbers.
1 4 7 8 58 5 4 8 5
Please enter 5 numbers.
7 [ l 4 5 
5 numbers, please.
7 4 8 9 54 8 65 
Please enter 5 numbers.
7 4 84 9 5 6 9 8

Matrix you entered:
1.00 4.00 7.00 8.00 58.00
7.00 4.00 8.00 9.00 54.00
7.00 4.00 84.00 9.00 5.00

Average of row 1:
15.60

Average of row 2:
16.40

Average of row 3:
21.80

Average of all elements:
17.93

Maximum in all elements:
84.00

添加新评论

电子邮件地址不会被公开,评论内容可能需要管理员审核后显示。