C语言复杂的声明(数组指针和函数指针)

指针数组和数组指针:

int a[8][8]; //一个内含int数组的数组
int ** ptr;//指向指针的指针,被指向的指针指向int
int * b[10];//指针数组,内含10个元素的数组,每个元素都是指向int类型的指针
int (* b)[10];//数组指针,一个指向数组的指针,该数组有10个int类型的值
int * c[3][4];//二维指针数组,每个元素都是指向int类型的指针
int (* d)[3][4];//一个指向二维数组的指针,该数组中含int类型值
int (* d[3])[4];//一个内含三个指针元素的数组,每个指针都指向一个内含4个int类型元素的数组。

要看懂上述声明,关键要理解 * 、()、和 [ ] 的优先级:

  • ()和 [ ] 的优先级相同,但比 * (解引用运算符)的优先级高。
  • 遵循从左往右结合。

指针函数和函数指针:

char * a(int);  //指针函数,首先是一个函数,返回值为char类型的指针
char (* b) (int); //函数指针,首先是个指针,它指向函数,该函数的返回类型为char
char* c[3])(int;//内含三个指针的数组,每个指针都指向一个返回值为char类型的函数。

函数指针

通常,函数指针用作另一个函数的参数,告诉函数要使用哪一个函数。
函数指针:指向函数的指针。函数也有地址,因为函数的机器语言实现由载入内存的代码组成,指向函数的指针存储着函数代码的起始位置的地址。
函数原型:

void ToUpper(char *);//带char * 类型参数、返回类型是void的函数

指向该函数的指针:

void (*pf) (char *); //pf是指向函数的指针

把函数名ToUpper替换成表达式(pf)是创建指向函数指针最简单的方式。所以 想声明一个指向某类型函数的指针,可以先写出该函数的原型,然后再把函数名用(*pf)替换即可 。

声明了函数指针后,可以把类型匹配的函数地址赋给它,在这种上下文中,函数名可以用于表示函数的地址:

void ToUpper(char *);
void ToLower(char *);
int round(double);
void (*pf)(char *);
pf = ToUpper;    //有效,ToUpper是该类型函数的地址
pf = ToLower;    //有效,ToLower是该类型函数的地址
pf = round;         //无效,round不是该类型函数的地址
pf = ToLower()//无效,ToLower()不是地址
//函数指针
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define LEN 81
char * s_gets(char * st, int n);
char showmenu(void);
void eatline(void); //读取至行末尾
void show(void(*fp)(char *), char * str);
void ToUpper(char *);
void ToLower(char *);
void Transpose(char *);
void Dummy(char *);

int main(void)
{
	char line[LEN];
	char copy[LEN];
	char choice;
	void(*pfun)(char *);//声明一个函数指针,被指向的函数接受 char * 类型的参数,无返回值。
	
	puts("Enter a string (empty line to quit):");
	while(s_gets(line,LEN) != NULL && line[0] != '\0')
	{
		while ((choice = showmenu()) != 'n')
		{
			switch(choice)
			{
				case 'u': pfun = ToUpper; break;
				case 'l': pfun = ToLower; break;
				case 't': pfun = Transpose; break;
				case 'o': pfun = Dummy; break;
			} 
			strcpy(copy,line);
			show(pfun, copy);
		}
		puts("Enter a string (empty line to quit):");
	} 
	puts("Bye!");
	
	return 0;	
} 

char showmenu(void)
{
	char ans;
	puts("Enter menu choice:");
	puts("u) uppercase         l) lowercase");
	puts("t) transposed case   o) original case");
	puts("n) next string");
	ans = getchar();
	ans = tolower(ans);
	eatline(); //清理输入行
	while (strchr("ulton", ans) == NULL)
	{
		puts("Please enter a u, l, t, o, or n:");
		ans = tolower(getchar());
		eatline();	
	} 
	
	return ans;
}

void eatline(void)
{
	while (getchar() != '\n')
		continue;
}
void ToUpper(char * str)
{
	while (*str)
	{
		*str = toupper(*str);
		str++;
	}
}
void ToLower(char * str)
{
	while (*str)
	{
		*str = tolower(*str);
		str++;
	}
}
void Transpose(char * str)
{
	while(*str)
	{
		if(islower(*str))
			*str = toupper(*str);
		else if(isupper(*str))
			*str = tolower(*str);
		
		str++; 
	}
}

void Dummy(char * str)
{
	//不改变字符 
}

void show(void(*fp) (char *), char * str)
{
	(*fp)(str);//把用户选定的函数作用于str 
	puts(str);//显示结果 
}


char * s_gets(char * st, int n){
	char * ret_val;
	int i = 0;
	
	ret_val = fgets(st, n, stdin);//如果一切进行顺利,返回的是第一个字符的地址 ,遇到文件结尾或者错误时返回NULL 
	if(ret_val){//如果输入成功 
		while (st[i] != '\n' && st[i] != '\0')//跳转到字符串末尾 
			i++;
		if(st[i] == '\n')//替换掉换行符 
			st[i] = '\0';
		else//如果输入字符串超出字数,之后的字符就省略 
			while (getchar() != '\n')
				continue;
	} 
	return ret_val;//输入正常则返回字符串首字符地址 
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值