指向多维数组的指针变量:
我们设二维数组的指针变量为p,可以定义为:int (p)[4],它表示p是一个指针变量,它指向包含4个元素的一维数组。
若指向第一个一维数组a[0],其值等于a,a[0],或者&a[0][0].二p+i则指向一维数组a[i]。所以(p+i)是指向一维数组的第几行
而要表示指针变量的二维数组:(p+i)+j,此时的j表示的就是第i行的第j列
二维数组指针变量说明的一般形式为:类型说明符 (指针变量名)[长度],这个括号是不可缺少的,缺少括号就变成了表示指针数组了
例子1:
int main()
{
int a[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11 },i,j;
int(*p)[4];
p = a;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("输出的是第%d行,第%d列.\n即第a[%d][%d]为:", i, j,i,j);
printf("%2d\n", *(*(p + i) + j));
}
}
return 0;
}
字符串的指针指向字符串的指针变量
在c语言中可以用两种方法来访问字符串
第一种:用字符数组存放一个字符串,然后输出该字符串
int main()
{
char string[] = "perseverance means victory";
printf("%s\n", string);
return 0;
}
第二种方法就是用只有变量来表示:因为string是数组名,他代表字符数组的首地址
int main()
{
const char *string = "perveserance means victory";//在c++里面,指针变量的数组一定要在类型说明符前面加上const
printf("%s\n", string);
return 0;
}
例子2:输出字符串中n个字符后的所有字符
int main()
{
const char *string = "perseverance means victory";
int n = 19;
string = string + n;
printf("%s\n", string);
return 0;
}
例子3:在输入的字符串中查找有没有t字符
int main()
{
char a[50];
char *string;
int i;
printf("please enter a string:\n");
string = a;
scanf_s("%s", string);
for (i = 0; string[i] != '\0'; i++)
{
if (string[i] == 't')
{
printf("there is a 't' in the string\n");
break;
}
}
if (string[i] == '\0')
{
printf("there is no 't' in the string");
}
return 0;
} //例子3代码运行发生错误,目前仍然不明白出错在哪里,希望大佬指点一下
例子4:用指针变量代替格式串
int main()
{
static int a[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
const char *PF;
PF = "%d,%d,%d,%d,%d\n";
printf(PF, a, *a, a[0], &a[0], &a[0][0]);
printf(PF, a + 1, *(a + 1), a[1], &a[1], &a[1][0]);
printf(PF, a + 2, *(a + 2), a[2], &a[2], &a[2][2]);
printf("%d,%d\n", a[1] + 1, *(a + 1) + 1);
printf("%d,%d\n", *(a[1] + 1), *(*(a + 1) + 1));
return 0;
}
例子5:字符串指针作为函数的参数使用。要求吧一个字符串的内容复制到另一个字符串中
void cpystr(char *pds, const char *pss)
{
while ((*pds = *pss) != '\0')
{
pds++;//这里不加*在前面是指地址自增
pss++;
}
return;
}
int main()
{
const char *pa = "CHINA";//加上 const变成了只读变量,但是可以改变pa这个指针
char b[10], *pb;//指针pb地址不可变,但可以改变指针指向的内容
pb = b;
cpystr(pb, pa);
printf("string a=%s\nstring b=%s\n", pa, pb);
return 0;
}
//简化后的程序:
void cpystr(char *pds, const char *pss)
{
while ((*pds++ = *pss++) != '\0');
return;
}
int main()
{
const char *pa = "CHINA";
char *pb, b[10];
pb = b;
cpystr(pb, pa);
printf("string a=%s\nstring b=%s\n", pa, pb);
return 0;
}
使用字符串指针变量和字符数组的区别:
字符串指针变量存放的是字符串的首地址,而字符串的本身存在是以首地址的一块连续的内存空间并以‘\0’作为串的结束
字符数组是有若干个数组元素组成的,它可用来存放整个字符串。
对数组的方式:
static char st[] = { "Perseverance mean victory" };
不能写成:
char st[20];
st="Perseverance means victory";
函数指针变量:
在c语言中,一个函数总是占用一段连续的内存区间,而函数名就是该函数所占内存区的首地址。我们可以把函数的这个首地址
赋予一个指针变量,使该指针变量指向该函数,然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量函数指针变量定义为:“函数指针变量”
函数指针变量定义的一般形式:
类型说明符 (指针变量名)();
例如:
int(*pf)();//表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整数
例子6:本例用来说明用指针形式实现对函数功能调用的方法
int max(int a, int b)
{
if (a > b) return a;
else return b;
}
int main()
{
int max(int a, int b);
//int(*pmax)()//这个就是错误的,在就旧的版本中不可用
int(*pmax)(int,int);//定义一个函数指针变量,也要说明函数的传递的形参类型
int x, y, z;
pmax = max;
printf("input two numbers:\n");
scanf_s("%d%d", &x, &y);
z = (*pmax)(x, y);
printf("maxnum=%d\n", z);
return 0;
}
函数指针变量的注意点:
1.函数指针变量不能进行算术运算,这是与数组指针变量不同的,函数指针的移动没有意义
指针型函数:
我们知道所谓的函数类型是指函数返回值的类型。在c语言中允许一个函数的返回值是一个指针(即地址),这种返回指针值的函数称为指针型的函数
定义指针型的函数的一般形式:
类型说明符 函数名(形参表)
例子7:通过指针函数,输入一个1~7之间的整数,输出对应的星期名。***
int main()
{
int i;
char *day_name(int n);
printf("input Day No:\n");
scanf_s("%d", &i);
if (i < 0)
{
exit(1);
}
printf("Day No:%2d-->%s\n", i, day_name(i));
return 0;
}
char *day_name(int n)
{
static char *name[] = { "I lleageal day",//有时候会出现这种错误-->无法从“const char ”转换为“char *”
"Monday", //出现这种错误的解决方法:点击项目属性 c++--> 语言--> 符合模式->> 选择否
"Tutesday",
"wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday" };
return ((n<1 || n>7) ? name[0] : name[n]);
}
应该要注意的是函数指针变量和指针型函数这两个的写法和意义上的区别。如:int (p)(类型说明符....) 具体看上面的例子6
指针型函数:int p(形参表)
函数指针变量int (*p)(int ,int)-->是一个***变量说明,说明p是一个指向函数入口的指针变量,该函数的返回值是整形量,(p)括号两边的符号不可少
指针型函数:int *p() 不是变量说明而是函数说明,说明p是一个指向函数入口的指针变量,该函数的返回值是整型量的指针
指针数组和指向指针的指针
指针数组的概念:一个数组的元素为指针则是指针数组。指针数组是一组有序的指针集合。指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量
指针数组的说明的一般形式:
类型说明符 *数组名[数组长度]
例子8:
int main()
{
int a[3][3] = { 1,2,3,4,5,6,7,8,9 };
int *pa[3] = { a[0],a[1],a[2] };//pa为指针数组
int *p = a[0];//一定要注意,指针p接收到的只是a数组的首地址
int i;
for (i = 0; i < 3; i++)
{
printf("%d,%d,%d\n", a[i][2 - i], *a[i], *(*(a + i) + i));
}
for (i = 0; i < 3; i++)
{
printf("%d,%d,%d\n", *pa[i], p[i], *(p + i));
}
return 0;
}
答案是:
3,1,2
5,4,5
7,7,9,
1,1,1,
4,2,2
7,3,3
指针数组也可以作函数参数
例子9
int main()
{
static char *name[] = { "Illegal day","Monday","Tuesday","Wednesday","Friday","Saturday","Sunny" };//指针数组
char *ps;
int i;
char *day_name(char *name[], int n);//指针型函数
printf("input Day No:\n");
scanf_s("%d", &i);
if (i < 0) exit(1);
ps = day_name(name, i);//指针型函数
printf("Day No:%2d-->%s\n", i, ps);
return 0;
}
char *day_name(char *name[], int n)//指针型函数
{
char *pp1, *pp2;
pp1= *name;
pp2 = *(name + n);
return ((n < 1 || n>7) ? pp1 : pp2);
}
例子10:输入5个国名,并按字母顺序排列后输出。
int main()
{
void sort(char *name[], int n);
void print(char *name[], int n);
static char *name[] = { "CHINA","AMERICA","AUSTARALIA","FRANCE","GERMAN" };
int n = 5;
sort(name, n);
print(name, n);
}
void sort(char *name[], int n)
{
char *pt;
int i, j, k;
for (i = 0; i < (n - 1); i++)
{
k = i;
for (j = i+1; j < n; j++)//j用于要和比较的前一个地址多加1
{
if (strcmp(name[k], name[j]) > 0)
{
k = j;
}
}
if (k != i)
{
pt = name[i];
name[i] = name[k];
name[k] = pt;
}
for (int i = 0; i < n; i++)
{
printf("%s\n", name[i]);
}
printf("\n\n");
Sleep(1000);
}
}
void print(char *name[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%s\n", name[i]);
}
}