C语言KR圣经笔记 5.7多维数组 5.8指针数组初始化 5.9指针vs多维数组

news2024/11/19 17:30:09

5.7 多维数组

C 提供了矩形的多维数组,虽然实际上它们用得比指针数组少得多。本节我们将展示多维数组的一些特性。

考虑下日期转换的问题:把某月的第几天转换为当年的第几天,以及反向转换。例如,3月1日是非闰年的第60天,是闰年的第61天。我们定义两个函数来做这个转换:day_of_year 把月和日转换为年的第几天,month_day 把年的第几天转换成月和日。因为第二个函数要计算两个值,所以月和日这两个参数会是指针:

month_day(1988, 60, &m, &d)

会将 m 设为 2,d 设为 29(2月29日)。

这两个函数需要相同的信息,每个月有多少天的表格(“七月大、八月大、九月小...”)。由于闰年和平年月份的天数不一样,把这些数据分开放到二维数组的两行,会比计算时去判断二月份的天数要简单。数组和执行转换的函数如下:

static char daytab[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

int day_of_year(int year, int month, int day)
{
    int i, leap;

    leap = year%4 == 0 && year%100 != 0 || year%400 == 0;
    for (i = 0; i < month; i++)
        day += daytab[leap][i];
    return day;
}

void month_day(int year, int yearday, int *pmonth, int *pday)
{
    int i, leap;

    leap = year%4 == 0 && year%100 != 0 || year%400 == 0;
    for (i = 1; yearday > daytab[leap][i])
        yearday -= daytab[leap][i];
    *pmonth = i;
    *pday = yearday;
}

回忆一下,逻辑表达式的算术值,不是0(假)就是1(真),所以能赋给 leap,用作数组 daytab 的下标。

对 day_of_year 和 month_day 而言,数组 daytab 只能是外部的,这两个函数才能共用它。我们把它的类型定义为 char, 是为了说明,用 char 来保存非字符的小整数,是一种正当的用法。【21世纪的应用程序员应该不用这么节省内存了】

daytab 是我们处理的第一个二维数组。在 C 中,二维数组实际上是一维数组,其【高维的】每个元素是一个数组。这样下标就能写成

daytab[i][j]    /* [列][行] */

而不是

daytab[i, j]    /* 错误 */

除了这个表示法上的区别,二维数组的处理方式与其他编程语言差不多是一样的。元素是按行来存的,因此最右边的下标,或者说列,在以存储顺序访问数组元素时,变化最快。

一维数组以大括号内的一个初始化表达式列表来初始化;二维数组的每行以对应的子列表来初始化。我们让 daytab 从第 0 列开始,这样月份就自然地从 1 到 12 而不是 0 到 11。因为这里内存空间并不稀缺,这种写法比调整下标会更清晰。

如果二维数组要传递给函数,函数中的参数声明必须包含列数;行数是无关紧要的,因为依旧传递的是一个指向行的指针,而每行是一个数组。在这个特例中,该指针指向的对象是这些包含 13 个 int 的数组。因此,如果 daytab 要传递给函数 f,f 的声明会是

f(int daytab[2][13]) { ... }

或是

f(int daytab[][13]) { ... }

既然行数无关紧要,也能写成

f(int (*daytab)[13]) { ... }

说明参数是指向有 13 个整数的数组的指针。括号是必须的,因为中括号 [] 的优先级比 * 号高。如果没有括号,如下声明

int *daytab[13]

是一个数组,包含13个整数指针。更通用地说【即针对所有多维数组】,数组的第一维(下标)是随意的,其他维度必须指定。

5.12节有对复杂声明的进一步讨论。

练习5-8、dat_of_year 和 month_day 中没有错误校验。修改这个缺陷。

5.8 指针数组初始化

考虑这个问题:写个函数 month_name(n) ,返回包含第 n 个月名字的字符串指针。这是内部 static 数组的理想应用场景。month_name 包含一个私有的字符串数组,当它被调用时会返回指向正确字符串的指针。本节展示了这个包含月份名的数组是如何初始化的。

语法与之前初始化语法类似:

/* month_name:返回第n个月的名字 */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        "April", "May", "June",
        "July", "August", "September",
        "October", "November", "December"
    };
    return (n < 1 || n > 12) ? name[0] : name[n];
}

name 是一个字符串指针的数组,它的声明与前面文本行排序例子中 lineptr 的声明一样。初始化表达式是一列字符串;每个字符串都被赋给数组中对应的位置。第 i 个字符串存放在内存的某处,而指向它们的指针存在了 name[i] 中。由于数组名 name 的长度没有指定,编译器会计算初始化表达式,并填充正确的数值。

5.9 指针vs多维数组

