指针的进阶

字符指针

    char ch = 'a';
	char* ps = &ch;//pc指向一个字符变量

	const char* p = "hello world";//"hello world"是一个常量字符串
	//把常量字符串第一个字符h的地址赋值给p
	//最好加const

	printf("%c", *p);
	printf("%s", p);
	//%s 打印字符串只需要提供首元素的地址就可以,不需要再解引用

例题

	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	char* str3 = "hello bit.";
	char* str4 = "hello bit.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

在这里插入**加粗样式**图片描述
常量字符串存放在常量区,不能被修改,两个指针指向同样的常量字符串,这个常量字符串只会存一份

指针数组

	int arr[10];//整型数组-存放整型的数组
	char arr1[4];//字符数组- 存放字符的数组

	//指针数组-存放指针的数组
	char* arr2[5];//arr2是存放字符指针的数组
	int* arr3[5];//arr3是存放整型指针的数组

指针数组的应用

在这里插入图片描述


	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	int* parr[] = { arr1,arr2,arr3 };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", *(parr[i]+j));
			//parr[i][j]==*(parr[i]+j)
		}
		printf("\n");
	}

parr[i][j]==*(parr[i]+j)
parr是数组名,数组名是数组首元素的地址,也就是int* 类型变量的地址
int** p=parr;//&arr[0]
在这里插入图片描述

数组指针

int* p;//整型指针 - 指向整型的指针
char* p;//字符指针 - 指向字符的指针

数组指针:指向数组的指针
在这里插入图片描述

int *p1[10];//p1是个数组,存放的每个元素类型是int*
int (*p2)[10];//p2是个指针,指向的是个数组,数组是十个元素,每个元素的类型是int

数组指针的类型就是去掉名字,剩下的就是类型int (*)[10]

    int* arr1[10];
	int* (*p2)[10] = &arr1;

接下来看个常见的用&数组名遍历数组错误

void print1(int(*p)[10],int sz)//错误示范
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", p[i]);//p[i]==*(p+i)
	}
}

如果想要&数组名遍历数组,下面这种写法可以

在这里插入图片描述
数组指针在二维数组用的较多
在二维数组里,arr是数组名,数组名是首元素的地址,也就是二维数组的第一行的地址,第一行是个数组,数组的地址应该放在一个数组指针

//p就是数组指针
void print2(int (*p)[5], int row, int line)
{
	for (int i = 0; i < row; i++)
	{ 
		for (int j = 0; j < line; j++)
		{
			//printf("%d ", *(*(p + i) + j));
			prinft("%d ", p[i][j]);
		}
		printf("\n");
	}
}

//遍历二维数组不用数组指针
//参数部分也是二维数组
void print(int arr[3][5], int row, int line)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < line; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

*(p + i)相当于找到第i行起始位置的地址

思考:int (*parr3[10])[5]表示什么?
parr3是一个数组,数组有十个元素,每个元素是一个数组指针,该指针指向的数组有5个元素,每个元素是int

数组参数,指针参数

一维数组传参

void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int* arr)//ok
{}

int main()
{
	int arr[10] = { 0 };
	test(arr);
	return 0;
}
void test2(int** arr)//ok
{}
void test3(int* arr[])//ok
{}
int main()
{
	int* arr2[20] = { 0 };
	test2(arr2);
	return 0;
}

一维数组传参时,参数可以是数组,也可以是指针,参数如果是数组大小可以省略,因为并不会真正创建一个数组

二维数组传参

void test(int arr[][5])//行可以省略,列不可以
{}

void test(int(*arr)[5])//参数是指向一维数组的指针
{}
int main()
{
	int arr[3][5] = { 0 };
	test(arr);//数组名是首元素的地址,也就是二维数组第一行的地址
	return 0;
}

二维数组首元素,指的是第一行

一级指针传参可以接收什么参数?

void test(int* p)
{}

int main()
{
	int a = 10;
	int arr[10];
	int* p = &a;
	test(&a);
	test(p);
	test(arr);
	return 0;
}

二级指针传参可以接收什么参数?

void test(int** ppa)//参数是二级指针
{}

int main()
{
	int a = 10;
	int* pa = &a;
	int** ppa = &pa;
    int* arr[5];//指针数组

	test(ppa);
	test(&pa);
	test(arr);
	return 0;
}

函数指针

函数指针变量 - 存放函数的地址,函数是有地址的

跟数组不一样,数组名 - 首元素地址;&数组名 - 数组的地址

函数名==&函数名

