《C语言程序设计 第4版》笔记和代码 第十一章 指针和数组

第十一章 指针和数组

11.1 指针和一维数组间的关系

1 由于数组名代表数组元素的连续存储空间的首地址,因此,数组元素既可以用下标法也可以用指针来引用。

例11.1见文末

2 p+1p++在本质上是两个不同的操作,前者不改变当前指针的指向(因为没有进行赋值操作),而后者相当于执行p=p+sizeof(p的基类型),因此改变了p指针的指向,指向下一个元素。

3 p++不是将指针变量加1字节,而是加上1*sizeof(基类型)个字节。

4 输入p和a都是表示首地址,但是数组名a是一个指针常量不可以进行增1或减1操作,而指针p是一个指针变量可以这种操作。

5 用一维数组作函数形参与指针变量作函数形参在本质上都是一样的,因此在被调函数中既能以下标形式也能以指针形式访问元素。

例11.2见文末

11.2 指针和二维数组间的关系

1 如数组:int a[M][N] 可在逻辑上看成一个M行N列的存储空间。

2 可将二维数组看成由多个元素组成的一维数组,因此可以通过行地址列地址定位到每个具体的元素。

3 类似于行地址和列地址,可以用行指针列指针来定位具体元素。

例11.3见文末

11.3 指针数组及其应用

1 指针数组是值由若干个基类型相同的指针组成的数组。定义形式为:

类型关键字 *指针数组名[数量];

2 指针数组可以用存储多个字符串

例11.4见文末

3 指针数组的元素是一个指针,因此与指针变量一样,在使用指针数组前必须对数组元素进行初始化

4 指针数组可用于表示命令行参数

例11.5见文末

11.4 动态数组

1 一个编译后的C程序会获得4块在逻辑上不相同并且用于不同目的的内存储区。

2 从低端起,第一块内存为只读存储区,用于存放程序的机器代码和字符串字面量等只读数据。

3 第一块内存相邻的一块是静态存储区,用于存放程序中的全局变量和静态变量等。

4 其他两块内存分别称为,属于动态存储区

5 用于保存函数调用时的返回地址、函数的形参、局部变量及CPU的当前状态等程序的运行信息;是一个自由存储区,程序可以用C的动态分配函数来使用堆。

6 变量的内存分配可以通过:(1)从静态存储区分配;(2)在上分配;(3)在上分配。

7 指针的另外一个作用是通过与动态内存分配函数联用,使动态数组成为可能。

8 动态内存分配是指程序运行时为变量分配内存的一种方法,在上实现。需要添加头文件<stdlib.h>

9 函数malloc()用于分配若干字节的内存空间,返回一个指向该内存首地址的指针。如果系统不能提供足够的内存单元,函数则会返回一个空指针NULL。

10 malloc()函数的使用举例:

pi=(int *)malloc(sizeof(int));

表明向系统申请一个大小为4字节的内存,并且pi为int型指针。

11 函数calloc()可用于给若干同一类型的数据项分配连续的存储空间并赋值为0,因此calloc()比malloc()更安全。

12 函数free()的功能是释放向系统动态申请的由指针p指向的存储空间。该函数的形参只能是由malloc()或calloc()申请内存时返回的地址。

13 函数realloc()用于改变原来分配的存储空间的大小。

例11.6见文末

14 永远不要忘记用free()释放不再使用的动态申请的内存。

例11.7见文末

代码

11.1a

演示数组元素的引用方法,下标法