C 初学者有时会搞不清二维数组与指针数组之间的区别,比如前一个例子中的 name。给出如下定义

int a[10][20];
int *b[10];

则 a[3][4] 和 b[3][4] 在语法上都是合法的,都是对一个 int 的引用。但 a 是一个真正的二维数组:有 200 个 int 大小的内存已经被分配了,而且使用传统的矩形下标计算公式 20*行+列 来找数组元素 a[行][列] 。然而,对 b 来说,这个定义只分配了10个指针的空间,而且没有初始化;必须显式初始化,不管是静态初始化或是通过代码来初始化。 假定 b 的每个元素的确指向了一个有20个元素的数组,则总共需要有200个 int 被分配,再加上 10 个内存单元用来放指针。指针数组的重要优势在于,数组的每行可以是不同的长度。也就是说, b 的每个元素不需要都指向有 20个元素的向量【数组】;某些可以指向有 2个元素的,或者有 50个元素的,甚至不指向任何东西【NULL】

虽然我们上面是拿整数来讨论,但目前为止最常用的指针数组是用来保存不同长度的字符串,例如函数 month_name 中保存各月份名称的 name 数组。指针数组的声明和图示如下:

char *name = {"Illegal month", "Jan", "Feb", "Mar"};

对比二维数组的声明和图

char aname[][15] =  {"Illegal month", "Jan", "Feb", "Mar"};

练习5-9、重写 day_of_year 和 month_day,但使用指针而不是索引。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1358623.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CG Magic分享3d max渲染效果图时,不可忽略的灯光技巧!

一幅效果图是否能够呈现更完美&#xff0c;不止是完美的模型基础&#xff0c;而且灯光的设置也不能忽视。 尤其&#xff0c;对于3dmax室内灯光渲染还是很重要的&#xff0c;对于新手伙伴来说&#xff0c;可能会想到的3dmax怎么打灯渲染&#xff1f; 3dmax灯光渲染设置需要注意…

CSS基础笔记-01CSS概述

文章目录 前言CSS是什么CSS的作用CSS语法添加CSS的方法 前言 CSS是什么&#xff1f;有什么作用&#xff1f;怎么编写CSS&#xff1f;怎样添加CSS&#xff1f;本文对CSS的四个方面作了学习并形成学习笔记。 CSS是什么 CSS &#xff08;Cascading Style Sheets&#xff0c;层叠…

vite环境变量的坑

最近在写项目的时候&#xff0c;遇到这么一个bug。直接看图&#xff1a; 这是我启动项目的时候vscode的提示&#xff1a; 然后默认自动打开浏览器 是不是发现bug了。你们绝对想不到这个bug是什么。我直接说吧。 这个bug来着一个环境变量&#xff0c;这个变量用来配置是否默认…

Mac 软件出现「意外退出」及「打不开」解决方法

Mac 软件出现「意外退出」及「打不开」解决方法 软件出现意外退出及软件损坏的情况&#xff0c;这是因为苹果删除了TNT的证书&#xff0c;所以大部分TNT破解的Mac软件会出现无法打开&#xff0c;提示意外退出。 终端需先安装Xcode或Apple命令行工具 如未装Xcode可以使用下列命…

SWM341系列之86盒智能开关应用

SWM341系列 86盒智能开关应用 华芯微特SWM341系列的SWM34SRET6&#xff0c;在86盒智能开关产品中的应用。 SWM34SRET6性能和UI的描述 SWM34SRET6是一款基于ARM Cortex-M33内核&#xff0c;最高主频可达150MHz时钟&#xff0c;提供内置512KB Flash&#xff0c;64KB SRAM&#…

给出一句话来描述想要的图片,就能从图库中搜出来符合要求的

介绍 地址&#xff1a;https://github.com/mazzzystar/Queryable The open-source code of Queryable, an iOS app, leverages the OpenAIs CLIP model to conduct offline searches in the Photos album. Unlike the category-based search model built into the iOS Photos…

js逆向第8例:猿人学第1题-js 混淆-源码乱码

题目1:抓取所有(5页)机票的价格,并计算所有机票价格的平均值,填入答案。 老规矩打开控制台调试,出现debugger 过掉这个很简单了,右键点击“一律不在此处暂停” 这样就可以查看具体的网络请求如下: m是加密值,熟悉的大佬能发现这串加密字符非常像md5,|后面的就是时…

linux 浅练一下哈

1.新建用户test不建家目录不允许登录&#xff0c;uid为10086_____________________ useradd -u 10086 -M -s /sbin/nologin 2.将 /opt 文件夹中所有文件的属主&#xff0c;属组改成&#xff0c;test_______________________ chown -R test.test /opt chown -R …

【基础篇】十三、强软弱虚引用、终结器引用