在这里插入图片描述
用来存放函数地址的指针变量,它的类型是什么样的?
在这里插入图片描述
int (*)(int,int)就是pf的类型,但是不能int (*)(int,int) p2这么定义

如何使用

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int (*pf)(int,int) = &Add;
	//int (*pf)(int,int) = Add;

	int ret = (*pf)(4, 5);//*写不写无所谓
	int ret2 = pf(6, 5);

	return 0;
}

pf前可以不写*号,*号在这里就是摆设

思考两行代码(*(void (*)())0) ();void (*signal(int, void(*)(int)))(int);

    (*(void (*)())0) ();
	//上面这行代码是一次函数调用
	//1.代码中把0强制类型转换为类型为void (*)()的一个函数的地址
	//2.解引用0的地址,就是调用0地址处的函数,被调的函数是无参,返回类型是void


	void (*signal(int, void(*)(int)))(int);
	//上面的代码是一次函数声明
	//声明的函数名是signal
	//signal函数有两个参数,第一个是int类型,第二个是void(*)(int)
	//signal函数的返回类型依然是void(*)(int)

如果函数指针的类型想用typedef
在这里插入图片描述

经过简化,signal函数可以写成func signal2(int, func);

函数指针数组

    //函数指针的数组 - 存放函数指针的数组
	int(*arr[3])(int, int) = {Add,Sub,Mul };
	//int(*arr[3])(int,int) = { pf1,pf2,pf3 };
	//arr先和[]结合,表面arr是个数组;
	//去掉arr[],int(*)(int,int)是数组元素的类型

函数指针数组的用途:

int Add(int x, int y)
{
	return x + y;
}

int Sub(int x, int y)
{
	return x - y;
}

int Mul(int x, int y)
{
	return x * y;
}

int main()
{
	int input = 0;
	int ret = 0;
	do
	{
		int x, y;
		scanf("%d", &input);
		scanf("%d %d", &x, &y);
		//函数指针数组
		int (*pfarr[4])(int, int) = { 0,Add,Sub,Mul };
		if (input == 0)
		{
			break;
		}
		else if (input >= 1 && input <= 3)//根据input的值选择调用哪个函数
		{
			ret = pfarr[input](x, y);
			printf("%d", ret);
		}
		else
		{
			printf("选择错误");
		}
	} while (input);
	return 0;
}

也可以用函数的方式,参数是函数指针,让calc有多种功能(回调函数

int Add(int x, int y)
{
	return x + y;
}

int Sub(int x, int y)
{
	return x - y;
}

int Mul(int x, int y)
{
	return x * y;
}

void Calc(int (*pf)(int, int))//参数是函数指针
{
	int x, y, ret;
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d", ret);
}

int main()
{
	Calc(Add);
	return 0;
}

指向函数指针数组的指针

先回顾数组指针整形指针数组

    int arr[10];
	int(*p)[10]=&arr;//p是指向整形数组的指针

	int* arr1[10];//整形指针的数组
	int* (*pf)[10] = &arr1;//整形指针数组的地址
	//pf是指向整形指针数组的指针

而指向函数指针数组的指针如何表示?
在这里插入图片描述

回调函数

在这里插入图片描述

int main()
{
	int a = 10;
	float f = 0.22;

	//void* -无具体类型指针
	//能够接收任意类型的地址
	//缺点,不能进行运算,不能加减整数,不能解引用,因为没有具体的
	void* p3 = &a;
	//p3++;*p3
	void* p4 = &f;

	return 0;
}

之前我们写过冒泡排序,但它只能比较int类型,而qsort能排列不同类型的数组

#include<stdlib.h>

int com_int(const void* e1, const void* e2)//回调函数
{
	return *(int*)e1 - *(int*)e2;//e1和e2要先强制类型转换成int*
}

int main()
{
		int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	    int sz = sizeof(arr) / sizeof(arr[0]);
		qsort(arr, sz, sizeof(arr[0]), com_int);

	    for (int i = 0; i < sz; i++)
		    printf("%d ", arr[i]);
	
	return 0;
}

qsort不仅能给整形数组排序,还能给结构体类型的数组排序

struct stu
{
	char name[20];
	int age;
};

int cmp_name(const void* e1, const void* e2)//e1指向一个结构体类型
{
	//return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
	return strcmp((*(struct stu*)e1).name, (*(struct stu*)e2).name);
}

int main()
{
	struct stu s[3] = { {"张三",10},{"李思",20},{"王武",21}};
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_name);
	return 0;
}

模拟实现qsort

