C语言---万能指针(void *)、查找子串(strncmp函数的应用)多维数组(一维数组指针、二维数组指针)、返回指针值函数、关键字(const)

一、字符串与指针

用字符指针指向一个字符串,可以不定义字符数组,而定义字符指针。用字符指针指向字符串中的字符。不能使用指针去改变不能修改的空间。

***eg1.***运用指针将 src 的内容拷贝到 dest 中去

cs 复制代码
void Strcpy(char *dest, char *src)
{
    while(*src != '\0')
    {
        *dest = *src;
        ++dest;
        ++src;
    }
    *dest = '\0';
}

eg2. 运用指针将 src 的内容剪切到 dest 后面

cs 复制代码
void Strcat(char *dest, const char *src)
{
    while(*dest)
    {
        *dest = *dest;
        ++dest;
    }
    while(*src)
    {
        *dest = *src;
        ++dest;
        ++src;
    }
    *dest = '\0';
}

***eg3.***运用指针比较 s1 与 s2 的大小

cs 复制代码
int Strcmp(const char *s1, const char *s2)
{
   while(*s1 == *s2 && *s1 != '\0' && *s2 != '\0') 
    {
        ++s1;
        ++s2;
    }
    return *s1 - *s2; 
}

eg4. 运用指针将 src 的前 n 个字符拷贝到 dest 中去

cs 复制代码
//将src的前n个字符拷给dest中去
void Strncpy(char *dest, const char *src,int n)
{
    while(*src != '\0' && n-- != 0 )
    {
        *dest = *src;
        ++dest;
        ++src;
    }
    //*dest = '\0';
}

***eg5.***运用指针将 src 前 n 个字符连接到 dest 的后面去

cs 复制代码
void Strncat(char *dest, const char *src, int n)
{
    while(*dest)
    {
        ++dest;
    }
    while(*src && n--)
    {
        *dest++ = *src++;
    }
    *dest = 0;
}

eg6. 运用指针只比较 s1 与 s2 的前 n 个字节的大小(可用于查找子串)

cs 复制代码
int Strncmp(const char *s1, const char *s2, int n)
{
    while(--n && *s1 == *s2 && *s1 && *s2)// --n
    {
        ++s1;
        ++s2;
    }
    return *s1 - *s2;
}

上述函数在主函数中的运行格式:

cs 复制代码
int main(void)
{
    char s1[100] = "Hello ";
    char s2[100] = "Herld!";
    Strcpy(s2, s1);
    Strcat(s1,s2);//Strcat(s1, "World");
    Strncpy(s1, s2, 2);
    Strncat(s1, s2, 2);
    //puts(s1);
    int t = Strncmp(s1, s2, 2);
    printf("%d\n", t);
    return 0;
}

二、万能指针(空指针)

万能指针可以用来接收任何数据类型的指针,当多个函数的运行程序段一致,但函数形参类型不一致时,可用万能指针结合强制类型转换符进行合并。

例如,只将 src 空指针型数组中的前 n 个数据拷贝到 dest 空指针型数组中去(适用于任何数据类型的拷贝)

cs 复制代码
//万能指针
void Memcpy(void *dest, const void *src, int n)
{
    char *q = (char *)dest;
    char *p = (char *)src;
    while(n--)
    {
        *q++ = *p++;
    }
}
int main(void)
{
    short a[10] = {1,2,3,4,5,6,7,8,9,0};
    short b[10];
    int len = sizeof(a) / sizeof(*a);
    Memcpy(b, a, sizeof(a));
    int i;
    for(i = 0; i < len; ++i)
    {
        printf("%d\n", b[i]);
    }
    return 0;
}

三、查找子串

运用 Strncmp 函数查找 sub 在 s 中首次出现的位置

cs 复制代码
int subString(const char *s, const char *sub)
{
    int i;
    //printf("%d\n",strlen(s));
    for(i = 0; i <= strlen(s) - strlen(sub); ++i)
    {
            if(strncmp(s + i, sub, strlen(sub)) == 0)
            {
                break;
            }        
    }
    if(i > strlen(s) - strlen(sub))
    {
        return 0;
    }
    else
    {
        return i;
    }
}
int main(void)
{
    char *sub = "hand";
    char *s = "He is handsome";
    int ret = subString(s, sub);
    if(ret != 0)
    {
    printf("found\n");
    printf("在s[%d]\n", subString(s, sub));
    }
    else
    {
        printf("not found\n");
    }
    return 0;
}

四、一维数组指针

一维数组指针也称为指向一维数组元素的指针,本质是一个指针变量。

一般形式:数据类型 (*标识符)[一维数组长度]

例如:int (*p)[10]:长度为10的一维整型数组,对指针 p 加 n 表示: 偏移 n*sizeof(基类型) 个字节。

五、二维数组指针

1、概念

二维数组指针也称为指向二维数组的指针或数组指针,其作为函数参数传递的媒介,形参是指向一维数组的指针,是一种特殊的指针类型,用于指向二维数组的整体或其行、元素,实现灵活的数组访问和传递。

(1) 指向二维数组的行(以下皆用 p 当作二维数组 a[][4] 的指针)

int (*p)[4]=a <=等价于=> a[0]

(2) 指向二位数组的 i 行 j 列

