当前位置: 首页 > news >正文

邯郸住房及城乡建设部网站app关键词推广

邯郸住房及城乡建设部网站,app关键词推广,萝岗微网站建设,网站建设实训总结范文本章主要是补充 指针和数组方面的指示,把前面指针的知识补充下。参考前面的C语言基础—指针 C语言指针与数组 进阶用一级指针访问二维数组❗易错点: 不能直接指针变量数组名指向数组的指针1. 指向指针的指针2. 指向一维数组的指针 (*P)[4]—行指针二维数组名指针数组…

本章主要是补充 指针和数组方面的指示,把前面指针的知识补充下。参考前面的C语言基础—指针

C语言指针与数组 进阶

  • 用一级指针访问二维数组
    • ❗易错点: 不能直接`指针变量=数组名`
  • 指向数组的指针
    • 1. 指向指针的指针
    • 2. 指向一维数组的指针 (*P)[4]—行指针
  • 二维数组名
  • 指针数组
    • ❗易错点: 区别行指针 (*ps)[10]— *ps[10] — *(ps[10])
    • ❗❗指针数组的作用
    • 指针数组表示二维数组的举例:p[i]=a[i]
  • 动态申请和释放二维数组
    • 动态一维数组实现
    • 用指针数组实现
      • - 为什么不用定义int *a[N]?
      • 动态分配内存的过程
      • 分配内存的图示
        • 定义指针数组
        • 动态申请指针数组
  • 用指针数组处理多个字符串
    • 二维字符数组存储多个字符串
    • 使用指针数组存储多个字符串
    • 下面举几个例子
    • 字符串排序 (指针数组)
      • 方法一: 二维字符数组
      • 方法二:使用指针数组处理
      • n个字符串排序(指针数组实现)

用一级指针访问二维数组

数组其实是按行排序在内存地址中的,所以可以省略行,不能省略列。
在这里插入图片描述

具体解释见C语言数组——多维数组

利用这一特性,可以通过指针偏移遍历数组

比如假设a是一个M行N列的数组,M,N列是预定义的常量,定义如下:

int a[M][N];
int *p=&a[0][0];

下面的语句段可以求出数组a中所有元素的累加和:

sum=0;
for(i=0;i<M*N;i++,p++)
sum+=p;

也可以通过行列号做循环变量,使用双重循环来实现:

求所有上三角元素的和:

for(i=0;i<M;i++)for(j=i;j<N;j++)sum+=*(p+i*N+j); //或者sum+= *(*(p+i)+j);

❗易错点: 不能直接指针变量=数组名

  • 也就是说不能p=&a[0][0]能写成p=a

二维数组名a可以被解释为指向第一行的指针,即a和&a[0]是等价的。
但是a并不是指向二维数组中第一个元素的指针,而是指向二维数组中第一行的指针。
因此,将指针p赋值为二维数组a是不正确的,因为它们指向的内存地址不同,不能直接相互赋值。

也就是说数组名在多维数组中指的是指向第一行的指针. a+1代表的是下一行的数据


指向数组的指针

1. 指向指针的指针

类型名 **变量名

比如下面:

int i,*p=&i;
int **dp;
dp=&p;

在这里插入图片描述

dp中存储的是指针变量p的地址,我们说,dp指向指针变量p,dp是指向指针(p)的指针(变量)


2. 指向一维数组的指针 (*P)[4]—行指针

比如二维数组: int a[3][4]
定义了一个3行4列的二维数组,可以看成a[0] a[1] a[2]三个元素组层的一维数组,每个元素a[i]都是一个有4个int型元素的值,定义一个指针p,我们已经知道P+1是下一行
在这里插入图片描述

  • 如何定义这种已经知道列的二维数组的指针呢?

可以这样写: int (*p)[4];

声明了p是一个指向数组的指针,指向的是int[4]类型,

  • 如何让p指向一维数组a[0]?

可以这样写:p=&a[0];

在这里插入图片描述

 

  • (*p)[0] 即 a[0][0]的引用
  • (*p)[1] 即 a[0][1]的引用
  • 要想下一行,p+1

比如假设a是一个M行N列的数组,M,N列是预定义的常量,定义如下:

int a[M][N];
int *p=&a[0];

下面的代码可以求元素和:

sum=0;
for(i=0;i<M;i++,p++) //p++自增,将指向下一行for(j=0;j<N;j++)sum+=(*p)[j]; //p指向数组a[i],(*p)等价于a[i]

二维数组名

我们通过上面已经知道 a是指向一维数组a[0]的指针,类似这样 *(a+i)就是对a[i]的引用

我们知道数组在内存中是按竖着按行排列的

在这里插入图片描述

所以 *(a+i)+j就是 第i行a[i]再+j 取得 a[i][j]的地址