int com_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;//e1和e2要先强制类型转换成int*
}

void Swap(char* buf1, char* buf2,int width)
{
	
	for (int i = 0; i < width; i++)//一个字节一个字节的交换
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;

	}
}

void Bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))//e1和e2可以不写
{
	for (size_t i = 0; i < sz - 1; i++)
	{
		for (size_t j = 0; j < sz - 1 - i; j++)
		{
			//这里强制类型转换成char*也很巧妙,char*类型加1就是往后跳过一个字节
			if (cmp((char*)base+width*j, (char*)base + width*(j+1))>0)
		//这里体现width的作用了,void* 类型的指针变量不能运算,必须强制类型转换
		//每个元素之间相差width个字节,因此能比较不同类型的变量
			{
				Swap((char*)base + width * j, (char*)base + width * (j + 1),width);
				//把相邻的两个元素交换
			}
		}
	}
}

void test1()
{
		int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	    int sz = sizeof(arr) / sizeof(arr[0]);
		Bubble_sort(arr, sz, sizeof(arr[0]), com_int);

	    for (int i = 0; i < sz; i++)
		    printf("%d ", arr[i]);
}

int main()
{
	test1();
	return 0;
}

指针和数组笔试题

数组名是数组首元素的地址,相当于&arr[0]
但是有两个例外:

  1. sizeof(数组名)数组名单独放在sizeof内部 - 数组名表示整个数组,计算的是整个数组的大小,单位是字节
  2. &数组名 - 数组名表示整个数组,取出的是整个数组的地址

sizeof - 操作符 求变量所占空间的大小,求类型创建的变量所占的空间大小
strlen - 库函数,求字符串长度

整形数组

重点看sizeof(a+0)sizeof(*&a)

	//指针的大小在32位下是4个字节,在64位下是8个字节
	//一维数组
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16 - 数组名单独放在sizeof内部,计算的是整个数组的大小
	printf("%d\n", sizeof(a + 0));//4/8 - sizeof内部不仅有数组名,a+0就是数组首元素的地址
	printf("%d\n", sizeof(*a));//4 - a是首元素地址,*a就是首元素
	printf("%d\n", sizeof(a + 1));//4/8 - a+1是第二个元素的地址
	printf("%d\n", sizeof(a[1]));//4 - a[1]就是第二个元素
	printf("%d\n", sizeof(&a));//4/8 -  &数组名,取出的是数组的地址,但还是地址
	printf("%d\n", sizeof(*&a));//16 - &数组名,取出的是数组的地址,解引用就拿到整个数组
	//*&a=a
	printf("%d\n", sizeof(&a + 1));//4/8 - &a是数组的地址,&a+1,就是数组的地址+1,跳过整个数组,但还是地址
	printf("%d\n", sizeof(&a[0]));//4/8 - 首元素的地址
	printf("%d\n", sizeof(&a[0] + 1));//4/8 - 第二个元素的地址

字符数组

sizeof

	//字符数组
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6
	printf("%d\n", sizeof(arr + 0));// 4/8
	printf("%d\n", sizeof(*arr));// 1
	printf("%d\n", sizeof(arr[1]));// 1
	printf("%d\n", sizeof(&arr));// 4/8
	printf("%d\n", sizeof(&arr + 1));// 4/8
	printf("%d\n", sizeof(&arr[0] + 1));// 4/8

strlen

    //字符数组
    char arr[] = { 'a','b','c','d','e','f' };
	//sizeof - 操作符 求变量所占空间的大小,求类型创建的变量所占的空间大小
	//strlen - 库函数,求字符串长度
	printf("%d\n", strlen(arr));//随机值 arr是首元素地址(没有&也没有单独放在sizeof内部)
	printf("%d\n", strlen(arr + 0));//随机值,跟上面一行一样
	printf("%d\n", strlen(*arr));//报错 *arr - 'a' -ASCII码值为97
	//strlen就以为传进来的'a'的ASCII码值97就是地址

	printf("%d\n", strlen(arr[1]));//报错 arr[1] - 'b'- ASCII码值为98
	printf("%d\n", strlen(&arr));// 随机值 跟strlen(arr)的随机值一样
	//&arr的类型是char(*)[6]
	//strlen参数类型是char* ,虽然类型不匹配,但传过去没有问题
	printf("%d\n", strlen(&arr + 1));//随机值  数组的地址+1,跳过整个数组
	printf("%d\n", strlen(&arr[0] + 1));//随机值

