html:
toc: true

写在前面:

  • 出于作者不了解C99以前标准中对二维数组的动态声明而导致的一场考场事故,作者写下这篇文章,,以便其他同学在遇到类似问题时不要犯同样的错误,同时作为对自己的警醒.
  • 本文主要是关于对于二维数组动态声明问题在不同C标准下方法的探讨,将给出一个简单的实例,以便读者能够快速理解.
  • 作者水平有限,若有错误,还请指正.

一个简单的实例

  • 题目描述:

    对输入的一个矩阵的偶数列分别求和并输出;

    输入说明:输入两个整数m,n代表矩阵的行数和列数,接下来输入m行,每行n个整数,代表矩阵的元素,数与数之间以空格隔开;

    输出说明:先输出偶数列的个数,然后输出每个偶数列所有元素的和,每个和后面有一个空格;

    输入示例:

    3 4

    3 5 6 7

    9 5 8 2

    6 5 8 7

    输出示例:

    2

    15 16
  • 要解决这个问题,我们可以声明一个二维数组,然后控制输入输出流程完成问题即可.但是注意到矩阵的行列数是未知的,因此我们需要使用动态数组来完成这个任务.

C99标准以及C99标准之后

在C99标准之后,要完成这个问题,只需要引入变长数组(variable length array)方法即可简单完成.

#include <stdio.h>
int main(void){
int m, n;
scanf("%d %d", &m, &n);
int matrix[m][n];
// 输入矩阵元素
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
scanf("%d", &matrix[i][j]);
// 计算偶数列的和
int sum[n / 2]; // 用于存储每个偶数列的和
int count = 0; // 偶数列的个数
for (int j = 1; j < n; j += 2){
int column_sum = 0;
for (int i = 0; i < m; i++){
column_sum += matrix[i][j];
}
sum[count++] = column_sum;
}
printf("%d\n", count);
for (int i = 0; i < count; i++){
printf("%d ", sum[i]);
}
return 0;
}

可以看到,对于二维数组的动态声明,使用变长数组方法可以直接使用类似于int matrix[m][n]这样的语句完成.

但是要注意的是,变长数组方法只能在C99标准之后使用,因为该方法是在C99标准中引入的,在C99之前,使用变长数组方法会报错.要动态分配二维数组,要借助指针传参.

现行部分学校旧OJ系统使用C89(C90)标准,使用变长数组将无法完成编译(血泪教训)

C99标准以前

在C99标准之前,要完成这个问题,我们需要使用指针来完成.

通常的步骤为:

  1. 声明一个指向指针的指针,用于保存动态分配的二维数组的首地址
  2. 使用malloc函数动态分配一个包含n行的指针数组,每个指针指向一个包含m个元素的一维数组
  3. 对分配的二维数组进行赋值或操作
  4. 在不需要使用该数组时,使用free函数释放分配的内存

    具体示例如下:
#include <stdio.h>
#include <stdlib.h>//使用malloc函数需要
int main(void){
int m, n;
scanf("%d %d", &m, &n);
//分配指向指针的指针数组
int **matrix = (int **)malloc(m * sizeof(int *));
//对每一行再分配空间并输入
for (int i = 0; i < m; i++){
matrix[i] = (int *)malloc(n * sizeof(int));
for (int j = 0; j < n; j++){
scanf("%d", &matrix[i][j]);
}
}
// 计算偶数列的和
int sum[n / 2]; // 用于存储每个偶数列的和
int count = 0; // 偶数列的个数
for (int j = 1; j < n; j += 2){
int column_sum = 0;
for (int i = 0; i < m; i++){
column_sum += matrix[i][j];
}
sum[count++] = column_sum;
}
// 输出结果
printf("%d\n", count);
for (int i = 0; i < count; i++){
printf("%d ", sum[i]);
}
// 释放内存
for (int i = 0; i < m; i++){
free(matrix[i]);
}
free(matrix);
matrix = NULL;
return 0;
}

