c语言字符串67ASDSff,C语言.字符串,及string.h初步应用

一、字符

字符是用单引号 ’ ’ 括起来的单个普通字符或转义字符。

例:char c='A'; char c='\n';

二、字符串

在 C 语言中,字符串实际上是使用 null 字符 ‘\0’ 终止的“一维字符数组”(本质!)。

三、字符数组

下面的声明和初始化创建了一个 “Hello” 字符串。

例子: char A[10];

//字符数组的赋值方法,三种

赋值: char A[10] = {'h','e','l','l','o'}; --> 后面没有赋值的成员的值都是0

char A[10] = {"hello"};-->等价于{'h','e','l','l','o','\0'} (本质)

char A[10] = "hello";

注意:

1)整型不需要使用任何符号,字符使用单引号’’,字符串使用""。

2)重点:字符数组初始化后不能整体赋值!

四、字符指针

整型指针 --> 指向内容: int

二级指针 --> 指向内容: 指针

数组指针 --> 指向内容: 数组

函数指针 --> 指向内容: 函数

字符指针 --> 指向内容: char

例子:

char a = ‘h’;

char *p = &a; --> p就是字符指针 --> 指向某个字符

char *p = "hello"; --> 不是把整个字符串拷贝到指针变量,指针变量永远只能存放指针/地址

五、char*p="hello"和char p[]="hello"的区别

首先“hello”在程序开启的时候放在了内存的.rodata段,是一个常量区,是一个only-read只读区域。

char *p=“hello”是将’h’的地址赋给指针p,即p指向了常量区‘h’的地址。

char p[]="hello"是将常量区中的"hello"拷贝到数组p[]中。

其在内存中的情况如下:

29eddee1dc35072b1b8c9ed7f0dd7e85.png

例:

//例如,我们试图将字符串的'h'改为'k',其结果如上图

char *p="hello";*p=‘k’;//错误,p指向常量区.rodata 'h'的地址,常量区的内容只读,无法修改;

char p[]="hello";*p=‘k’;//正确,p[]在堆栈开辟连续内存并把"hello"从常量区复制过来;

注意:

1) p: 存放"hello"字符串首元素’h’的地址,

2) p是指向一个字符,不是指向一个字符串

3) 字符串在常量区存储时,以’\0’作为结束标志

细节补充1:

char *p="hello";

char *q="hello";

p和q的地址是一样的,编译器在处理的时候会把相同的字符串优化。

细节补充2:

“如果有空间”系统会在字符串后补‘\0’

反言之就是如果空间不够,系统就不能补了;

用strlen()测试下面字符串长度:

char cc[5]="hello"; //结果:19(不确定) //空间不足补\0 {'h','e','l','l','o'}

char cc[10]="hello"; //结果:5 //空间足够补\0 {‘h’,'e','l','l','o','\0','\0','\0','\0','\0'};

char cc[]="hello"; //结果:5 //自适应 {‘h’,'e','l','l','o','\0'}

//strlen()测字符串长度是到'\0'截止,第一张情况由于系统不能补'\0',则测的时候会

一直寻找下去直到找到'\0'(null,0),所以其结果不定。

到后面使用strcpy()同理,一定要注意开辟足够的内存空间

例如存放"hello"应预留‘\0的位置’ char cc[6];

总结:

char A[10] = “hello”; --> 把常量区的字符串"hello"直接拷贝到栈空间A变量中(如果数组是局部变量)

char *p = “hello” --> 把常量区的字符串"hello"的首元素的地址存储在指针变量p中

六、strlen()

原型:

*size_t strlen(const char *s);

功能: 给一个字符串的起始地址s,不断往后计算,直到遇到\0为止就停止计算!

返回值:s指向的字符串对应的字符个数*

问题①:

//strlen()的用法以及和sizeof()的区别

char B[] = "helloworld";

char A[100] = "helloworld";

char *p = "helloworld";

printf("sizeof(A) = %d\n",sizeof(B));//11

printf("sizeof(A) = %d\n",sizeof(A));//100

printf("sizeof(p) = %d\n",sizeof(p));//4

printf("strlen(A) = %d\n",strlen(B));//10

printf("strlen(A) = %d\n",strlen(A));//10