sizeof

	//char arr[] = { 'a','b','c','d','e','f' };
	//a b c d e f - 数组有6个元素
	char arr[] = "abcdef";
	//a b c d e f \0 - 数组有七个元素
	printf("%d\n", sizeof(arr));//7 
	printf("%d\n", sizeof(arr + 0));// 4/8 arr+0,arr是首元素地址
	printf("%d\n", sizeof(*arr));//1 arr首元素地址,解引用就是'a'
	printf("%d\n", sizeof(arr[1]));//1 'b'的大小
	printf("%d\n", sizeof(&arr));// 4/8 数组的地址
	printf("%d\n", sizeof(&arr + 1));// 4/8 跳过整个数组的地址
	printf("%d\n", sizeof(&arr[0] + 1));// 4/8 第二个元素的地址

strlen

	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6 '\0'前6个字符
	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));// 报错
	printf("%d\n", strlen(arr[1]));//报错
	printf("%d\n", strlen(&arr));// 6 虽然类型不匹配,但是不影响
	printf("%d\n", strlen(&arr + 1));// 随机值 
	printf("%d\n", strlen(&arr[0] + 1));// 5

常量字符串

sizeof

	const char* p = "abcdef";
	printf("%d\n", sizeof(p));// 4/8 p是指针变量,用来存放字符串首元素的地址
	printf("%d\n", sizeof(p + 1));// 4/8 p+1是'b'的地址
	printf("%d\n", sizeof(*p));//1
	printf("%d\n", sizeof(p[0]));//1 p[0]就是*(p+0)
	printf("%d\n", sizeof(&p));// 4/8 &p取出p的地址
	printf("%d\n", sizeof(&p + 1));//4/8 
	printf("%d\n", sizeof(&p[0] + 1));//4/8 'b'的地址

strlen

	const char* p = "abcdef";
	printf("%d\n", strlen(p));// 6
	printf("%d\n", strlen(p + 1));//5
	printf("%d\n", strlen(*p));//报错
	printf("%d\n", strlen(p[0]));//报错
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值,跟上面一行的随机值无关
	printf("%d\n", strlen(&p[0] + 1));//5 b的地址往后找'\0'

二维数组(重要)

二维数组也是数组
1.sizeof(数组名),计算整个二维数组的大小
2.&数组名,取出的是整个二维数组的地址
除此之外,所有的数组名都是数组首元素的地址
二维数组数组名表示首元素的地址,而二维数组的首元素是它的第一行
在这里插入图片描述

	//二维数组
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48
	printf("%d\n", sizeof(a[0][0]));//4
	printf("%d\n", sizeof(a[0]));//16
	//a[0]是第一行的数组名,数组名单独放在sizeof内部,计算整个数组大小
	printf("%d\n", sizeof(a[0] + 1));//4/8 
	//sizeof内部不是只有数组名,a[0]代表数组首元素地址,第一行第一个元素地址,即a[0][0]的地址
	//a[0]+1就算第一行第二个元素的地址
	printf("%d\n", sizeof(*(a[0] + 1)));//4 *(a[0] + 1))就算第一行第二个元素
	printf("%d\n", sizeof(a + 1));//4/8 
	//数组名a并没有单独放在sizeof内部,也没有&,所以a表示首元素(第一行)地址
	//所以a+1是第二行的地址,类型int(*)[4],a+1等价于&a[1]
	printf("%d\n", sizeof(*(a + 1)));//16 *(a+1)等价于a[1],就是第二行
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//&a[0]+1和a+1,一样
	//a[0]是第一行数组名,&a[0]拿到第一行地址,&a[0]+1就是第二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//16
	//*(&a[0] + 1)) - 第二行 - a[1]
	//a[1]是第二行的数组名
	printf("%d\n", sizeof(*a));//a表示首元素(第一行)地址,*a拿到的就是第一行,相当于第一行数组名
	printf("%d\n", sizeof(a[3]));//16 a[3]假设存在,就第四行的数组名,根据他的类型确定大小
	//相当于第四行的数组名
	//虽然二维数组没有第四行
	//sizeof不会去访问不存在的第四行,计算的是它的类型属性

在这里插入图片描述

指针笔试题

下面这段程序的结果是什么?打印2 5

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	//&a的类型是int(*)[5],+-1跳过整个数组,被强制类型转换成int*
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));//2 5
	return 0;
}

下面这段程序的结果是什么?

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;