C99标准前后对于二维数组的动态声明问题的更多相关文章

  1. C++二维数组的动态声明

    int **a  =  new int* [m]   //分配一个指针数组,将其首地址保存在a中   . for(int i = 0; i < m; i++)   //为指针数组的每个元素分配一 ...

  2. JAVASE(八) 数组: 一维数组、二维数组、动态数组、静态数组

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.一维数组 1.1 数组的声明和初始化声明方式: String str[]; //不建议使用 Stri ...

  3. C语言数组:C语言数组定义、二维数组、动态数组、字符串数组

    1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...

  4. C语言学习笔记 (005) - 二维数组作为函数参数传递剖析

    前言 很多文章不外乎告诉你下面这几种标准的形式,你如果按照它们来用,准没错: //对于一个2行13列int元素的二维数组 //函数f的形参形式 f(int daytab[2][13]) {...} / ...

  5. c++ 二维数组传递

    c++ 二维数组传递 我们在传递二维数组时,对于新手来说,可能会存在某些问题,下面讲解几种传递方法 在讲解如何传递二维数组时,先看看如何动态new 二维数组 // 二维数组动态申请 int row , ...

  6. 【C语言入门教程】4.2 二维数组

    C 语言允许使用多维数组,即使用多组小标的数组,二维数组是最常用的多维数组.多维数组在内存中存放数据的顺序与一维数组相同,使用连续的存储单元. 4.2.1 二维数组的一般形式 二维数组的一般声明形式为 ...

  7. 《Java大学教程》—第16章 二维数组

    多维(Multi-dimensional)数组维数由索引个数决定.常用的数组:一维(one-dimensional)数组.二维(two-dimensional)数组 16.2    创建二维数组索引从 ...

  8. js一维数组转换为二维数组

    function arrTrans(num, arr) { // 一维数组转换为二维数组 const iconsArr = []; // 声明数组 arr.forEach((item, index) ...

  9. Java连载68-数组的拷贝、二维数组

    一.数组的拷贝 函数arraycopy(),参数为:源数组.源数组的开始下标.目标数组.目标数组的开始下标.拷贝长度 package com.bjpowernode.java_learning; ​ ...

  10. C# 二维数组 [,]与[][] 的区别 及特性

    arr[,] 用于声明等长的二维数组 Eg: //声明数组有3行 每行长度相等为2 var s = new int[3, 2] { { 1, 2 }, { 3, 4 }, { 1, 4 } }; 获取 ...

随机推荐

  1. SNN_SRM模型

    # SRM模型 ## 早期SRM模型 Spike Response Modul(SRM)模型将传统的LIF微分模型换成了一个关于输入.输出的脉冲函数,可以将脉冲神经网络简化为第二代神经网络. 基本公式 ...

  2. 数论笔记(Full Version)

    数论笔记(Full Version) 一.数论基础: 1.整除: 重新定义除法: 对于计算式:\(a\div b\) 来说,其结果可以变化为以下的式子:$$a = b\lfloor \frac{a}{ ...

  3. 【MySQL】MySQL中的锁

    全局锁 全局锁是对整个数据库实例加锁,整个库处于只读状态. flush tables with read lock 适用场景 全局锁适用于做全库逻辑备份,但是整个库处于只读状态,在备份期间,所有的更新 ...

  4. 微信小程序动态生成表单来啦!你再也不需要手写表单了!

    dc-vant-form 由于我们在小程序上涉及到数据采集业务,需要经常使用表单,微信小程序的表单使用起来非常麻烦,数据和表单是分离的,每个输入框都需要做数据处理才能实现响应式数据,所以我开发了dc- ...

  5. 记一次有趣的hwclock写RTC的PermissionDenied错误

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   无 前言   稍微接触过嵌入式板卡的,基本都知道嵌 ...

  6. 思科4331 语音网关配置, cisco 4331 router 配置文件

    GW01#cisco_ROUTER01#cisco_ROUTER01#sh clocisco_ROUTER01#cisco_ROUTER01#cisco_ROUTER01#cisco_ROUTER01 ...

  7. nginx 反向代理teleport

    nginx 反向代理teleport 普通配置(以Nginx服务与TP服务在同一台主机上为例) # ...其他内容... server { listen 80; server_name www.you ...

  8. 10个必备的 async/await 工具函数

    | 当谈到异步编程时,async/await是JavaScript中常用的功能之一.下面是10个常用的await和async函数示例,以及对它们的代码用途的解析: 1.异步获取数据 async fun ...

  9. 新报: 根据IP获取物理地址不需要调用接口啦

    一. 复制data文件夹到自己的项目当中 可以进行加载到这个文件即可 博主放入在项目的根目录当中 请移步Gitee pull 该文件 https://gitee.com/yangbuyi/ip_fil ...

  10. 微软成为PostgreSQL主要贡献者

    微软成为PostgreSQL主要贡献者 微软对PostgreSQL贡献的很多新功能都来自于客户在使用微软Azure上的PostgreSQL管理实例数据库,所以这些新功能都来自于真实的客户需求 微软对P ...