【C语言学习记录】字符串

一、初识

二、字符串的结束标志’ \0 ’

字符串的结尾标志是0,如果没有结尾标志的情况我们在数组章节中已介绍过,现在我们介绍结尾标志后面的内容如何处理。

char strname[21];
memset(strname,0,sizeof(strname));
strcpy(strname,"abcdefghijk");     // 把abcdefghijk赋值给strname
strname[5]=0;     // 强制把第6个元素赋值0
printf("%s",strname);   // 输出的结果是abcde

以上代码输出的结果是abcde,但是,在内存中的值仍是abcde0ghijk,后面的ghijk成了内存中的垃圾值。

不要让字符串的内存中有垃圾值,容易产生意外的后果,我们将在后面的内容中演示,所以字符串的初始化不建议采用把第一个元素的值置为0的方式(strname[0]=0)。

三、sizeof和strlen的区别

四、动态开辟字符串

1、malloc

动态开辟内存空间;后记得释放所分配的内存空间;让指针指向NULL,防止悬挂指针;

2、realloc

扩容 函数原型void *realloc(void *ptr, size_t size)

3、free

释放,防止空间泄露,free之后让指针指向NULL,防止悬挂指针

4、memset

  • 内存空间初始化

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
malloc:动态开辟内存空间;后记得释放所分配的内存空间;让指针指向NULL,防止悬挂指针
strcpy:拷贝   char *strcpy(char* dest, const char *src);//从src拷贝到dest去
realloc:扩容  void *realloc(void *ptr, size_t size);
memset:     memset(p,'\0',12);   //内存空间初始化
*/

int main()
{   
    char *p;//野指针
	p = (char *)malloc(1);//p有了具体的内存指向

    *p = 'c';
    printf("%c\n",*p);

	free(p);//动态开辟后重新指向,记得释放所分配的内存空间。不然存在内存泄露的风险
	p = NULL; //free之后让指针指向NULL,防止悬挂指针

	p = (char *)malloc(12); //开辟12字节的内存空间
    if(p == NULL){          //通常养成习惯对malloc返回值做NULL判断,申请失败了
		printf("malloc error\n");
		exit(-1);
	}
	memset(p,'\0',12);   //内存空间初始化

    printf("扩容地址:%x\n",p);
    int len =strlen("DT1213_STC8A8K64D4");
    int newLen = len - 12 + 1;
    p = realloc(p,newLen);         //扩容
    printf("扩容后地址:%x\n",p);
    strcpy(p,"DT1213_STC8A8K64D4");//空间不够 越界  realloc扩容函数
	puts(p);

    puts("end");

    return 0;
}

五、几种字符串常用的API

1、strcpy、strncpy 拷贝

  • strcpy:拷贝 char strcpy(char dest, const char *src);//从src拷贝到dest去
  • strncpy:拷贝 复制字符串的前n个字符

2、assert 断言

assert:断言 assert 的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行

. 自己实现strcpy函数

char* myStrcpy(char*dest, char *src)
{
	//assert(dest != NULL && src != NULL);//断言
    if(dest == NULL || src == NULL){
		return NULL;
	}
    char *bak = dest;   //char备份地址bak保存目标地址dest

    while( *src != '\0'){
        *dest++ = *src++;
        /*
        *dest = *src;
		dest++;
		src++;
        */
	}
	*dest = '\0';

	return bak;
}
char* myStrcpy2(char *des, char *src)
{
    //assert(des != NULL && src != NULL);//断言
	if(des == NULL || src == NULL){
		return NULL;
	}
	char *bak = des;
	
	while( (*des++ = *src++) != '\0');
	*des = '\0';
	
	return bak;
}
  • 自己实现strncpy函数
char* myStrncpy(char *des, char *src, int count)
{
	if(des == NULL || src == NULL){
		return NULL;
	}
	char *bak = des;
	
	while( *src != '\0' && count>0){
		*des++ = *src++;
		count--;
	}
	if(count > 0){
		while(count > 0){
			count--;
			*des++ = '\0';
		}
		return des;
	}
	*des = '\0';
	
	return bak;
}

3、strcat 拼接

函数原型:char strcat(char dest, const char src)
把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除dest原来末尾的“\0”)。要保证dest足够长,以容纳被复制进来的src。*src中原有的字符不变。返回指向dest的指针。

  • 自己实现strcat函数
char* myStrcat(char *des, char *src)
{
	assert( des!=NULL && src!=NULL);//断言

	char *bak = des;
	
	while(*des != '\0'){      //while(*des)
		des++;
	}
	while((*des++ = *src++) != '\0');
	*des = '\0';
	
	return bak;
}

char* myStrcat2(char *des, char *src)//指针偏移
{
	char *bak = des;
	strcpy(des + strlen(des), src);
	return bak;
}

char* myStrcat3(char *des, char *src)
{
	assert( des!=NULL && src!=NULL);
	char *bak = des;
	
	for( ; *des!='\0'; des++);
	while((*des++ = *src++) != '\0');
	*des = '\0';
	
	return bak;
}

int main()
{
    char str[128] = "DT1213_";
	char *p = "STC8";
    char *p2;

	//strcat(str,p);
    //puts(str);

    p2 = myStrcat(str,p);
	//p2 = myStrcat2(str,p);
	//p2 = myStrcat3(str,p);
	puts(p2);

    return 0;
}

4、strcmp 比较

函数原型:int strcmp(const char *s1,const char *s2);
若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数
自己实现strcmp函数

计算字符ASCII值总和

int myStrcmp(char *str1, char *str2)
{
	int ret = 0;
	int n_str1 = 0;  //计算ASCII值总和
	int n_str2 = 0;
	char *bakStr1 = str1;
	char *bakStr2 = str2;

	while( *str1 && *str2 && (*str1 == *str2)){
		str1++;
		str2++;
	}
	// if(*str1 || *str2){
	// 	str1 = bakStr1;//指针回归,做运算
	// 	str2 = bakStr2;
		while(*str1){
				n_str1 += *str1; //计算ASCII值总和
				str1++;
		}
		while(*str2){
				n_str2 += *str2;
				str2++;
		}
	//}
	ret = n_str1 - n_str2;
	if(ret < 0){
		ret = -1;
	}
	if(ret > 0){
		ret = 1;
	}
	return ret;
}

int main()
{
    char *p1 = "DTAB";
	char *p2 = "DTBA";

	int ret = strcmp(p1,p2);//-1  1  0     //返回-1
	if(ret == 0){
		puts("两个字符串相同");
	}
	printf("ret = %d\n",ret);

    ret = myStrcmp(p1,p2);//-1  1  0       //返回0
	if(ret == 0){
		puts("两个字符串相同");
	}
	printf("ret = %d\n",ret);

    return 0;
}
posted @ 2023-02-24 16:49  zggb  阅读(93)  评论(0)    收藏  举报