int main()
{
	//p的类型是struct Test* 而0x100000是个十六进制数,类型是int
	//0x100000赋给p要强制类型转换
	p = (struct Test*)0x100000;
	//0x1是16进制的1,还是1
	printf("%p\n", p + 0x1);//0x100014
	//p+0x1跳过一个结构体,结构体大小是二十个字节,答案不是0x100020,1是1*16的一次方,4是4*16的0次方
	printf("%p\n", (unsigned long)p + 0x1);//0x1000001
	//p的类型被强制类型转换成unsignded long,不再是指针了
	//整形+1就是+1
	printf("%p\n", (unsigned int*)p + 0x1);//0x1000004
	return 0;
}

下面这段程序的结果是什么?4 2000000

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	//%x - 以16进制打印
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

在这里插入图片描述
下面这段程序的结果是什么?1

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	//陷阱:()里的是逗号表达式,结果是最后应该表达式的结果
	//所以a[3][2]里真正放的是{1,3,5}
	int* p;
	p = a[0];//a[0]是第一行的数组名,代表首元素地址
	printf("%d", p[0]);//p[0]等价于*(p+0)
	return 0;
}

在这里插入图片描述
下面这段程序的结果是什么?FFFFFFFC,-4

int main()
{
  int a[5][5];
  int(*p)[4];
  p = a;
  printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
  //                       地址-地址             地址-地址
  //-4在内存中的补码是FFFFFFFC
  //%p是以十六进制打印地址,没有原反补的概念,所以之间打印-4在内存中的补码FFFFFFFC
  return 0;
}

在这里插入图片描述
下面这段程序的结果是什么?10,5

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	//(int*),强制类型转换不起作用,因为*(aa+1)的类型就是int*
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10 5
	return 0;
}

下面这段程序的结果是什么?at

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	//pa的类型是char**,+1往后跳过一个char*
	pa++;
	printf("%s\n", *pa);
	return 0;
}

在这里插入图片描述
(难)下面这段程序的结果是什么?

int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *-- * ++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW
	return 0;
}

在这里插入图片描述

作业

1.打印杨辉三角

int main()
{
	int arr[10][10] = { 0 };//用二维数组来表示杨辉三角
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j <= i; j++)//每行只考虑j==0到j==i
		{
			if (j == 0 || i == j)//把每一行第一个和最后一个数初始化为1
				arr[i][j] = 1;
			if (i > 1 && j > 0)//其余的数等于上一行的数+上一行之前的数
				arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
		}
	}
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j <= i; j++)
			printf("%d ", arr[i][j]);
		printf("\n");
	}
	return 0;
}

在这里插入图片描述
2.实现一个函数,可以左旋字符串中的k个字符

#include<stdio.h>
#include<string.h>

void Reverse(char* left, char* right)
{
	while (left < right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

void left_move(char arr[], int k)//ABCDEF  3
{
	int len = strlen(arr);
	Reverse(arr, arr + k - 1);//先把ABC逆序,得到CBADEF
	Reverse(arr + k, arr + len - 1);//再把DEF逆序,得到CBAFED
	Reverse(arr, arr + len - 1);//最后整体逆序得到,DEFABC
}

int main()
{
	char arr[] = "ABCDEF";
	left_move(arr,3);
	printf("%s", arr);
	return 0;
}

3.写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串

int Is_left_move(char arr1[], char arr2[])
{
	int len1 = strlen(arr1);
	int len2 = strlen(arr2);
	if (len1 != len2)
		return 0;
	strncat(arr1, arr1, len1);//strncat在arr1后面追加arr1的字符,个数是len
	if (strstr(arr1, arr2) == NULL)
	//strstr,判断arr2是不是arr1中的一部分,不是的话返回NULL,是的话返回arr1中arr2那部分的起始地址
		return 0;
	else
		return 1;
}

int main()
{
	char arr1[20] = "ABCDEF";
	char arr2[] = "CDEFAB";
	int ret=Is_left_move(arr1, arr2);
	if (ret == 1)
		printf("是左旋");
	return 0;
}

4.看一个数是否在杨氏矩阵里,杨氏矩阵每一行和每一列都是递增的

void find_k(int arr[3][3], int row, int line, int k)
{
	int x = 0, y = line - 1;
	while (x < row && y >= 0)
	{
		//拿每一行最右边的数跟k比较
		if (arr[x][y] < k)//小于k就往下一行找
			x++;
		else if (arr[x][y] > k)//大于k就往上一列找
			y--;
		else
		{
			printf("x的下标%d y的下标%d", x, y);
			return;
		}
	}
	printf("找不到");
}

int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int k = 7;
	find_k(arr, 3, 3, k);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值