栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C语言基础10:指针进阶】字符指针、指针数组、数组指针、函数指针、函数指针数组、回调函数、数组名详解、杨氏矩阵、字符串旋转

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C语言基础10:指针进阶】字符指针、指针数组、数组指针、函数指针、函数指针数组、回调函数、数组名详解、杨氏矩阵、字符串旋转

指针进阶 字符指针

字符指针的另一种使用方式

#include 

int main()
{
    //字符指针的使用
    char ch = 'q';
    char * pc = &ch;

    //本质上是把这个字符串的首字符地址存储在了指针变量ps中
    const char * ps = "hello world";
    //数组存储字符串时,是把整个字符串都存储在其中。
    char arr[] = "hello world";

    printf("%cn",*ps);//h
    printf("%sn",ps);//hello world   %s打印,遇到字符串结束符停止
    printf("%sn",arr);//hello world

    return 0;
}

因为常量字符串不可以被修改,所以相同的常量字符串,在内存中只会存储一份。

#include 

int main()
{
    //每个数组初始化都会开辟空间,即使两个数组中保存的是相同的数据,也会另外开辟空间,其内存地址不同。
    char str1[] = "hello world.";
    char str2[] = "hello world.";

//    char * str3 = "hello world.";
//    char * str4 = "hello world.";
    //这里的"hello world."是一个常量字符串。不能使用*解引用操作修改。
    //因为不能使用*修改,所以一般要使用const修饰,是用于修饰*str3或*str4,所以const要写在*的左边
    const char * str3 = "hello world.";
    const char * str4 = "hello world.";
    /

int main()
{
    //整型指针,指向整型的指针;
    int i = 10;
    int *pi = &i;
    // 字符指针,是指向字符的指针。
    char c = 'c';
    char * pc = &c;

    //数组指针
    int arr[10] = {0};

    //数组名是数组首元素的地址,arr存储数组首元素地址;&arr,取出的是整个数组的地址。
    //因为[]下标引用符的优先级比*解引用操作符的优先级高,所以这样写就成了指针数组:
    //int * parr[10] = &arr;

    //所以要先让*与parr结合,这样就是指针了,结合之后再与[10]结合,就叫做数组指针
    //parr就是一个数组指针,其中存放的是一个数组的地址。int表示指向的数组是int类型的,[10]表示指向的数组中存储了10个元素
    int (*parr)[10] = &arr;

    //d是一个指针数组,其中存储的是一级浮点型指针
    double * d[5];
    //取d的地址,是取出d这个数组。d这个数组是double*类型的 ,有5个元素。
    //又因为是存储数组的地址,所以pd是一个数组指针。加()先与*结合,再与[]结合
    double* (*pd)[5] = &d;

    return 0;
}

数组名 与 &数组名 的区别


#include 

int main()
{

    int arr[9] = {0};
    //arr和&arr分别是什么?
    int * p1 = arr;
    int (*p2)[9] = &arr;

    //数组名arr表示的是数组首元素的地址,arr+1,加了4个字节,也就是加一个int类型大小。
    printf("%pn",p1);//0000009cbf1ff780
    printf("%pn",p1+1);//0000009cbf1ff784

    //&arr,取出的是整个数组,&arr+1,加的是0x24,十进制就是36个字节,加的是整个数组大小。
    printf("%pn",p2);//0000009cbf1ff780
    printf("%pn",p2+1);//0000009cbf1ff7a4
    
    return 0;
}

数组指针使用示例,并不建议这样使用。

#include 

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

    int (*pa)[10] = &arr;
    int i;
    for(i=0 ; i<10 ; i++)
    {
        /
函数指针

函数指针语法

//函数返回类型 (*函数指针变量名)(函数参数[,函数参数......]) = 函数名/&函数名
#include 

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

void test(char* str){}

int main()
{
    //函数指针——存放函数地址的指针。
    //&函数名:取出函数的地址。
    printf("%pn",&Add);//00007ff6562617a1
    //函数名,表示的也是函数的地址。 函数名==&函数名
    printf("%pn",Add);//00007ff6562617a1

    //pf就是一个函数指针变量。
    //因为()优先级要比*高,所以要写成(*pf),意思是pf是一个指针,指向参数为(int,int),返回类型为int的函数。
    //int (*pf)(int,int) = &Add;
    //printf("%pn",*pf);//00007ff6562617a1

    //test函数指针
    void (*pt)(char*) = &test;

    //通过指针调用函数:
    //先解引用(*pf)找到这个函数然后传递参数(3,5)。然后使用变量接收返回值。
    //int ret = (*pf)(3,5);
    //printf("%d",ret);//8

    //因为&函数名与函数名等效。也就是说Add的地址直接放到了pf中
    //函数Add保存的是函数本身的地址,pf保存的是Add函数的地址。所以Add === pf
    int (*pf)(int,int) = Add;

    //平时我们调用函数:
    int ret = Add(3,9);
    printf("%dn",ret);//12

    //使用指针解引用调用
    ret = (*pf)(10,33);
    printf("%dn",ret);//43

    //因为Add===pf,所以我们也可以这样调用:
    ret = pf(22,44);
    printf("%dn",ret);//66

    //所以调用时,(*pf)===pf===Add

    return 0;
}

《C陷阱和缺陷》中的两段代码解读



int main()
{
    //使用typedef对类型进行重定义
    //typedef void(*)(int) pfun_t;  指针类型的*要与名字写在一起,所以就成为:
    typedef void(*pfun_t)(int);  //将void(*)(int)函数指针类型,重命名为pfun_t
    pfun_t signal(int,pfun_t);
    return 0;
}
函数指针数组

函数指针数组的定义

//函数指针数组:存放函数指针的数组
//函数指针数组定义语法:指向的函数的返回类型 (*函数指针数组变量名[函数指针数组元素个数])(函数参数);
int Add(int x, int y)
{
    return x+y;
}
int Sub(int x, int y)
{
    return x-y;
}

int main()
{
    int (*pf1)(int,int) = Add;
    int (*pf2)(int,int) = Sub;

    //函数指针数组,也是一个数组,所以直接在变量名后面加[2]。*pfArr[2]就表示一个指针数组
    //剩下的int (int,int)是数组元素类型。也就是说每个元素都指向一个参数为(int,int),返回类型为int的函数。
    int(*pfArr[2])(int,int) = {Add, Sub};

    return 0;
}

函数指针数组的应用:计算器

//计算器,计算整型变量的加减乘除。
#include 
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 Div(int x , int y)
{
    return x/y;
}

void menu()
{
    printf("------------------------------------n");
    printf("------输入菜单序号执行对应功能---------n");
    printf("------------- 0.退出 ----------------n");
    printf("------------- 1.加法 ----------------n");
    printf("------------- 2.减法 ----------------n");
    printf("------------- 3.乘法 ----------------n");
    printf("------------- 4.除法 ----------------n");
    printf("-------------------------------------n");
}

int main()
{

    //条件
    int input = 1;
    //函数指针数组
    int(*pfArr[5])(int,int) = {0,Add,Sub,Mul,Div};
    //循环
    while(input)
    {
        menu();
        printf("请选择:");
        scanf("%d",&input);

        if(input >0 && input<5)
        {
            int x,y,ret;
            printf("输入要进行操作的两个数:");
            scanf("%d %d",&x,&y);
            //ret = (*pfArr[input])(x,y);  /
//一个数组,如 int arr[10]
//去掉数组名,是数组类型:int [10]  ; 去掉数组名[],是数组中的元素类型:int

#include 

void test(const char* str)
{
    printf("%sn",str);
}
int main()
{
    //函数指针pfun
    void (*pfun)(const char*) = test;
    //函数指针数组pfunArr
    void (* pfunArr[5])(const char*);
    pfunArr[0] = test;
    //指向函数指针数组pfunArr的指针ppfunArr
    void (*(*ppfunArr)[5])(const char *) = &pfunArr;
    return 0;
}
回调函数

回调函数是什么?

  

使用回调函数改进以下程序

#include 
int Add(int a, int b)
{
    return a + b;
}
int Sub(int a, int b)
{
    return a - b;
}
int Mul(int a, int b)
{
    return a*b;
}
int Div(int a, int b)
{
    return a / b;
}
void menu()
{
    printf("------------------------------------n");
    printf("------输入菜单序号执行对应功能---------n");
    printf("------------- 0.退出 ----------------n");
    printf("------------- 1.加法 ----------------n");
    printf("------------- 2.减法 ----------------n");
    printf("------------- 3.乘法 ----------------n");
    printf("------------- 4.除法 ----------------n");
    printf("-------------------------------------n");
}
int main()
{
    int x, y;
    int input = 1;
    int ret = 0;
    do
    {
        menu();
        printf( "请选择:" );
        scanf( "%d", &input);
        switch (input)
        {
            case 1:
                printf( "输入操作数:" );
                scanf( "%d %d", &x, &y);
                ret = Add(x, y);
                printf( "ret = %dn", ret);
                break;
            case 2:
                printf( "输入操作数:" );
                scanf( "%d %d", &x, &y);
                ret = Sub(x, y);
                printf( "ret = %dn", ret);
                break;
            case 3:
                printf( "输入操作数:" );
                scanf( "%d %d", &x, &y);
                ret = Mul(x, y);
                printf( "ret = %dn", ret);
                break;
            case 4:
                printf( "输入操作数:" );
                scanf( "%d %d", &x, &y);
                ret = Div(x, y);
                printf( "ret = %dn", ret);
                break;
            case 0:
                printf("退出程序n");
                break;
            default:
                printf( "选择错误n" );
                break;
        }
    } while (input);

    return 0;
}

改进

#include 
int Add(int a, int b)
{
    return a + b;
}
int Sub(int a, int b)
{
    return a - b;
}
int Mul(int a, int b)
{
    return a*b;
}
int Div(int a, int b)
{
    return a / b;
}
void menu()
{
    printf("------------------------------------n");
    printf("------输入菜单序号执行对应功能---------n");
    printf("------------- 0.退出 ----------------n");
    printf("------------- 1.加法 ----------------n");
    printf("------------- 2.减法 ----------------n");
    printf("------------- 3.乘法 ----------------n");
    printf("------------- 4.除法 ----------------n");
    printf("-------------------------------------n");
}

void calc(int (*pf)(int,int ))
{
    int x, y,ret;
    printf( "输入操作数:" );
    scanf( "%d %d", &x, &y);
    ret = pf(x, y);
    printf( "ret = %dn", ret);
}

int main()
{
    int input = 1;
    do
    {
        menu();
        printf( "请选择:" );
        scanf( "%d", &input);
        switch (input)
        {
            case 1:
                calc(Add);
                break;
            case 2:
                calc(Sub);
                break;
            case 3:
                calc(Mul);
                break;
            case 4:
                calc(Div);
                break;
            case 0:
                printf("退出程序n");
                break;
            default:
                printf( "选择错误n" );
                break;
        }
    } while (input);

    return 0;
}

复习:冒泡排序的实现

#include 

void bubble_sort(int arr[], int sz)
{
    int i,j;
    //冒泡排序的趟数:有10个元素,就要排序9趟,剩下最后一个元素不用再于别的元素比较。趟数=元素个数-1
    for(i=0 ; i arr[j+1])
            {
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
}

int main()
{
    //升序
    int arr[10] = {9,8,7,6,5,4,3,2,1,0};
    int sz = sizeof(arr)/sizeof(arr[0]);
    bubble_sort(arr,sz);
    int i;
    for(i=0 ; i  

qsort排序函数的使用

#include 
#include 
#include 

void print(int arr[],int sz)
{
    int i;
    for(i=0 ; ip2;如果小于,返回的是一个小于0的数,就表示p1name,(s+i)->age);
    }
}

int cmp_age(const void* p1,const void* p2)
{
    return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

int cmp_name(const void* p1,const void* p2)
{
    
    return strcmp(((struct Stu*)p1)->name,((struct Stu*)p2)->name);
}

void qsort_stu()
{
    //使用qsort函数为结构体数据排序
    struct Stu s[] = {{"zhangsan",30},{"lisi",34},{"wangwu",20}};
    int sz = sizeof(s)/sizeof(s[0]);

    printf("排序前:n");
    print_stu(s,sz);
    //按照年龄排序
    //qsort(s,sz, sizeof(s[0]),cmp_age);
    //按照名字排序
    qsort(s,sz,sizeof(s[0]),cmp_name);

    printf("排序后:n");
    print_stu(s,sz);
}

int main()
{
    //整型数据的排序
    //qsort_int();

    //结构体数据的排序
    qsort_stu();
}

模拟qsort实现一个冒泡排序算法

#include 
#include 

Swap(char* buf1,char* buf2,int size)
{
    int i;
    for(i=0 ; i0)
            {
                //交换
                //交换的是两个指针指向的内容。但是我们只是知道地址,而不知道其是什么类型的数据。
                //解决:不管其是什么类型的数据,我们把他们的每个字节的内容都进行交换,这样也相当于交换了内容。
                Swap((char*)base+j*size,(char*)base+(j+1)*size,size);
            }
        }
    }
}

int cmp_int(const void* p1,const void* p2)
{
    //因为p1与p2都是void* 无类型指针。没有办法比较。
    //而我们知道传入的数据是int类型的,所以我们可以将其先强制类型转换为int*类型的指针(int*)p1、(int*)p2
    //然后再解引用,就可以进行比较了。*(int*)p1 - *(int*)p2
    //如果p1大于p2,就会将这个值返回,返回的是一个大于0的数,就表示p1>p2;如果小于,返回的是一个小于0的数,就表示p1name,(s+i)->age);
    }
}

int cmp_age(const void* p1,const void* p2)
{
    return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

int cmp_name(const void* p1,const void* p2)
{
    
    return strcmp(((struct Stu*)p1)->name,((struct Stu*)p2)->name);
}

void qsort_stu()
{
    //使用qsort函数为结构体数据排序
    struct Stu s[] = {{"zhangsan",30},{"lisi",34},{"wangwu",20}};
    int sz = sizeof(s)/sizeof(s[0]);

    printf("排序前:n");
    print_stu(s,sz);
    //按照年龄排序
    //bubble_sort(s,sz, sizeof(s[0]),cmp_age);
    //按照名字排序
    bubble_sort(s,sz,sizeof(s[0]),cmp_name);

    printf("排序后:n");
    print_stu(s,sz);
}

int main()
{
    //test();
    qsort_stu();
    return 0;
}

void *类型

#include 

int main()
{
    int a = 10;
    char ch = 'w';
    //void为无具体类型,void*就是无具体类型指针。其指针变量中,什么类型的变量地址都可以存储。
    void* p = &a;
    p = &ch;
    //但是在引用的时候不能直接引用,因为void*是无具体类型的,所以解引用或进行指针运算,编译器不知道访问几个字节。
    /
#include 

int main()
{
    int a[] = {1,2,3,4};

    //sizeof(数组名),计算整个数组的大小。int类型数组中有4个元素。4*4=16
    printf("%dn",sizeof(a));//16

    //a+0,a中存储数组首元素地址,首元素地址+0:代表的还是首元素地址。sizeof(a+0)计算地址的大小
    //在32位平台下,地址大小是4个字节;在64位平台下,地址是8个字节。
    printf("%dn",sizeof(a+0));//8

    //数组名a中存储的是数组首元素的地址,解引用找到的是数组首元素:1。1是int类型数据,所以应该是4
    printf("%dn",sizeof(*a));//4

    //a+1,a中存储数组首元素地址,首元素地址+1:代表的数组中第二个元素的地址。sizeof(a+1)计算地址的大小
    printf("%dn",sizeof(a+1));//4/8

    //计算数组中第二个元素的大小。
    printf("%dn",sizeof(a[1]));


    //&a,取出整个数组地址。sizeof(地址) 4/8
    printf("%dn",sizeof(&a));//8

    //&a,取出整个数组地址。解引用找到数组。也就是计算整个数组大小
    printf("%dn",sizeof(*&a));//16

    //&a,取出整个数组地址。数组地址+1,跳过整个数组之后的一块地址。还是一个地址,所以这里是计算地址的大小。4/8
    printf("%dn",sizeof(&a+1));//8

    //a[0]是数组首元素,&a[0]取出数组首元素地址。是一个地址,4/8
    printf("%dn",sizeof(&a[0]));//8

    //a[0]是数组首元素,&a[0]取出数组首元素地址,&a[0]+1,数组首元素地址+1,就是数组第二个元素地址。是一个地址,4/8
    printf("%dn",sizeof(&a[0]+1));//8

    return 0;
}

字符数组(不存放字符串结束符),sizeof以及strlen的计算

#include 
#include 

int main()
{
    char arr[] = {'a','b','c','d','e','f'};

    

    //计算字符串长度,strlen计算字符串长度时,直到遇见字符串结束符''才结束
    //arr是首元素地址,会一直往后取。直到碰到才结束。所以这里是个随机值
    printf("n%dn",strlen(arr));//随机值
    //首元素地址+0,还是首元素地址。然后往后取,直到碰到才结束。与以上相同,是个随机值。
    printf("%dn",strlen(arr+0));//随机值

    //strlen函数的原型:size_t __cdecl strlen(const char *_Str);
    //其参数是一个指针,也就是说参数应该是一个指针,或者直接传地址过去。

    //&arr,取出的是整个数组地址,该地址是int (*)[6]类型。然后放入strlen函数,被强制类型转换为char*类型。
    //也会从数组首元素开始取,直到碰到字符串结束符结束
    printf("%dn",strlen(&arr));//随机值
    //&arr+1,紧接着数组地址后的一块地址。该地址也是int (*)[6]类型。然后放入strlen函数,被强制类型转换为char*类型。
    //会从数组后第一个元素开始取,直到碰到字符串结束符结束。也就是说要比以上随机值少6个字符。
    printf("%dn",strlen(&arr+1));//随机值-6
    //arr[0]是数组首元素,&arr[0]取出数组首元素地址,&arr[0]+1,数组首元素地址+1,就是数组第二个元素地址。
    //从数组第二个元素取直到取到字符串结束符,少了数组首元素。所以应该是随机值-1
    printf("%dn",strlen(&arr[0]+1));//随机值-1

    /

    //注意:字符串长度,不计算最后的字符串结束符
    //计算字符串长度,strlen计算字符串长度时,直到遇见字符串结束符''才结束
    //arr是首元素地址,会一直往后取。直到碰到才结束。这里是6
    printf("n%dn",strlen(arr));//6
    //首元素地址+0,还是首元素地址。然后往后取,直到碰到才结束。与以上相同,是6
    printf("%dn",strlen(arr+0));//6

    //strlen函数的原型:size_t __cdecl strlen(const char *_Str);
    //其参数是一个指针,也就是说参数应该是一个指针,或者直接传地址过去。
    //&arr,取出的是整个数组地址,该地址是int (*)[6]类型。然后放入strlen函数,被强制类型转换为char*类型。
    //也会从数组首元素开始取,直到碰到字符串结束符结束
    printf("%dn",strlen(&arr));//6
    //&arr+1,紧接着数组地址后的一块地址。该地址也是int (*)[6]类型。然后放入strlen函数,被强制类型转换为char*类型。
    //会从数组后第一个元素开始取,直到碰到字符串结束符结束。也就是说是个随机值
    printf("%dn",strlen(&arr+1));//随机值
    //arr[0]是数组首元素,&arr[0]取出数组首元素地址,&arr[0]+1,数组首元素地址+1,就是数组第二个元素地址。
    //从数组第二个元素取直到取到字符串结束符,少了数组首元素。所以应该是6-1=5
    printf("%dn",strlen(&arr[0]+1));//5

    /

    //strlen函数的原型:size_t __cdecl strlen(const char *_Str);
    // 其参数是一个指针,也就是说参数应该是一个指针,或者直接传地址过去。

    //p是一个指针,指向a。一直取到字符串结束,是6
    printf("%dn",strlen(p));//6
    //p是指向a的char类型指针,p+1,跳过1个字节,就是指向b。从b开始取到字符串结束,6-1=5
    printf("%dn",strlen(p+1));//5

    //&p,取出的是p的地址。&p是一个char**类型,放入strlen函数,被强制转换为char*类型。
    //&p是一个地址,占8个字节。每个字节都被当作一个字符。直到取到(或者是十六进制的00)才会结束,其后面不知道什么时候才能取到字符串结束符,所以这里是一个随机值。
    printf("&p:%dn",strlen(&p));//随机值
    //&p,取出的是p的地址。&p+1,是&p后面紧接着的那个地址。其后面不知道什么时候才能取到字符串结束符,所以这里是一个随机值
    printf("&p+1:%dn",strlen(&p+1));//随机值

    //这两个地址都是随机值,有没有什么联系呢? //可能有联系、可能没有联系
    //没有联系的情况:
    //p变量的地址(&p):0x00 00 7f f7 60 31 a0 10
    //因为内存中采用小端存储形式,也就是低位低地址。所以&p存储到内存中是:10 a0 31 60 f7 7f 00 00。
    //本来使用指针来取,则是倒着取出来。但是传入strlen函数,被强制转换为char*类型
    // 每次取出一个字节,10,a0,31,60,f7,7f,然后遇到字符串结束符。00也是字符串结束符,所以这里是6。
    //紧接着10 a0 31 60 f7 7f 00 00后的8个字节就是&p+1的中存储的内容,从开头开始取,直到取到字符串结束符。不管什么时候取到字符串结束符,也与&p的长度没有关系
    //此时&p与&p+1就没有联系

    //有联系的情况:
    //p变量的地址(&p):0x11 22 7f f7 60 31 a0 10
    //因为内存中采用小端存储形式,也就是低位低地址。所以&p存储到内存中是:10 a0 31 60 f7 7f 22 11。
    //本来使用指针来取,则是倒着取出来。但是传入strlen函数,被强制转换为char*类型
    //从开头开始取,每次取出一个字节,10,a0,31,60,f7,7f,22,11,没有遇到字符串结束符。
    //紧接着10 a0 31 60 f7 7f 22 11后的8个字节就是&p+1的中存储的内容,继续取,直到取到字符串结束符。
    //不管什么时候遇到结束符,此时生成的随机值关系:&p的随机值减去8就是&p+1的随机值。
    //因为是在64位平台下,所以是减去8。如果是32平台下,那么地址的长度是4个字节,就是减去4。


    //p[0]找到a,&p[0]取出a的地址,&p[0]+1,也就是b所在的地址,然后取到字符串结尾。应该是6-1=5
    printf("%dn",strlen(&p[0]+1));//5

    /


杨氏矩阵

#include 
void find_num(int arr[3][3],int a,int b,int num)
{
    int x = 0;
    int y = b-1;//把num与每一行的最后一列上的数进行比较
    //只要行数x<行数,就说明还没到最后一行;并且y≥0,说明还没到第一列。就可以继续寻找
    while(x= 0)
    {
        //如果num比这一行最后一个数都大, 说明比这一行所有的数都大。
        if(arr[x][y] < num)
        {
            x++; //x+1,与下一行比较
        }
        else if(arr[x][y] > num)
        {//bum比这一行最后一个数大,说明num在这个数的左边。
            y--;//与倒数第二个、第三个...比较
        }
        else
        {
            //运行到这里,说明找到了,此时这个数与arr[x][y]相等
            //输出下标
            printf("这个数字所在下标是:%d %dn",x,y);
            //找到之后结束方法
            return;
        }
    }
    //如果循环结束都没有找到,说明矩阵中没有这个数,返回0。
    printf("没有这个数n");
}
int main()
{
    int arr[3][3] = {1,2,3,4,5,6,7,8,9};
    //查找一个数字,比如说找7
    int k = 7;
    find_num(arr,3,3,k);


//    //遍历数组查找——时间复杂度=o(N),不能使用这种方法
//    int i,j;
//    for(i=0 ; i<3 ; i++)
//    {
//        for(j=0 ; j<3 ; j++)
//        {
//            if(arr[i][j] == 7){}
//        }
//    }
    return 0;
}

找到之后,如何在main中就可以打印出找到的数字的下标?

#include 
int find_num(int arr[3][3],int* px,int* py,int num)
{
    int x = 0;
    int y = *py-1;//把num与每一行的最后一列上的数进行比较
    //只要行数x<行数,就说明还没到最后一行;并且y≥0,说明还没到第一列。就可以继续寻找
    while(x<*px && y>= 0)
    {
        //如果num比这一行最后一个数都大, 说明比这一行所有的数都大。
        if(arr[x][y] < num)
        {
            x++; //x+1,与下一行比较
        }
        else if(arr[x][y] > num)
        {//bum比这一行最后一个数大,说明num在这个数的左边。
            y--;//与倒数第二个、第三个...比较
        }
        else
        {
            //找到后将x与y,将其值保存到指针指向的变量,并且返回1
            *px = x;
            *py = y;
            return 1;
        }
    }
    return 0;
}
int main()
{
    int arr[3][3] = {1,2,3,4,5,6,7,8,9};
    //查找一个数字,比如说找7
    int k = 7;

    //如何获取到坐标呢?
    //传入指针进去,这样操作的就是同一数了
    int x = 3;
    int y = 3;

    int ret = find_num(arr,&x,&y,k);
    if(ret == 1)
    {
        printf("找到了n下标是:%d,%d",x,y);
    }
    else
    {
        printf("没这个数n");
    }

    return 0;
}

声明一个指向函数指针数组的指针

  

字符串左旋

#include 
#include 

void left_rotate(char* str,int k)
{
    int i,j;
    //求字符串长度,也就是传入的数组中有多少个字符
    int n = strlen(str);
    //要左旋几个字符,就循环几次
    for(i=0 ; i 

自己想出来的(改变了首元素指针指向,不推荐使用)

#include 
#include 

void left_rotate(char* str,int k)
{
    int i,j;
    //求字符串长度,也就是传入的数组中有多少个字符
    int n = strlen(str);
    //要左旋几个字符,就循环几次。
    for(i=0 ; i
#include 
#include 

reverse(char* left,char* right)
{
    //断言:left和right不为空指针。如果他们不是空,则为非0;如果为NULL,则是0,assert(0)就会不会往下运行,并给出错误信息。
    assert(left);
    assert(right);
    while(leftn)
    {
        k -= n;//如果k大于字符串长度,就减去n,直到k  

判断某个字符串是否由另一个字符串旋转而来

#include 
#include 

int is_rotate(char* str1,char* str2)
{
    int i,j;
    //求字符串长度,也就是传入的数组中有多少个字符
    int n = strlen(str1);
    //有多少个字符,就左旋多少次,每旋转一次判断一下是否相等。
    for(i=0 ; i 

另一种方法






#include 
#include 

int is_rotate(char* str1,char* str2)
{
    //如果两个字符串长度不相等,则直接返回0
    if(strlen(str1) != strlen(str2))
    {
        return 0;
    }
    //1、str1字符串的后面追加一个str1
    //AABCD变为AABCDAABCD
    strcat(str1,str1);
    //判断str2是否是str1中的字符串。如果是,则返回首次出现的指针,如果不是,则返回NULL。所以我们直接返回
    return strstr(str1,str2);

}

int main()
{
    //将arr1开辟的空间变大一点
    char arr1[20] = "AABCD";
    char arr2[] = "CDAAB";
    int ret = is_rotate(arr1,arr2);
    if(ret == 0)
    {
        printf("不是旋转而来");
    }
    else
    {
        printf("是旋转而来");
    }
    return 0;
}

test.c中包括如下语句

//文件定义的四个变量,哪个不是指针类型? 变量b不是

//定义宏,使用的时候,INT_PTR 会被int*替换掉
#define INT_PTR int*
//typedef是将int*类型,重命名为int_ptr了
typedef int* int_ptr;
//INT_PTR 会被int*替换掉 就成为:int * a,b;
//注意这里的*表示a是指针变量,所以*给了a,而b没有*,所以a是int*指针类型,而b是int类型
//所以定义指针变量的时候,不能使用连续声明。如果要连续声明,则需要int *a,*b;这样a和b就都是int*指针类型了。
INT_PTR a,b;

//typedef是将int*类型,重命名为int_ptr了
//所以这里c与d都是int_ptr类型,也就是int*指针类型。
int_ptr c,d;
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号