c语言 指针进阶 字符串数组指针6,C语言进阶 ~ 一级指针与字符串

目录数组

2.1 指针强化

强化1:指针是一种数据类型

1)指针变量也是一种变量,占有内存空间,用来保存内存地址测试指针变量占有内存空间大小。

2)保证所指的内存块能修改

3)指针是一种数据类型,是指它指向的内存空间的数据类型 。

4 ) 不容许向NULL和未知非法地址拷贝内存。

char *p3 = NULL;

//给p3指向的内存区域拷贝内存

strcpy(p3, "1111"); //err

char *p3 = 0x0001;

//给p3指向的内存区域拷贝内存

strcpy(p3, "1111"); //err

强化2:间接赋值(*p)是指针存在的最大意义

强化3:理解指针必须和内存四区概念相结合

强化4:应用指针必须和函数调用相结合(指针作函数参数)

值得一看:

用1级指针形参,去间接修改了0级指针(实参)的值。

用2级指针形参,去间接修改了1级指针(实参)的值。

用3级指针形参,去间接修改了2级指针(实参)的值。

用n级指针形参,去间接修改了n-1级指针(实参)的值。

#include

void fun(char **p , int *len)

{

if (p == NULL)

{

return;

}

char *tmp = (char *)malloc(100);

if (tmp == NULL)

{

return;

}

strcpy(tmp, "adlsgjldsk");

//间接赋值

*p = tmp;

*len = strlen(tmp);

}

int main(void)

{

char *p1 = NULL;

int len1 = 0;

fun(&p1, &len1);

if (p1 != NULL)

{

printf("p1 = %s, len1 = %d\n", p1, len1);

}

printf("\n");

system("pause");

return 0;

}

1db76ae9cc8eff251b577e7a0f7d6b1a.png

① 程序运行至 char *tmp = (char *)malloc(100);

05e898ab15471da46988646d65975c2e.png

6e71aba0748dad35a39115efd194e276.png

② 程序运行至 strcpy(tmp, "adlsgjldsk");

c02cabf8e668aec710c994c12222d8a9.png

6e91b8fcb578f52cf514a770d4864a60.png

③ 程序运行至 *p = tmp;

bb8f1aad2eb3b8a031fba5568fa4fb93.png

④ 程序运行至 *len = strlen(tmp);

2ba4b7f080c6c73c844c955d313dd011.png

2.2 一级指针(char*)易错地方

2.2.1 对空字符串和非法字符串的判断

void copy_str(char *from, char *to)

{

if (*from == '\0' || *to == '\0')  //正确的为if (from == '\0' || to == '\0')地址是否为空

{

printf("func copy_str() err\n");

return;

}

for (; *from!='\0'; from++, to++)

{

*to = *from;

}

*to = '\0';

}

2.2.2 越界

char buf[3] = "abc";

2.2.3 指针的叠加会不断改变指针的方向

char *getKeyByValue(char **keyvaluebuf, char *keybuf)

{

int i = 0;

char *a = (char *)malloc(50);

for (; **keyvaluebuf != '\0'; i++)

{

*a++ = *(*keyvaluebuf)++;

}

free(a);

}

2.2.4 局部变量不要外传

char *my_stract(char *x, char* y)

{

char str[80];

char *z=str;           /*指针z指向数组str*/

while(*z++=*x++);

z--;                    /*去掉串尾结束标志*/

while(*z++=*y++);

z=str;                 /*将str地址赋给指针变量z*/

return(z);

}

2.2.5 函数内使用辅助变量的重要性

int getSubCount(char *str, char *substr, int *mycount)