也就是说如图:
指针 a[i]+1、 *(a+i)+1指向a[i][1]; *(a[i]+1)、*( *(a+i)+1)是对a[i][1]的引用


举例: 用指针访问二维数组 求元素和

#include <stdio.h>int main() {int i,j,m,n;int sum = 0;scanf("%d%d",&m,&n);int a[m][n];printf("\n");for (int i = 0; i < m; i++) for ( j = 0; j < n; j++)scanf("%d",*(a+i)+j); //这是指针for (int i = 0; i < m; i++)for ( j = 0; j < n; j++) sum += *(*(a+i)+j);  //指针引用取值printf("三角元素的和为%d\n", sum);return 0;
}

在这里插入图片描述


指针数组

指针数组就是数组里面每个都是指针

格式:类型名* 数组名[数组长度]
数组元素是指针类型,用于存储地址

  • int a[10];
    a是一个数组,它有10个元素
    每个元素的类型都是整型

  • char *color[5];
    color是一个数组,它有5个元素
    每个元素的类型都是字符指针


❗易错点: 区别行指针 (*ps)[10]— *ps[10] — *(ps[10])

int *ps[10];
定义了含有10个元素的一维数组ps,每个元素都是int指针类型

区别于 int (*ps)[10],这个是一个指向10列的二维数组的一个指针变量.

因为[]的优先级高于*,所以int *ps[10];解释为int*(ps[10])这样


❗❗指针数组的作用

指针数组的主要作用是表示二维数组,尤其是字符串数组
用指针数组表示二维数组的好处是:
二维数组的每一行或字符串数组的每个字符串可以具有不同的长度.

在二维数组中,每一行可以具有不同的长度,但是使用传统的二维数组表示方式,每一行的长度都必须相同,这给程序的编写带来了一定的限制。而使用指针数组来表示二维数组,则可以轻松地实现每一行具有不同长度的效果。例如,可以使用指针数组来表示一个3行不等长的二维数组,代码如下:

int a1[] = {1, 2, 3};
int a2[] = {4, 5};
int a3[] = {6, 7, 8, 9};
int *p[] = {a1, a2, a3};

在上面的例子中,指针数组p中的每个元素都是一个指向int类型的指针,每个指针指向一个长度不同的int类型数组,即一个二维数组的一行。在上面的例子中,第一行有3个元素,第二行有2个元素,第三行有4个元素。

另外,在字符串数组中,每个字符串的长度也可以不同,使用指针数组来表示字符串数组可以更加灵活地处理不同长度的字符串。

因此,使用指针数组来表示二维数组或字符串数组,可以具有不同的长度,从而更加灵活地处理数据。

指针数组表示二维数组的举例:p[i]=a[i]

在表示二维数组时,指针数组可以被用来代替二维数组。二维数组是一组连续的内存空间,元素的地址是连续的。而指针数组则是一组指针,每个指针指向一个内存空间,这些内存空间不一定是连续的。因此,指针数组可以用来表示非连续的二维数组。

例如,可以使用指针数组来表示一个3行4列的二维数组,代码如下:

int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int *p[3];
for (int i = 0; i < 3; i++) {p[i] = a[i];
}

在上面的例子中,指针数组p中的每个元素都是一个指向int类型的指针,每个指针指向一个长度为4的int类型数组,即一个二维数组的一行,比如p[0]指向a[0]第一行的

在循环中,通过将指针数组p中的每个元素指向二维数组a的每一行,就可以使用指针数组p来表示整个二维数组。

使用指针数组表示二维数组的好处是,可以更加灵活地对数组进行操作。例如,可以通过修改指针数组中的元素来改变二维数组的大小和形状,而不需要创建一个新的二维数组。同时,指针数组的内存使用也更加灵活,可以根据需要动态分配内存。


动态申请和释放二维数组

输入整数n和n,然后输入m行n列的矩阵。然后输出矩阵。要求动态申请和释放二维数组

  • 方法1:用动态一维数组的方法存储二维数组
  • 方法2:用指针数组实现

动态一维数组实现

也就是申请的内存块是一维数组那样的,然后一个一个装进去。
在这里插入图片描述
代码如下:

#include <stdio.h>
#include <stdlib.h>int main() {int n, m,i,j;scanf("%d %d", &n, &m);// 动态申请一维数组 m*n个内存块int *p = (int *) malloc(n * m * sizeof(int));for (i = 0; i < m; i++){ for (j = 0; j < n; j++)scanf("%d",p+i*n+j);//scanf("%d",&p[i*n+j]);}for (i = 0; i < m; i++){       for (j = 0; j < n; j++)printf("%d ",p[i*n+j]);//指针也可以作为数组名printf("\n");
}return 0;
}

在这里插入图片描述


用指针数组实现

(1) 声明一个一维指针数组,存放每行的首地址

int **a; //指向指针数组的首地址
a=(int **)malloc(m*sizeof(int*));

