C语言基础(八)字符串

字符串

我们将字符串保存在char类型的字符数组中,如果char类型的字符数组以空字符\0结尾,则该数组就构成了字符串。

因为字符串需要以\0结尾,所以在定义的时候字符数组的长度要预留一个字节来存放空字符,例如:
char str[21]; //存放20个英文字符或10个汉字。
字符串要使用双引号包围起来,不能使用单引号,例如:“zunnajim”,“ABC”;

1.占用内存的情况

一个字符占用一个字节的内存,字符串定义时数组的大小决定了字符串占用的内存大小。
char str1[21]; //占用21个字节

2.字符串的初始化

1.在定义的时候初始化(后面的代码中不可以使用)
char str[20]=“zunnajim”;

2.将首字符置零
char str[20];
sr[0]=0;

3.memset 函数
char str[20];
memset(str,o,sizeof(str)); // 设置为空字符

4.strcpy函数
char str[20];
strcpy(str,“zunnajim”); //将制定的字符赋值给str

3.字符串的输出

字符串的输出控制符是%s,可以加以格式:
%ms:输出m个字符宽度,右对齐
%-ms:输出m个字符宽度,左对齐
如果字符串长度大于m,则按实际的字符长度输出

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

int main()
{
   char str[10]="zunnajim";
   printf("%20s\n",str);
   printf("%-20s\n",str);
   printf("%5s\n",str);
}

运行结果:

      zunnajim 

zunnajim
zunnajim

4.字符串越界

字符串本质上是一个字符数组,所以也可以用下标来访问其中的单个字符。所以字符串也存在数组下标越界问题。

示例1:

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