//例11.1a 演示数组元素的引用方法,下标法
#include<stdio.h>
int main(void)
{int a[5],i;printf("Input five numbers:");for(i=0;i<5;i++){scanf("%d",&a[i]);}for(i=0;i<5;i++){printf("%4d",a[i]);//通过数组下标,一个个将元素打印出来 }printf("\n");return 0;}

11.1b

演示数组元素的引用方法,解引用 

//例11.1b 演示数组元素的引用方法,解引用 
#include<stdio.h>
int main(void)
{int a[5],i;printf("Input five numbers:");for(i=0;i<5;i++){scanf("%d",a+i);//a+i等价于&a[i] }for(i=0;i<5;i++){printf("%4d",*(a+i));//等价于a[i] }printf("\n");//这种方法是效率最高的 return 0;} 

 11.1c

演示数组元素的引用方法,用移动指针变量p的方法 

//例11.1c 演示数组元素的引用方法,用移动指针变量p的方法 
#include<stdio.h>
int main(void)
{int a[5],*p;printf("Input five numbers:");for(p=a;p<a+5;p++){scanf("%d",p);//指针法输入 }for(p=a;p<a+5;p++){printf("%4d",*p);//指针法输出 }printf("\n");return 0;} 

11.1d

演示数组元素的引用方法,用移动指针结合下标的方法 

//例11.1d 演示数组元素的引用方法,用移动指针结合下标的方法 
#include<stdio.h>
int main(void)
{int a[5],*p=NULL,i;//需要初始化指针 printf("Input five numbers:");p=a;//等价于p=&a[0]; for(i=0;i<5;i++){scanf("%d",&p[i]);//指针法输入 }for(i=0;i<5;i++){printf("%4d",p[i]);//指针法输出 }printf("\n");return 0;
}

11.2主函数a

主函数a 演示数组和指针变量作为函数参数,实现与例11.1相同的功能

//例11.2 主函数a 演示数组和指针变量作为函数参数,实现与例11.1相同的功能
#include<stdio.h>
int main(void)
{int a[5];printf("Input five numbers:");InputArray(a,5);//数组名作函数参数 OutputArray(a,5);return 0;
}  

11.2 主函数b

主函数b(实际意义不大) 演示数组和指针变量作为函数参数,实现与例11.1相同的功能

//例11.2 主函数b(实际意义不大) 演示数组和指针变量作为函数参数,实现与例11.1相同的功能
#include<stdio.h>
int main(void)
{int a[5];int *p=a; printf("Input five numbers:");InputArray(p,5);//指针作函数参数 OutputArray(p,5);return 0;
}

11.2 几类被调函数

//被调函数实现方法一:形参和访问都用数组
void InputArray(int a[],int n);
void OutputArray(int a[],int n);
void InputArray(int a[],int n)//数组作形参 
{int i;for(i=0;i<n;i++){scanf("%d",&a[i]);//下标法访问 } 
} 
void OutputArray(int a[],int n)
{int i;for(i=0;i<n;i++){printf("%4d",a[i]);//下标法访问 }printf("\n");
}
//被调函数实现方法二:形参和访问都用指针 
void InputArray(int *pa,int n);
void OutputArray(int *pa,int n);
void InputArray(int *pa,int n)//指针作形参 
{int i;for(i=0;i<n;i++,pa++)//这里指针也需移动 {scanf("%d",pa);//指针访问 } 
} 
void OutputArray(int *pa,int n)
{int i;for(i=0;i<n;i++,pa++){printf("%4d",*pa);//下标法访问 }printf("\n");
}
//被调函数实现方法三:形参为数组类型,访问用指针法 
void InputArray(int a[],int n);
void OutputArray(int a[],int n);
void InputArray(int a[],int n)//指针作形参 
{int i;for(i=0;i<n;i++){scanf("%d",a+i);//指针访问 } 
} 
void OutputArray(int a[],int n)
{int i;for(i=0;i<n;i++){printf("%4d",*(a+i);//指针访问 }printf("\n");
}
//被调函数实现方法四:形参用指针变量,访问都用数组方式 
void InputArray(int *pa,int n);
void OutputArray(int *pa,int n);
void InputArray(int *pa,int n)//指针作形参 
{int i;for(i=0;i<n;i++){scanf("%d",&pa[i]);//数组方式访问 } 
} 
void OutputArray(int *pa,int n)
{int i;for(i=0;i<n;i++){printf("%4d",pa[i]);//数组方式访问 }printf("\n");
}

11.3a

编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。方法一

//例11.3a 编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。方法一 
#include<stdio.h>
#define N 4
void InputArray(int p[][N],int m,int n);
void OutputArray(int p[][N],int m,int n);
int main (void)
{int a[3][4];printf("Input 3*4 numbers:\n");InputArray(a,3,4);//向函数传递的是第0行地址OutputArray(a,3,4);return 0; }
void InputArray(int p[][N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){scanf("%d",&p[i][j]);//使用两层循环就可以完成二维数组的输入 }}
}
void OutputArray(int p[][N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){printf("%4d",p[i][j]);//使用两层循环同样可以实现二维数组的打印 }printf("\n");//在每一个内层循环结束后添加换行符,相当于实现二维数组的逻辑换行 }
}

11.3b

 编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。方法二 

//例11.3b 编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。方法二 
#include<stdio.h>
#define N 4
void InputArray(int (*p)[N],int m,int n);//不要忘记(*p) 
void OutputArray(int (*p)[N],int m,int n);
int main (void)
{int a[3][4];printf("Input 3*4 numbers:\n");InputArray(a,3,4);//向函数传递的是第0行地址OutputArray(a,3,4);return 0; }
void InputArray(int (*p)[N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){scanf("%d",*(p+i)+j);//相当于先按行移动,再找到对应的列 }}
}
void OutputArray(int (*p)[N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){printf("%4d",*(*(p+i)+j));//对*(p+i)+j的解引用 }printf("\n");//在每一个内层循环结束后添加换行符,相当于实现二维数组的逻辑换行 }
}

11.3c

编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。方法三 

//例11.3c 编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。方法三 
#include<stdio.h>
#define N 4
void InputArray(int *p,int m,int n);//不要忘记(*p) 
void OutputArray(int *p,int m,int n);
int main (void)
{int a[3][4];printf("Input 3*4 numbers:\n");InputArray(*a,3,4);//注意a前面的*,这个时候先函数传递的就是0行0列的地址,不同于前面传递0行地址 OutputArray(*a,3,4);return 0; }
void InputArray(int *p,int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){scanf("%d",&p[i*n+j]);//相当于先定位到具体的下标 }}
}
void OutputArray(int *p,int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){printf("%4d",p[n*i+j]);//同样先定位到具体的下标 }printf("\n");//在每一个内层循环结束后添加换行符,相当于实现二维数组的逻辑换行 }
}

11.4

使用指针数组来重新编写例10.4

//例11.4 使用指针数组来重新编写例10.4
#include<stdio.h>
#include<string.h>
#define MAX_LEN 10//字符串的最大长度
#define N 150   //最大参赛国
void SortString(char *ptr[],int n);
int main(void)
{int i,n;char name[N][MAX_LEN];//使用字符型的二维数组char *pStr[N];printf("How many countries?");scanf("%d",&n);getchar();//读走缓冲区的回车符printf("Input their name:\n");for(i=0;i<n;i++){pStr[i]=name[i];//让pStr指向name的第i行gets(pStr[i]);//输入第i个字符串到pStr指向的内容 } SortString(pStr,n);//这时候排序的就是pStr printf("Sorted results:\n");for(i=0;i<n;i++){puts(pStr[i]);//输出排序后字符 }return 0;} 
void SortString(char *ptr[],int n)
{//指针数组作函数参数,来用交换法实现字符串的排序int i,j;char *temp=NULL;//因为交换的是字符串的地址值,所以temp需要为指针变量 for(i=0;i<n-1;i++){for(j=i+1;j<n;j++){if(strcmp(ptr[j],ptr[i])<0)//用strcmp()函数实现字符串的比较功能{temp=ptr[i];//这里就使用赋值运算符即可ptr[i]=ptr[j];ptr[j]=temp; } }} 
} 

11.5

演示命令行的参数与函数main()各形参之间的关系。

//例11.5 演示命令行的参数与函数main()各形参之间的关系。
#include<stdio.h>
int main(int argc,char *argv)//带参数的main()函数定义,argc和argv是惯例 
{int i;printf("The number of command line arguments is:%d\n",argc);printf("The program name is:%s\n",argv[0]);if(argc>1){printf("The other arguments are following:\n");for(i=1;i<argc;i++){printf("%s\n",argv[i]);}}return 0;} 

11.6

编程输入某班学生的某门课成绩,计算并输出其平均分。学生人数由键盘输入。

//例11.6 编程输入某班学生的某门课成绩,计算并输出其平均分。学生人数由键盘输入。
#include<stdio.h>
#include<stdlib.h>
void InputArray(int *p,int n);
double Average(int *p,int n);
int main(void)
{int *p=NULL,n;double aver;printf("How many students?");scanf("%d",&n);p=(int *)malloc(n*sizeof(int));//有多少学生就对应开辟多少空间if(p==NULL)//防止出现分配不成功的情况 {printf("No enough memory!\n");//提醒用户空间分配失败exit(1);//结束程序 } printf("Input %d score:",n);InputArray(p,n);//输入学生成绩aver=Average(p,n);//计算平均分printf("aver=%.1f\n",aver);free(p);//千万不要忘记释放空间 return 0;}
void InputArray(int *p,int n)
{int i;for(i=0;i<n;i++){scanf("%d",&p[i]);}}
double Average(int *p,int n){int i,sum=0;for(i=0;i<n;i++){sum+=p[i];}return (double)sum/n;//注意强制转换 } 

11.7

编程输入m个班学生(每班n个学生)的某门课成绩,计算并输出平均分。班级数和每班学生数由键盘输入。

//例11.7 编程输入m个班学生(每班n个学生)的某门课成绩,计算并输出平均分。班级数和每班学生数由键盘输入。 
#include<stdio.h>
#include<stdlib.h>
void InputArray(int *p,int m,int n);
double Average(int *p,int m,int n);
int main(void)
{int *p=NULL,m,n;double aver;printf("How many classes?");scanf("%d",&m);printf("How many stuents in a class?");scanf("%d",&n);p=(int *)calloc(m*n,sizeof(int));//申请内存 if(p==NULL)//防止出现分配不成功的情况 {printf("No enough memory!\n");//提醒用户空间分配失败exit(1);//结束程序 } printf("Input %d score:",n);InputArray(p,m,n);//输入学生成绩aver=Average(p,m,n);//计算平均分printf("aver=%.1f\n",aver);free(p);//千万不要忘记释放空间 return 0;}
void InputArray(int *p,int m,int n)
{int i,j;for(i=0;i<m;i++){printf("Please enter scores of class %d:\n",i+1);for(j=0;j<n;j++){scanf("%d",&p[n*i+j]);}}}
double Average(int *p,int m,int n){int i,j,sum=0;for(i=0;i<m;i++){for(j=0;j<n;j++){sum=sum+p[n*i+j];}}return (double)sum/n;//注意强制转换 }

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

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

相关文章

无人机之遥控器保养

一、使用存放 1、避免让遥控器受到强烈的震动或从高处跌落&#xff0c;以免影响内部结构的精度&#xff1b; 2、遥控器在使用完后&#xff0c;需要将天线收拢&#xff0c;避免折断&#xff0c;养成定期检查天线的习惯&#xff1b; 3、定期检查遥控器按键有无裂纹、畸变、松旷…

ISO/OIS的七层模型②

OSI模型是一个分层的模型&#xff0c;每一个部分称为一层&#xff0c;每一层扮演固定的角色&#xff0c;互不干扰。OSI有7层&#xff0c;从上到下分别是&#xff1a; 一&#xff0c;每层功能 7.应用层&#xff08;Application layer &#xff09;&#xff1a;应用层功能&#x…

如何从gitlab删除仓库

嗨&#xff0c;我是兰若姐姐。今天发现gitlab上有些仓库的代码没有用&#xff0c;是个多余的仓库&#xff0c;想要删掉&#xff0c;经过一番操作之后&#xff0c;成功的删除了&#xff0c;git上没有 多余的仓库&#xff0c;看着干净舒服很多&#xff0c;现在把删除的过程分享出…

基于ssm的图书管理系统的设计与实现

摘 要 在当今信息技术日新月异的时代背景下&#xff0c;图书管理领域正经历着深刻的变革&#xff0c;传统的管理模式已难以适应现代社会的快节奏和高要求&#xff0c;逐渐向数字化、智能化的方向演进。本论文聚焦于这一转变趋势&#xff0c;致力于设计并成功实现一个基于 SSM&…

U-net和U²-Net网络详解

目录 U-Net: Convolutional Networks for Biomedical Image Segmentation摘要U-net网络结构pixel-wise loss weight U-Net: Going Deeper with Nested U-Structure for Salient Object Detection摘要网络结构详解整体结构RSU-n结构RSU-4F结构saliency map fusion module -- 显著…

JavaFx+MySql学生管理系统

前言: 上个月学习了javafx和mysql数据库,于是写了一个学生管理系统,因为上个月在复习并且有一些事情,比较忙,所以没有更新博客了,这个项目页面虽然看着有点简陋了,但是大致内容还是比较简单的,于是现在跟大家分享一下我的学生管理系统,希望对这方面有兴趣的同学提供一些帮助 &a…

Vue 3 中创建一个动态的组件实例

本文将介绍如何在 Vue 3 中实现一个动态 Toast 组件实例。我们将创建一个简单的 Toast 组件&#xff0c;并使用一个动态创建实例的脚本来显示 Toast 消息。在 Vue 3 中创建动态组件实例有许多好处&#xff0c;这些好处主要体现在灵活性、性能、可维护性和用户体验等方面。 创建…

【JavaScript 算法】快速排序:高效的排序算法

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现三、应用场景四、优化与扩展五、总结 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;通过分治法将数组分为较小的子数组&#xff0c;递归地排序子数组。快速排序通常…

分享一个 .NET 通过监听器拦截 EF 消息写日志的详细例子

前言 EF 开发效率确实很高也很便捷&#xff0c;但当它发生错误时&#xff0c;也挺让人头疼的&#xff0c;为什么&#xff1f;因为 EF 就像是一个黑盒子&#xff0c;一切全被封装起来&#xff0c;出错的时候很难定位原因&#xff0c;如果能够知道并打印 EF 生成的 SQL 语句&…

记录些Redis题集(1)

为什么Redis要有淘汰机制&#xff1f; 淘汰机制的存在是必要的&#xff0c;因为Redis是一种基于内存的数据库&#xff0c;所有数据都存储在内存中。然而&#xff0c;内存资源是有限的。在Redis的配置文件redis.conf中&#xff0c;有一个关键的配置项&#xff1a; # maxmemory…

Go语言入门之Map详解

Go语言入门之Map详解 1.基础定义 map是一个无序的&#xff0c;k-v键值对格式的集合 &#xff08;1&#xff09;特点 类型特点&#xff1a;map为引用类型&#xff0c;所以在函数中更新value值会永久改变顺序特点&#xff1a;map的遍历是无序的&#xff0c;因为底层是哈希表&am…

零基础学python(二)

1. 字典 字典的创建 最常见的创建方式&#xff1a; d {"k1": "v1", "k2": "v2"} 再向字典中添加一对键值&#xff1a; d["k3"] "v3" 字典还可以用dict()创建&#xff0c;这种方式中&#xff0c;键是不加引…

【Unity2D 2022:UI】制作主菜单

一、创建主菜单游戏场景 1. 在Scenes文件夹中新建一个游戏场景Main Menu 2. 为场景添加背景 &#xff08;1&#xff09;创建画布Canvas &#xff08;2&#xff09;在Canvas中创建新的空游戏物体Main Menu &#xff08;3&#xff09;在Main Menu中新建一个图像游戏物体Backgrou…

无人机之机身保养

一、外观检查 1、检查机器表面整洁无划痕、无针孔凹陷擦伤、畸变等损坏情况&#xff1b; 2、晃动机身&#xff0c;仔细听机身内部有无松动零件或者螺丝在机身内部。 二、桨叶检查 1、有无裂痕、磨损、变形等缺陷&#xff0c;如有明显缺陷建议更换&#xff1b; 2、卡扣、紧…

Animate软件基础:图层的基本用法

图层作为Animate软件中比较重要的功能&#xff0c;需要对其使用方法和作用理解充分&#xff0c;并熟练操作才可以更好的用来制作内容。 图层相关的功能和用法如下&#xff1a; 图层可以帮助在文档中组织插图。 可以在一个图层上绘制和编辑对象&#xff0c;而不会影响其他图层…

排座椅【详细代码题解】

[NOIP2008 普及组] 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳&#xff0c;这是令小学班主任十分头疼的一件事情。不过&#xff0c;班主任小雪发现了一些有趣的现象&#xff0c;当同学们的座次确定下来之后&#xff0c;只有有限的 D D D 对同学上课时…

USB转RS485+RS232+TTL串口电路

USB转RS485RS232TTL电路 USB转RS485RS232TTL电路如下图所示&#xff0c;可实现USB转RS485RS232TTL串口&#xff0c;一个电路模块即可实现电路调试过程中用到常用接口。 电路模块上留有2.54MM单排针接口和接线端子两种接线方式&#xff0c;可接线和跳线。电路模块同时有5V和3.3V…

开源浏览器引擎对比与适用场景:WebKit、Chrome、Gecko

WebKit与Chrome的Blink引擎对比 起源与关系&#xff1a; WebKit最初由苹果公司开发&#xff0c;用于Safari浏览器。后来&#xff0c;WebKit逐渐成为一个独立的开源项目&#xff0c;被多个浏览器厂商采用。Blink是Google基于WebKit项目分支出来的一个浏览器引擎&#xff0c;用于…

文献翻译与阅读《Integration Approaches for Heterogeneous Big Data: A Survey》

CYBERNETICS AND INFORMATION TECHNOLOGIES’24 论文原文下载地址&#xff1a;原文下载 目录 1 引言 2 大数据概述 3 大数据的异构性 4 讨论整合方法 4.1 大数据仓库&#xff08;BDW&#xff09; 4.2 大数据联盟&#xff08;BDF&#xff09; 5 DW 和 DF 方法的比较、分…

C++入门基础题:数组元素逆序(C++版互换方式)

1.题目&#xff1a; 数组元素逆置案例描述: 请声明一个5个元素的数组&#xff0c;并且将元素逆置. (如原数组元素为:1,3,2,5,4;逆置后输出结果为:4,5,2,3,1) 2.图解思路&#xff1a; 3.代码演示&#xff1a; #include<iostream>using namespace std;int main(){int a…