C--六、字符串

C–六、字符串

什么是字符串呢?

简单来说,就是字符数组,不过在声明上也有区别。可以借助整形数组来理解。

int intArr[] = {1,2,3,4};//-->1
char charArr2[] = {'a','b','c','d'};//-->2
char charArr1[5] = {'a','b','c','d'};//-->3
char charArr3[] = "abcd";//-->4
//也可以写作
char *charArr4 = "abcd";//-->5

上述几个数组的一些说明与区别:

  1. 只有字符串赋值的时候才会自动加’\0’
  2. 字符串和字符数组的区别:字符串的结束标志位 ‘\0’
  3. 2与3的区别:使用sizeof关键字计算出2的长度为4。sizeof关键字计算出3的长度为5。
  4. 4:此种声明方式,会默认其为字符串,在末尾加上字符 ‘\0’,使用sizeof关键字计算出其长度为5(c语言字符串数组初始化时剩余长度全部为’\0’)。
  5. 2,3,4与5:2,3,4是字符串变量可以更改,但5是字符串常量,不允许被更改。
  6. 指针操作注意:
    1. 其保存的是一个字符串常量的地址,可以通过修改地址来更改指针指向的值
    2. 不能对野指针的空间进行操作

demo:

#include <stdio.h>

int main()
{	
	
	int idata[] = {1,2,3,4,5};
	
	char cdata[] = {'h','e','l','l','o'};
	char cdata1[6] = {'h','e','l','l','o'};
	char cdata2[] = "hello";//此种声明方式,会默认其为字符串,在末尾加上字符 '\0'
	
	int size1 = sizeof(idata)/sizeof(idata[0]);
	int size = sizeof(cdata)/sizeof(cdata[0]);
	int size2 = sizeof(cdata1)/sizeof(cdata1[0]);
	int size3 = sizeof(cdata2)/sizeof(cdata2[0]);
	
	printf("idata     : %d\n",size1);
	printf("cdata     : %d\n",size);
	printf("cdata1    : %d\n",size2);
	printf("cdata2    : %d\n",size3);
	printf("cdata1[5] : %d\n",cdata1[5]);//-->'\0'
	
	//输出字符串的方式
	//在使用<string.h>中的函数,以下列方法输出字符串时
	//都是使用'\0'作为结束标志符,如果用字符数组的方式声明可能会出现问题
	printf("cdata2 : %s",cdata2);
	
	return 0;
}

result:
在这里插入图片描述

字符串中常见的错误

  1. 错误1:此种声明方式为字符串常量,不能修改:
	char *p = "hello;"
	*p = 'm';
  1. 错误2,野指针:
	char *p1;//p1没有明确为其分配内存空间,是野指针
	*p1 = 'a';//此处访问野指针空间出现segment fault

注意

  1. C语言中指针声明时会分配随机的地址,也就是野指针。
  2. 指针分配具体地址是在赋值以后,其他数据类型分配地址是在声明以后。

strlen与sizeof的区别

使用sizeof来计算的时候,得出的是其在计算机中所占字节数。
使用strlen(针对字符串的,在string.h中)计算的是有效字符的长度,不包括’\0’

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

void test(){
	int a;
};

int main()
{
	char *cdata1 = (char *)malloc(sizeof(char)*5);
	memset(cdata1,'\0',5);
	*cdata1 = 'h';
	
	char cdata[128] = "hello";
	void (*ptest)();
	ptest = test;
	char cdata2[] = "hello";
	
	//pest是函数指针,也就是地址,在window下是用8是字节存储一个地址
	printf("sizeof cdata   :%d\n",sizeof(cdata));
	printf("sizeof ptest   :%d\n",sizeof(ptest));
	printf("sizeof *ptest  :%d\n",sizeof(*ptest));
	printf("sizeof cdata2  :%d\n",sizeof(cdata2));
	printf("strlen cdata   :%d\n",strlen(cdata));
	
	printf("sizeof cdata1  :%d\n",sizeof(cdata1));
	printf("sizeof *cdata1 :%d\n",sizeof(*cdata1));
	printf("strlen cdata1  :%d\n",strlen(cdata1));

	free(cdata1);
	return 0;
}

result:
在这里插入图片描述

动态开辟字符串

  1. malloc,函数原型 void *malloc(size_t size),C库函数void *malloc(size_t size)分配所需的内存空间,并返回一个指向它的指针。
  2. realloc,函数原型 void *realloc(void *ptr,size_t size),扩容。C库函数void *realloc(void *ptr,size_t size)尝试重新调整之前调用malloc或calloc所分配的ptr所指向的内存块的大小。
  3. free,C库函数void free(void *ptr)释放之前调用calloc、malloc或realloc所分配的内存空间。
  4. memset,函数原型void *memset(void *str, int c, size_t n)。将指针变量 str 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。s 是 void 型的指针变量,所以它可以为任何类型的数据进行初始化。

free的目的

  1. 释放空间,防止内存泄漏
  2. 防止悬挂指针----->野指针的一种。

注意malloc申请的空间里是可能存在垃圾数据的,在使用之前要先用memset清空一下
demo:

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

int main()
{	
	//悬挂指针是野指针的一种
	char *p = NULL;
	p = (char *)malloc(1);
	*p = 'a';
	
	free(p);
	
	p = (char  *)malloc(12);
	memset(p,'\0',12);
	printf("p的地址       :%p\n",p);
	
	int len = strlen("helloLiQiaoQiao");
	int newLen = len - 12 + 1;
	
	realloc(p,newLen);
	printf("扩容后p的地址 :%p\n",p);

	strcpy(p,"helloLiQiaoQiao");
	puts(p);
	
	free(p);
	return 0;
}

result:
在这里插入图片描述

字符串常用的API

  1. 输出字符串:
    puts(),
    printf(“%s”,p)

  2. 获取字符串:
    scanf(“%s”,p),
    gets

  3. 计算长度:strlen

  4. 拷贝:
    全部或前n个字符
    char * strcpy(char* dest, const char *src);
    char * strncpy(char *dest, const char *src, int n)

  5. 断言:assert。断言一个表达式正确,如果错误就从strerr退出。

  6. 拼接:char *strcat(char *dest, const char *src);

  7. 比较:
    若str1 = str2,则返回零;若strl<str2,则返回负数;若strl>str2,则返回正数(全部或前n个字符)
    int strcmp(const char *s1,const char *s2);
    int strncmp ( const char * strl, const char * str2, size_t n)

  8. 查找子字符:
    char *strchr(const char *str, int c);

  9. 查找子串:
    char *strstr(char *strl, const char *str2);

  10. 字符串分割:
    char *strtok(char *str, const char *delim)

#include <string.h>
#include <stdio.h>
int main) {

	char str[80] ="This is - www.runoob.com - website";
	const char s[2] ="-";
	char *token;
	/*获取第一个子字符串*/
	token = strtok(str, s);
	
	/*继续获取其他的子字符串*/
	while( token !=NULL ){
		printf( "%s\n", token );
		token = strtok(NULL,s);
	}
	return 0;

注意

  1. gets可以无限读取,易发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值
  2. strtok分割处理后原字符串str 会变,原字符串的改动是切分符原位置均更改为’\0’
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值