printf("strlen(p) = %d\n",strlen(p));//10

//由char B[]可知'\0'也占一个空间,但是测字符串的时候不会算进去。

//由char A[100]可知,后面全补0,一样会占内存空间,但不会算在字符串长度上。

//sizeof(p)测的是'h'的地址,相当于sizeof(char *),任何指针都是占4个字节(32 位系统机器位长)

问题②:

int main()

{

char a[7]="a0\0a0\0";

char b[7]="a0\0asds";

char c[7]="a0\aasds";

char d[7]="a0\aaa\0";

printf("%d \n",strlen(a)); //2

printf("%d \n",strlen(b)); //2

printf("%d \n",strlen(c)); //12

printf("%d \n",strlen(d)); //5

}

//'\0'结束 结果2

//‘\0’结束 结果2

//'\a'转义字符,算一个字符 总共7个字符 c[7]没空间补'\0' 其结果为12(不确定)

//‘\a’转义字符 ,‘\0’结束,一共5个字符 结果5

补充-关于转义字符:

226e6cda2b95ebd8c5b925b4378f2575.png

总结:

1)strlen()传首地址进来,返回长度;

2)strlen()直到‘\0’结束,要考虑是否有‘\0’(空间是否够补);

3)转义字符算一个字符;

七、strcmp()

int strcmp(const char *s1, const char *s2);

int strncmp(const char *s1, const char *s2, size_t n);

功能:

比较两个字符串是否一致;

参数:

s1与s2都是需要进行对比的字符串的首元素地址

n: 只匹配前n个字节

返回值:

s1与s2匹配: 0

s1与s2不匹配: 非0 (实际可能负数或正数,但一般用不到,知道非0就行)

//Demo

char A[100] = "helloworld";

char *p = "hello";

//if(A == p)//错误

if(strncmp(A,p,5) == 0) //正确

{

printf("ok!\n");

}

注意:

1 )strcmp也是基于strlen的基础上,所以若果不够空间存’\0’也会导致越界对比,导致字符串不匹配;

八、strcpy()

原型:

char *strcpy(char *dest, const char *src);

char *strncpy(char *dest, const char *src, size_t n);

功能:

拷贝字符串到某段内存中

参数:

dest: 需要把字符串拷贝到的空间的起始地址,空间必须足够大

src: 需要拷贝的字符串起始地址

n: 需要的前n个字节 ,需要src指向的内容总长度

返回值:

指向dest这个区域的指针

char a[]="hello";

char b[]="ab";

strcpy(a,b);

//执行后a里面是:{'a','b','\0','l','o','\0'}

printf("%s",a);

//打印 ab

//printf("%c",a+3)

//打印 l

注意:

1)保证被拷贝的空间足够,否则会导致越界

2)strcpy会把’\0’也拷贝过去

3)n指定可以实现追加字符串功能

经验:

① 常用于字符数组初始化后赋值:

char A[100];

A[100] = “gec123456” ; //错误

strcpy(A,“gec123456”);//正确

②malloc()申请堆空间,要用strcpy把字符串赋值过去。

九、strcat()

功能:追加字符串

十、关于数组清零的几种常用方式

1.定义数组时初始化0

char s[50]={0}; – 初始化时,小于开辟的长度,后面自动补0

2.清空某段内存空间 – bzero() –

#include void bzero(void *s, size_t n);

s: 需要清零的内存空间首地址

n:需要清零的字节数

没有返回值

char str[50]; bzero(str,50);

3.内存初始化 --memset()–

#include 或#include void *memset(void *s, int ch, size_t n);

函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。

功能:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 。

char str[50];memset(str,0,sizeof(str));

十一、开发经验

以上几个函数在开发中会使用到的场景:

1)write()/send() – 确定某些数据的总字节数 – strlen()

2)strcmp() – 检索数据的正确与否 /登录密码,检索某个特征值

3)strcpy() – 给某些字符数组赋值(数组初始化后不能整体赋值)

char A[100];

A[100] = “gec123456” ; //错误

strcpy(A,“gec123456”);//正确

4)strcat() – 拼接字符串,仅限于追加功能 – 后期使用sprintf()代替strcat()

更多:https://www.cnblogs.com/intelwisd/p/8299738.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值