int main()
{
   char str[10]="zunnajim";
   int i;
   for(i=0;i<10;i++)
   {
       printf("%c  ",str[i]);
	}
	strcpy(str,"zunnajim mamitimin");
	printf("\n");
	printf("%s",str);

运行结果:

z u n a j i m
zunnajim mamitimin
示例2:

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


int main()
{
    char str_array[2][10];
    memset(str_array,0,sizeof(str_array));


    strcpy(str_array[1],"我是一名中华人民共和国公民!");
    strcpy(str_array[2],"武汉理工大学是一所大学!");
    

    printf("str_array[1]=%s\n",str_array[1]);
    printf("str_array[2]=%s\n",str_array[2]);
}


运行结果:

str_array[1]=我是一�武汉理工大学是一所大学!
str_array[2]=武汉理工大学是一所大学!
Segmentation fault (core dumped)

可以看出该程序报了一个段错误,在此处就是因为数组越界问题,给长度为10个bits的字符串赋值一个实际长度大于10bits的字符串时,就会出现错误。

这是因为strcpy函数再给字符串赋值的时候,源字符串(“zunnajim mamitimin”)长度如果大于目标字符串(str)的长度,其次目标字符串后面的内存是空的,就会将这一片内存划分给目标字符串(str)。如果目标字符串后面的内存已经被使用,那么就会出现Segmentation fault。就像示例2。

5.常用函数

1.获取字符串的长度(strlen)

size_t  strlen(const char* str);	
/*计算字符串长度,不包含\0,返回字符串的字符数,遇到第一个\0停止。如果字符串没有被初始化,那么会从字符串首地址开始查找\0,他的结果是不定的*/

sizeof()函数返回的是字符串在内存所占用的空间,并不是字符串所含有的字符串个数。
示例:

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


int main()
{
    char str1[10];
    memset(str1,0,sizeof(str1));
    char str2[10]="zunnajim";
    char str3[20]="zunnajim mamitimin";


    printf("size(str1)=%d\n",strlen(str1));
    printf("size(str2)=%d\n",strlen(str2));
    printf("size(str3)=%d\n",strlen(str3));


    printf("sizeof(str1)=%d\n",sizeof(str1));
    printf("sizeof(str2)=%d\n",sizeof(str2));
    printf("sizeof(str3)=%d\n",sizeof(str3));
}

运行结果:

size(str1)=0
size(str2)=8
size(str3)=18
sizeof(str1)=10
sizeof(str2)=10
sizeof(str3)=20

2.字符串赋值或复制(strcpy)

char *strcpy(char* dest,const char* src);
/*功能:将参数src字符串拷贝至参数dest所指的地址
返回值:返回参数dest的字符串起始地址
注意:如果dest所指的内存不够大,可能造成溢出缓冲区的情况(越界)*/

3.字符串赋值或复制(strncpy)

char* strncpy(char* dest,const char* src,const size_t n);
/*
功能:把src前n个字符的内容复制到dest中
返回值:dest的起始地址
注意:如果src字符长度小于n,则拷贝完字符串之后,在dest后面追加0,直到n个
	  如果src字符长度大于n,就截取src的前n个字符,不会再dest后面追加0.
	  dest的长度必须大于n,否则可能会造成缓冲区溢出。

4.字符串拼接(strcat)

char* strcat(char* dest,char* src);
/*
功能:将 src字符串拼接到dest尾部
返回值:dest的起始地址
dest最后原有的结尾字符\0会被覆盖,并在连接后的字符串的尾部再增加一个\0。
dest要有足够大的空间,否则可能会造成缓冲区溢出。

5.字符串拼接(strncat)



/*
功能:将 src字符串前n个字符拼接到dest尾部
返回值:dest的起始地址
dest最后原有的结尾字符\0会被覆盖,并在连接后的字符串的尾部再增加一个\0。
dest要有足够大的空间,否则可能会造成缓冲区溢出。

6.字符串比较(strcmp,strncmp)

int strcmp(const char* str1,const char *str2);	
/*功能:比较str1和str2的大小
返回值:str1>str2  	返回大于0的数
		str1=str2	返回0
		str1<str2	返回小于0的数
		*/
int strncmp(const char* str1,const char *str2,size_t n);	
/*功能:比较str1和str2前n个字符的大小
返回值:str1>str2  	返回大于0 的数
		str1=str2	返回0
		str1<str2	返回小于0的数。
两个字符比较的是ASCII码的大小。

7.字符查找(strchr、strrchr)

char* strchr(const char* s,int c);		//返回字符串s中第一个c的地址,找不到返回0
char* strrchr(const char* s,int c);		//返回字符串s中c最后出现的地址,找不到返回0

8.字符串查找(strstr)

char *strstr(const char* str,const char *str);		//检索子串在字符串中首次出现的位置,返回字符串中第一次出现子串substr的地址,如果没有则返回0.

示例:

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


int main()
{
 /* 	char* strcpy(char* dest,const char* src);
 *  	char* strncpy(char* dest,const char* src,size_t n);
 *      char* strcat(char* dest,char* src);
 *      char* strncat(char* dest,char* src,size_t n);
 *      int strcmp(const char* str1,const char *str2);	
 *      int strncmp(const char* str1,const char *str2,size_t n);
 *      char* strchr(const char* s,int c);		
 *      char* strrchr(const char* s,int c);
 *      char *strstr(const char* str,const char *str);
 */

    char str1[10]="zunnajim";
    strcpy(str1,"zunnajim");
    printf("strcpy=%s\n",str1);

    char str2[5];
    strncpy(str2,str1,5);
    printf("strncpy=%s\n",str2);

    char str3[20]="zunnajim";
    strcat(str3,str1);
    printf("strcat=%s\n",str3);

    printf("strcmp=%d\n",strcmp(str1,str2));
    printf("strncmp=%d\n",strncmp(str1,str2,5));

    printf("strchr(n)=%p\n",strchr(str1,'n'));
    printf("strrch(n)=%p\n",strrchr(str1,'n'));

    printf("strstr(unn)=%s\n",strstr(str1,"unn"));
}

运行结果:

strcpy=zunnajim
strncpy=zunna
strcat=zunnajimzunnajim
strcmp=-21
strncmp=0
strchr(n)=0x7ffe12d6e9e2
strrch(n)=0x7ffe12d6e9e3
strstr(unn)=unnajim

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑暗守护者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值