{

int ret = 0;

char *p = str;

char *sub = substr;

if (str==NULL || substr==NULL || mycount == NULL)

{

ret = -1;

return ret;

}

............

2.3 字符串

c语言没有字符串类型,经过字符数组模拟

c语言字符串,以字符‘\0’或数字0

2.3.1 字符串初始化

①  strlen:测字符串长度,不包含数字0,字符'\0'

sizeof:测数组长度,包含数字0,字符'\0'

char buf9[100] = "agjdslgjlsdjg";

printf("strlen = %d, sizeof = %d\n", strlen(buf9), sizeof(buf9));

9e42a3360be8f499dd5e7d5ecc9a6226.png

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

/*

C语言没有字符串类型,经过字符数组模拟

C语言字符串,以字符‘\0’, 数字0

*/

int main(void)

{

//不指定长度, 没有0结束符,有多少个元素就有多长

char buf[] = { 'a', 'b', 'c' };

printf("buf = %s\n", buf);

//指定长度,后面没有赋值的元素,自动补0

char buf2[100] = { 'a', 'b', 'c' };

printf("buf2 = %s\n", buf2);

//全部元素赋值为0

char buf3[100] = { 0 };

//

//char buf4[2] = { '1', '2', '3' }; //数组越界

char buf5[50] = { '1', 'a', 'b', '0', '7' };

printf("buf5 = %s\n", buf5);

char buf6[50] = { '1', 'a', 'b', 0, '7' };

printf("buf6 = %s\n", buf6);

char buf7[50] = { '1', 'a', 'b', '\0', '7' };

printf("buf7 = %s\n", buf7);

//

//使用字符串初始化,经常使用

char buf8[] = "agjdslgjlsdjg";

//

//strlen: 测字符串长度,不包含数字0,字符'\0'

//sizeof:测数组长度,包含数字0,字符'\0'

printf("strlen = %d, sizeof = %d\n", strlen(buf8), sizeof(buf8));

//

char buf9[100] = "agjdslgjlsdjg";

printf("strlen = %d, sizeof = %d\n", strlen(buf9), sizeof(buf9));

/

printf("\n");

system("pause");

return 0;

}

93c648731ce48a93602b55b42d4e18d1.png

2.3.2 数组法和指针法操做字符串

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

int main(void)

{

char buf[] = "algjdlksajgldksjg";

int i = 0;

int n = strlen(buf);

char *p = NULL;

//[]方式

for (i = 0; i < n; i++)

{

printf("%c", buf[i]);

}

printf("\n");

//指针方法

//数组名字,数组首元素地址

p = buf;

//

for (i = 0; i < n; i++)

{

printf("%c", p[i]);

}

printf("\n");

//

for (i = 0; i < n; i++)

{

printf("%c", *(p+i) );

}

printf("\n");

//

for (i = 0; i < n; i++)

{

printf("%c", *(buf+i) );

}

printf("\n");

//

//buf和p彻底等价吗?

//p++; 正常

//buf++; 此处出错

//buf 只是一个常量,不能修改

//

printf("\n");

system("pause");

return 0;

}

2.3.3 字符串拷贝函数 strcpy

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

//成功为0,失败非0

//一、判断形参指针是否为NULL

//二、最好不要直接使用形参

int my_strcpy(char *dst, char *src)

{

if (dst == NULL || src == NULL)

{

return -1;

}

//辅助变量把形参接过来

char *to = dst;

char *from = src;

//*to = *from

//to++, from++

//判断 *to是否为0, 为0跳出循环

while (*to++ = *from++)

{

NULL;

}

printf("my_strcpy: dst = %s\n", dst);

return 0;

}

int main(void)

{

char src[] = "abcedfdgds";

char dst[100] = { 0 };

int ret = 0;

ret = my_strcpy(dst, src);

if (ret != 0)

{

printf("my_strcpy err:%d\n", ret);

return ret;

}

printf("%s\n", dst);

printf("\n");

system("pause");

return 0;

}

剖析片断程序

while (*to++ = *from++)

{

NULL;

}

① *to = *from

② to++, from++

③ 判断 *to是否为0, 为0跳出循环

2.4 const

2.4.1 冒牌的 “const”

const旨在用户层面不能修改,而通常在机器修改时候都是用的是地址进行改数。

const int b = 10;

//b = 100; //err

int *q = &b;

*q = 22;

printf("%d, %d\n", b, *q);

90719dfaff1a41c53f6abfb6e99c70e7.png

2.4.2 const 与 指针

指针变量, 指针指向的内存, 2个不一样概念

char buf[] = "aklgjdlsgjlkds";

从左往右看,跳过类型,看修饰哪一个字符

const char *p = buf;

// 等价于上面 char const *p1 = buf;

若是是*, 说明指针指向的内存不能改变

const char *p = buf;

// 等价于上面 char const *p1 = buf;

//p[1] = '2'; //err

p = "agdlsjaglkdsajgl"; //ok

若是是指针变量,说明指针的指向不能改变,指针的值不能修改

char * const p2 = buf;

p2[1] = '3';

//p2 = "salkjgldsjaglk"; //err

若是是指针变量和*, 指向不能变,指向的内存也不能变

//p3为只读,指向不能变,指向的内存也不能变

const char * const p3 = buf;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值