*(*( a+ i) + j) <=等价于=> a[i][j]

例如:*(*(a + 1) + 1) <=表示=> 二维数组中 a[1][1] 的值

2、二维数组指针的输出

cs 复制代码
void printArray2D(int (*a)[4], int rows)
{
    int i, j;
    int cols = sizeof(*a) / sizeof(**a);
    for(i = 0; i < rows; ++i)
    {
        for(j = 0; j < cols; ++j)
        {
            printf("%2d ", *(*(a+i)+j));
        }
        puts("");
    }
}

3、二维数组指针的求和

cs 复制代码
int sumArray2D(int (*a)[4], int rows)
{
    int i, j;
    int sum = 0;
    int cols = sizeof(*a) / sizeof(**a);
    for(i = 0; i < rows; ++i)
    {
        for(j = 0; j < cols; ++j)
        {
            sum += *(*(a + i) + j);
        }
    }
    return sum;
}

4、二维数组指针的水平镜像

cs 复制代码
//a与b的交换
void swap(int *a, int *b)
{
    int t;
    t = *a;
    *a = *b;
    *b = t;
}
//一维数组的逆序
void reverse(int *begin, int *end)
{
    while(begin < end)
    {
        swap(begin++, end--);
    }
}
//二维数组的水平镜像
void reverse2D(int (*a)[4], int rows)
{
    int i, j;
    int cols = sizeof(*a) / sizeof(**a);
    for(i = 0; i < rows; ++i)
    {
            reverse(*(a + i), *(a + i) + (cols -1));
        
    }
}

上述函数在主函数中的使用格式:

cs 复制代码
int main(void)
{
    int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    int rows = sizeof(a) / sizeof(*a);
    int t = sumArray2D(a, rows);
    printArray2D(a, rows);
    //printf("%d\n", t);
    reverse2D(a, rows);
    printArray2D(a, rows);
    return 0;
}

可以运用强制类型转换符改变指针输出类型,例如:

printf("%d\n", *( (int *)(p + 3) - 5) ),对于三行四列的二维数组a[3][4],该输出指向 a[1][3] 中的值。

六、返回指针值的函数

一般定义形式:类型名 *函数名(参数列表)

返回指针值的函数称为指针函数。一个函数可以返回一个整型值、字符值、实型值等,也可以返回指针型的数据,即地址。可应用到多种函数的创建中去,例如字符型数组的拷贝(eg1. )、字符型数组的剪切(eg2.)。

***eg1.***将 src 字符串的内容拷贝到 dest 字符串中去,要求函数须有返回值,并在输出时直接打印出结果

cs 复制代码
char *Strcpy(char *dest, const char *src)
{
    char *ret = dest;
    while(*src)
    {
        *dest++ = *src++;
    }
    *dest = '\0';
    return ret;
}

eg2. 将 src 字符串的内容粘贴到 dest 字符串的后面,要求函数须有返回值,并且输出时直接打印出结果

cs 复制代码
char *Strcat(char *dest, const char *src)
{
    char *ret = dest;
    while(*dest)
    {
        ++dest;
    }
    while(*src)
    {
        *dest = *src;
        ++dest;
        ++src;
    }
    return ret;
}

以上函数在主函数中的运行的书写格式

该类函数不能返回局部变量的值,例如:

|------------------------------|
| static int i; |
| return &i; |
| *foo(&i) = 100; // * 为取地址 |

需要在变量 i 前加上 static ,让其存储与静态区(全局区)。

七、关键字 const

在指针前加 const 表示无法通过该指针去修改它所指向的变量,但指针本身可以指向其他地址。可以提高代码可读性和函数的传参效率。常用于不能修改的字符指针前。例如:

cs 复制代码
int a = 10;
int b = 20;
const int *p = &a;

若执行" *p = 20 ",会编译错误,不能通过 p 修改所指向的值;

若执行" p = &b ",可以执行,指针 p 可以指向其他地址。

相关推荐
今天也好累8 分钟前
C 语言基础第16天:指针补充
java·c语言·数据结构·笔记·学习·算法
_君落羽_41 分钟前
C语言 —— 指针(4)
c语言·开发语言
望星空听星语1 小时前
C语言自定义数据类型详解(四)——联合体
c语言·开发语言
细嗅蔷薇@5 小时前
C语言在键盘上输入一个3行3列矩阵的各个元素的值(值为整数),然后输出主对角线元素的积,并在fun()函数中输出。
c语言·算法·矩阵
吻等离子5 小时前
Linux ARM 平台 C 语言操作 Excel 文件的常用库与工具汇总(支持 xls 和 xlsx)
linux·c语言·arm开发
mftang5 小时前
C 标准库 <time.h> 函数详解
c语言·开发语言
菜还不练就废了7 小时前
7.25 C/C++蓝桥杯 |排序算法【下】
c语言·c++·排序算法
程序员编程指南8 小时前
Qt 移动应用性能优化策略
c语言·开发语言·c++·qt·性能优化
程序员编程指南10 小时前
Qt 移动应用常见问题与解决方案
c语言·开发语言·c++·qt
野原鑫之祝14 小时前
嵌入式开发学习———Linux环境下数据结构学习(五)
linux·c语言·数据结构·学习·vim·排序算法·嵌入式