(2) 用malloc为每一行元素申请空间

for(i=0;i<m;i++)
a[i]=(int*)malloc(n*sizeof(int));

(3) 读入m*n个元素
(4) 输出矩阵
(5) 释放每一个行指针所指空间

for(i=0;i<m;i++)
free(a[i]);

代码如下:

#include <stdio.h>
#include <stdlib.h>
#define N 100int main() {int n, m,i,j;// 读入矩阵的行列数printf("请输入矩阵的行数和列数:\n");scanf("%d %d", &m, &n);// 动态分配指针数组,存放每行的首地址int **a=(int **)malloc(m * sizeof(int *)); //申请存储m个指针的内存块// 动态分配每一行的空间for (i = 0; i < m; i++) {a[i] = (int *)malloc(n * sizeof(int));}// 读入矩阵元素printf("请输入矩阵的元素:\n");for (i = 0; i < m; i++) {for (j = 0; j < n; j++) {scanf("%d", &a[i][j]);}}// 输出矩阵printf("您输入的矩阵为:\n");for (i = 0; i < m; i++) {for (j = 0; j < n; j++) {printf("%d ", a[i][j]);}printf("\n");}// 释放每一行的空间for(i=0;i<m;i++)free(a[i]);return 0;
}

在这里插入图片描述


下面解释下?

- 为什么不用定义int *a[N]?

实际上,定义 int *a[N] 可以用来定义一个指针数组,每个指针指向一个整型数组。在这个例子中,指针数组的长度为 N,但是在动态分配内存时使用的是一个 m 倍的空间,这可能会导致内存溢出。因此,指针数组的定义在这里并不适用。相反,需要使用一个指向指针的指针 int **a 来动态分配内存。

动态分配内存的过程

首先,通过调用 malloc() 函数来为存储指针的内存块分配空间。为了能够存储 m 个指针,需要分配 m * sizeof(int *) 字节的内存。然后,通过循环分配每一行的内存空间。每一行需要分配n * sizeof(int)字节的内存。

总结一下,a[i] 可以直接使用是因为它在数组 a 中被定义为指向整型数组的指针。在动态分配内存时,首先需要为存储指针的内存块分配空间,然后循环为每一行分配内存。

也就是系统自动分配了指针数组,因为通过分配m * sizeof(int *) 字节的内存相当于知道 a[i]的地址,然后再通过n * sizeof(int)分配每一行的列的内容的内存。


分配内存的图示

定义指针数组

在这里插入图片描述

动态申请指针数组

在这里插入图片描述

在这里插入图片描述


用指针数组处理多个字符串

二维字符数组存储多个字符串

char ccolor[][7]={"red","blue","yellow","green","purple"};

一个字符占一位,列数取决于最长的字符串

在这里插入图片描述

使用指针数组存储多个字符串

char *pcolor[]={"red","blue","yellow","green","purple"};

这时候指针数组里面每个指针指向字符串首地址

在这里插入图片描述
优点是更节省内存空间


下面举几个例子

字符串排序 (指针数组)

{“red”,“blue”,“yellow”,“green”,“purple”}; 请排序后输出

方法一: 二维字符数组

#include <stdio.h> 
#include <string.h>int main(void) 
{ char colors[][7] = {"red", "blue", "yellow", "green", "purple"}; int num_colors = sizeof(colors) / sizeof(colors[0]); //行// Sort the colors
for (int i = 0; i < num_colors - 1; i++) {for (int j = i + 1; j < num_colors; j++) {if (strcmp(colors[i], colors[j]) > 0) {char temp[7];strcpy(temp, colors[i]);strcpy(colors[i], colors[j]);strcpy(colors[j], temp);}}
}// Print the sorted colors
for (int i = 0; i < num_colors; i++) {printf("%s\n", colors[i]);
}return 0;
}

在这里插入图片描述


方法二:使用指针数组处理

本质是改变指针数组中每个指针的地址,改变指向方向

在这里插入图片描述

#include <stdio.h>
#include <string.h>int main(void) { char *colors[] = {"red", "blue", "yellow", "green", "purple"}; int num_colors = sizeof(colors) / sizeof(colors[0]);// Sort the colors
for (int i = 0; i < num_colors - 1; i++) {for (int j = i + 1; j < num_colors; j++) {if (strcmp(colors[i], colors[j]) > 0) {char *temp;temp = colors[i];colors[i] = colors[j];colors[j] = temp;}}
}// Print the sorted colors
for (int i = 0; i < num_colors; i++) {printf("%s\n", colors[i]);
}return 0;
}

在这里插入图片描述


n个字符串排序(指针数组实现)

输入n和n个字符串(每个字符串不超过80个字符)请排序后输出,要求使用指针数组(而不是二维字符数组)处理