文章目录 0、相关&#x1f58a;1、强引用2、软引用3、弱引用4、虚引用5、终结引用 关于对象能否被回收&#xff1a; 计数器可达性分析 还可以根据引用的类型&#xff0c;不同的引用类型&#xff0c;对应对象的不同GC回收规则。 0、相关&#x1f58a; &#x1f4d5;【强软弱虚…

【HarmonyOS开发】ArkUI-X 跨平台框架(使用ArkTs开发AndroidIOS)

ArkUI-X 跨平台框架进一步将 ArkUI 开发框架扩展到了多个OS平台&#xff0c;目前支持OpenHarmony、HarmonyOS、Android、 iOS&#xff0c;后续会逐步增加更多平台支持。开发者基于一套主代码&#xff0c;就可以构建支持多平台的精美、高性能应用。 一、跨平台框架有哪些? 1、…

java发送邮件到qq邮箱

自己的授权码自己记好 引入依赖 <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version> </dependency> <dependency><groupId>javax.mail</groupId>&…

[C#]使用OpenCvSharp实现区域文字提取

【官方框架地址】 github.com/shimat/opencvsharp 【算法介绍】 采用opencv算法实现文字区域提取&#xff0c;步骤如下&#xff1a; &#xff08;1&#xff09;形态学操作 &#xff08;2&#xff09;查找轮廓 &#xff08;3&#xff09;筛选那些面积小的 &#xff08;4&#…

【AI】人类视觉感知特性与深度学习模型(1/2)

目录 一、关于人类视觉感知 1.1 视觉关注 1.自上而下&#xff08;Top-down&#xff09;的视觉关注 ​编辑 2.自下而上&#xff08;Bottom-up&#xff09;的视觉关注 3.区别和记忆点 1.2 视觉掩盖 1.常见的视觉掩盖效应 2.恰可识别失真&#xff08;Just Noticeable Dif…

缓存数据库一致性问题

为什么使用缓存&#xff1f; 业务处于起步阶段&#xff0c;流量非常小&#xff0c;那无论是读请求还是写请求&#xff0c;直接操作数据库随着业务指数级增长&#xff0c;请求量剧增&#xff0c;直接访问数据库&#xff0c;导致性能急剧下降&#xff0c;需要引入缓存提高读性能…

win环境安装yarn脚手架

win环境安装yarn脚手架 1、安装命令 npm install -g yarn 2、查看安装的版本 yarn --version 报错了&#xff01;&#xff01;&#xff01; 解决方案 搜索​​ PowerShell​​&#xff0c;右键以管理员身份运行&#xff1b; 输入&#xff1a;​​set-ExecutionPolicy Remo…

知虾shopee数据:为卖家提供了丰富的数据分析工具

使用Shopee的卖家都知道&#xff0c;这个平台为卖家提供了丰富的数据分析工具&#xff0c;帮助他们更好地理解店铺运营状况和市场趋势。这些数据分析工具不仅能够提供数据总览&#xff0c;还包括买家分析、商品排名、分类排名、销售辅导、流量分析、销售结构、行销活动、聊天响…

性能优化-OpenMP概述(一)-宏观全面理解OpenMP

本文旨在从宏观角度来介绍OpenMP的原理、编程模型、以及在各个领域的应用、使用、希望读者能够从本文整体上了解OpenMP。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础…

整除判断-判断正整数a能否被b整除,如果不能整除,输出商和余数 C语言xdoj42

问题描述 判断正整数a能否被b整除&#xff0c;如果不能整除&#xff0c;输出商和余数 输入说明 输入两个正整数a和b&#xff08;0<a, b<10000&#xff09;&#xff0c;a和b之间用空格分隔。 输出说明 如果a能被b整除&#xff0c;输出yes&#xff0c;否则在同…

山区老人爱的礼物丨守护银龄,情暖寒冬

为让山区老人们在寒冷的冬天感受到来自社会的温暖&#xff0c;新年伊始&#xff0c;北京传益千里携手志愿者再次走进酉阳土家族苗族自治县木叶乡分发新的一轮山区老人爱的礼物&#xff0c;让更多的物资走向有需要的人群。 中午阳光正好&#xff0c;志愿者们走进山林中的人家&am…

文件销毁 硬盘销毁 数据销毁 物料销毁 淼一护航数据安全最后一公里

文件销毁、硬盘销毁、数据销毁以及物料销毁&#xff0c;是现代商业和行政管理中必须面对的重要环节。随着信息化程度的加深&#xff0c;数据安全和隐私保护已经成为全社会共同关注的焦点&#xff0c;而数据销毁则是确保信息安全的重要手段。淼一护航数据安全最后一公里&#xf…