王老师 指针 第二讲

指针详解

(7)二级指针

指向一级指针的指针.

类似的,可有更高级的指针.

(8)指向数组的指针

声明语法: 类型名 (*变量名)[表达式1]...[表达式n];

(9)指向函数的指针

声明语法: 值类型 (*指针名)(形参表);

运算与用途:

1.赋值

2.调用语法 (*函数指针)(实参表);

3.可作函数参数

4.可作函数值

5.可作数组元素

(10)复合说明项

在c语言中,处理声明语句时,遇到[]处理成数组;遇到*处理成指针;遇到()处理成函数;
但是,
1.不能有元素为函数的数组,但是可以有元素为函数指针的数组;
2.不能有函数值是函数的函数,但是函数值可以是指向函数的指针;
3.不能有函数值是数组的函数,但是函数值可以是指向数组的指针.

示例程序如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void show(int array[]);
void swap_1(int **a, int **b);
void swap_2(int **a, int **b);

double g(double a, double b, double (*fp)(double));

//注意,c语言中的抽象说明符 ??
double g(double, double, double (*)(double));

double y(double x);

//自己实现scanf
void scanf_m(char *c, void *p);

void main()
{
 int i;
 
 /*
 * 二级指针
 */
 int array[10], *p[10];
 int **q;
 
 for(i = 0; i < 10; i++)
  p[i] = &array[i];
 
 //为q赋初值
 q = p;
 
 //下面的语句只能给array[0]赋值
 for(i = 0; i < 10; i++)
  **q = i;
 
 //应改为
 for(i = 0; i < 10; i++)
 {
  **q = i;
  q++;  
 }
 
 //下面的程序会出错
 /*
 for(i = 0; i < 10; i++)
 {
 *q = ++ *q; 
 printf("%d ", **q);
 }*/
 
 //show(array);
 
 //使用二级指针,交换两个指针的指向
 int u = 1, v = 2, *pointer = &u, *qointer = &v;
 
 swap_1(&pointer, &qointer);
 //printf("%d, %d/n", u, v);
 //printf("%d, %d", *pointer, *qointer);
 
 //swap_2(&pointer, &qointer);
 //printf("%d, %d/n", u, v);
 //printf("%d, %d", *pointer, *qointer);
 
 /*
 * 指向数组的指针:一个指针,所指对象是数组,例如:
 */
 int (*pa)[10], a[5][10];
 pa = a;
 printf("pa = %d/n", pa);
 
 //pa + 1跨过了40个字节
 printf("pa + 1 = %d/n", pa + 1);
 
 int (*qb)[5][10], b[1][5][10];
 qb = b;
 
 /*
 * 在c语言中, 不论p是什么样的指针, p[i] = *(p + i)总成立.
 */
 for(i = 0; i < 5; i++){
  for(int j = 0; j < 10; j ++){
   a[i][j] = i;
  }
 }
 int (*pb)[10] = pa + 5;
 //打印数组元素
 for(; pa < pb; pa++)
 {
  printf("%d ", **pa);
  printf("%d ", *(*pa + 9));
 }
 printf("/n");
 
 /*
 * 指向函数的指针:一个指针,值为函数入口地址
 */
 printf("%f/n", g(0, 10, y));
 printf("%f/n", g(0, 3.1415926, sin));
 
 /*
 * 复合说明项
 */
 
 //例1.windows消息映射,使用了元素为函数指针的数组,而不是一个大的switch语句.
 //例2.返回值是指向一个函数的指针,用的不多.
 //例3.返回值是指向数组的指针
 
 //指针的强制类型转换
 int intTemp = 0;
 double flTemp = 0;
 char chTemp[100];
 char ch = 'd';
 scanf_m(&ch, &intTemp);
 ch = 'f';
 scanf_m(&ch, &flTemp);
 ch = 's';
 scanf_m(&ch, chTemp);
 printf("%d, %f, %s/n", intTemp, flTemp, chTemp);
}

/*
* 输出数组
*/
void show(int array[])
{
 int i = 0;
 for(i = 0; i < 10; i++)
 {
  printf("%d ", array[i]);
 }
}

/*
* 下面的2个程序交换两个指针指向的内容
*/
void swap_1(int **a, int **b)
{
 int *x = NULL;
 x = *a;
 *a = *b;
 *b = x;
}

void swap_2(int **a, int **b)
{
 int **x = NULL;
 //下面的程序会报错,x的值不定,说不定指到哪.
 *x = *a;
 *a = *b;
 *b = *x;
}

/*
* 积分计算
*/
double g(double a, double b, double (*fp)(double))
{
 int i = 0;
 double s = 0;
 double d = (b - a)/10000;
 
 for(; i < 10000; i++){
  s += (*fp)(a + i * d + d / 2) * d;
 }
 return s;
}

double y(double x)
{
 return x;
}

//复合说明项
//error1: array element type cannot be function
//int a[10](int *, int);

//error2:
/*
int f1(int);
int f2(int);
int f(int x)
{
if(x > 0)
return f1;
else
return f2;
}*/
//例2.返回值是指向一个函数的指针:
//f是一个函数,形参是x,返回值是一个函数指针:其形参是float型,返回double.
double (* f(int x))(float);