可以使用指针数组和动态内存分配来实现,具体思路如下:

  1. 首先读入字符串的个数 n;
  2. 使用 malloc 函数动态分配一个指针数组 strArr,大小为 n;
  3. 然后使用 fgets 函数逐个读入字符串,将每个字符串的地址存储到指针数组中;
  4. 对指针数组中的字符串进行排序,可以使用 qsort 函数;
  5. 最后遍历指针数组,按照顺序输出每个字符串。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_LENGTH 80int cmp(const void *a, const void *b) {return strcmp(*(char **)a, *(char **)b);
}int main() {int n;printf("请输入字符串的个数:");scanf("%d", &n);// 动态分配指针数组char **strArr = (char **)malloc(n * sizeof(char *));if (strArr == NULL) {printf("动态分配内存失败!\n");exit(1);}// 逐个读入字符串for (int i = 0; i < n; i++) {strArr[i] = (char *)malloc((MAX_LENGTH + 1) * sizeof(char));if (strArr[i] == NULL) {printf("动态分配内存失败!\n");exit(1);}printf("请输入第%d个字符串:", i + 1);getchar();  // 去掉回车fgets(strArr[i], MAX_LENGTH + 1, stdin);// 如果字符串最后一个字符是 '\n',将其替换为 '\0'int len = strlen(strArr[i]);if (strArr[i][len - 1] == '\n') {strArr[i][len - 1] = '\0';}}// 排序指针数组qsort(strArr, n, sizeof(char *), cmp);// 输出排序后的字符串for (int i = 0; i < n; i++) { printf("%s\n", strArr[i]); }// 释放动态分配的内存
for (int i = 0; i < n; i++) {free(strArr[i]);
}
free(strArr);return 0;
}

在这里插入图片描述


解释下:

cmp 函数是一个用于比较两个字符串指针的函数,它的作用是在使用 qsort 函数对指针数组进行排序时,指定排序的规则。

qsort 函数的原型为:

void qsort(void *base, size_t nmemb, size_t size, int (*compar)
(const void *, const void *));

其中,compar 参数是一个指向比较函数的指针, 它接受两个指针参数,分别指向数组中需要比较的两个元素。比较函数应该返回一个整数值,表示两个元素的大小关系

 

在本例中,cmp 函数的作用是比较两个字符串指针所指向的字符串,返回它们的大小关系。具体地,cmp 函数的参数类型为 const void *,也就是指向任意类型的指针。我们需要将它们转换为指向 char * 类型的指针,然后再进行字符串比较。

为了实现这个目的,我们首先将 a 和 b 转换为指向 char ** 类型的指针。然后使用 * 运算符来取出指针所指向的字符串,再使用 strcmp 函数进行比较。

因此,cmp 函数的实现如下:

int cmp(const void *a, const void *b) {return strcmp(*(char **)a, *(char **)b);
}

这样,在调用 qsort 函数时,我们可以将 cmp 函数的地址作为参数传递,qsort 函数会根据 cmp 函数的返回值来排序指针数组中的元素。


http://www.qdjiajiao.com/news/11374.html

相关文章:

  • 有没有可以在网站上做试卷的网站优化外包多少钱
  • 网站建设推广浩森宇特一键免费生成网页的网站
  • 珠宝出售网站模板100个经典创意营销方案
  • 长兴网站建设2022年热点营销案例
  • 外贸网站搭建服务商快速建网站
  • 赣州网站建设机构seo内部优化具体做什么
  • 网站服务器计算机安全的措施哈尔滨seo关键词优化
  • 被派出所找到老家说我做非法网站推广怎么做
  • 西安百通网站建设公司网站首页不收录
  • 泾川网站城镇建设规化图seo优化咨询
  • 网页设计个人网站怎么做深圳网站营销seo电话
  • 做加盟代理的网站域名搜索引擎
  • 学编程去哪里学比较好鞍山seo公司
  • 最近香港疫情最新消息seo学习网站
  • 网站定制服务怎么样广州:推动优化防控措施落地
  • 网站开发中定义路由的作用广告优化师工作内容
  • 甘肃做网站价格软文营销怎么做
  • 市中移动网站建设佛山seo整站优化
  • wordpress数据库删不掉武汉抖音seo搜索
  • 广州设计网站培训学校我想在百度发布信息
  • 网站开发需要逻辑吗打开网址跳转到国外网站
  • 城阳做网站的公司站内优化
  • 永久建站平台佛山seo技术
  • 小型企业管理系统软件南京百度推广优化
  • 建设网站的工具是什么seo运营学校
  • 做门户网站需要学什么软件什么是软文营销
  • 苹果网站设计风格简述绍兴百度推广优化排名
  • 鄂州建设工程造价信息管理网站友情链接检查工具
  • 做网站的软件著作权今日头条新闻
  • 睿艺美开封做网站seo定义