//error3:function returns array
//int f()[10];
//例3.返回值是指向数组的指针
int (* fun(int))[10];

//自己实现的scanf()函数
void scanf_m(char *c, void *p)
{
 char a[100], *s = a, *r;
 while(*s = getchar(), *s != '/n')
  s++;
 *s = '/0';
 
 if(*c == 'd')
 {
  *(int *)p = atoi(a);
  return;
 }
 
 if(*c == 'f')
 {
  *(double *)p = atof(a);
  return;
 }
 else
 {
  s = a;
  r = (char *)p;
  while(*r ++ = *s ++);
 }
}

王老师 现在有 n 个字符串,聪明的小 Z 想要考考王老师 对于字符串的掌握程度。 聪明的小 Z 现在要求王老师 把他的所有字符串按照开头字母 a,b,...,z 分类,每类字符串分别按字典序排序,每类字符串存一个指针,程序开始时指针指向第一个字符串。 现在,聪明的小 Z 会根据这些字符串询问王老师 共 k 个问题。 每次查询,询问某一个字母,要求输出当前指针指向的字符串,然后将这个指针循环右移一位(即指针指向下一个字符串,若已经是该类字符串最后一个,则指向第一个字符串)。 请结合样例理解。 输入格式 第一行输入两个整数 n,k。 接下来 n 行,每行一个字符串。 接下来又有 k 行,每行输入一个要查询的字母 输出格式 共 k 行,每行一个字符串表示答案。 样例输入 1 4 5 zagreb split zadar sisak z s s z z 样例输出 1 zadar sisak split zagreb zadar 样例输入 2 5 3 london rim pariz moskva sarajevo p r p 样例输出 2 pariz rim pariz 样例输入 3 1 3 zagreb z z z 样例输出 3 zagreb zagreb zagreb 提示/说明 样例 1 解释 输入的字符串可以分成以下两类,并且每类字符串按照字典序排序: sisak → split zadar → zagreb 共 5 次询问: 第一次询问,字母 z,显然输出 z 类字符串的第一个字符串 zadar,然后 z 类字符串的指针移动到下一个字符串 zagreb 第二次询问,字母 s,显然输出 s 类字符串的第一个字符串 sisak,然后 s 类字符串的指针移动到下一个字符串 split 第三次询问,字母 s,此时 s 类字符串指针指向的是 split,将其输出,然后 s 类字符串的指针移动到下一个字符串 sisak 第四次询问,字母 z,此时 z 类字符串指针指向的是 zagreb,将其输出,然后 z 类字符串的指针移动到下一个字符串 zadar 第五次询问,字母 z,此时 z 类字符串指针指向的是 zadar,将其输出,然后 z 类字符串的指针移动到下一个字符串 zagreb 数据范围 对于 20% 的数据,n,k≤100。 对于 60% 的数据,n,k≤500。 对于 100% 的数据,n,k≤100000。 输入的字符串长度不超过 21,且仅包含小写字母。c++
08-11
王老师的老千计划 文件 IO比赛题目 时间限制: 1000MS空间限制: 512MB 题目描述 马上就要放暑假了! 王老师把小姜,邹老师,鲁老师叫到一起打牌,他们决定用打牌的方式选出一个赢家。 打牌的规则很简单,每个人手里有一些牌,牌上有一些点数,每一轮由王老师先打出一张牌,然后另外三人可以不出牌,但是要出牌则只能打出点数 严格大于 这张牌的牌,直到王老师手里打完牌后,游戏结束。 每个人最终的得分由打出的所有牌点数之和决定。 现在邹老师和鲁老师已经打完了自己的所有牌,王老师还剩下 n 张牌,小姜还剩下 m 张牌 王老师决定和小姜私下进行了合作——只要王老师帮助小姜成为赢家,那么小姜就带王老师出去玩。 现在王老师想知道,对于剩下的这些牌,怎么出牌可以让小姜获得尽可能大的得分? 输入格式 第一行包含两个整数 n,m 含义如题 第二行 n 个整数 A i ​ ,表示王老师手里每张牌的点数 第三行 m 个整数 B i ​ ,表示小姜手里每张牌的点数 输出格式 输出一行,表示在剩下的这些牌中,小姜能获得最大的得分 样例输入 1 3 4 3 4 7 1 2 4 8 样例输出 1 12 样例输入 2 3 3 10 7 8 4 7 6 样例输出 2 0 样例输入 3 见下发大样例数据 样例输出 3 见下发大样例数据 提示/说明 大样例数据 样例解释1 一种方案为: 王老师先打 3 小姜打 4 王老师再打 4,小姜打 8 最终得分为 4+8=12 样例解释2 无论王老师打什么牌,小姜都没法出牌,得分为 0 数据范围 测试点编号 1≤n,m≤ 1≤A i ​ ,B i ​ ≤ 1∼2 5 1000 3∼4 1000 1000 5∼7 10 5 1000 8∼10 10 5 10 9 贪心,不要使用vector
08-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值