天天看点

C语言学习笔记8

C语言学习笔记8

      • 字符串:以'\0'结尾的字符数组
      • strlen函数的仿写
      • strcpy(目标,源)
      • 部分复制:strncpy(目标,源,要复制多长)
      • 字符串拼接:strcat
      • 比较两个字符串:strcmp
      • 字符串整型互转

字符串:以’\0’结尾的字符数组

int main() 
{
	char str[5] = { 'a','b','c','d','\0' };//'\0'不会被输出
	//char str[5] = { 'a','b','c','d','0' };
	//'\0'不等于‘0’,在ASCII中‘\0’ == 0,'0' == 48
	//char str[5] = { 'a','b','c','d','e' };
	//没有以\0结尾,后面乱码
	//char str[5] = { 'a','b','c','d'};
	//数组中没有被定义的位置自动补为0,也就相当于‘\0’,因此可以输出abcd

	char str1[] = "abcde"; //在栈区定义一个字符数组,然后将字符常量区中的字符串拷贝到栈区的字符数组中
	//此时这个数组存放六个字符 分别是abcde和\0
	//所有以双引号出现的字符串,都存储在字符常量区
	//“abcde”代表a的地址,单拿出“xxx”代表该字符串在字符常量区存储空间首元素的地址

	char* str2 = "abcde";//该指针在字符常量区

	printf("%d\n", sizeof(str1));	
	printf("%d\n", sizeof(str2));
	//str1与str2大小不一样,1是字符串数组,长度由数组元素(字符串长度)决定,2是指针,指针大小由程序位数决定

	//修改的不同
	  str1[1] = 'B';
	//str2[1] = 'B';//该指针在字符常量区,常量,所以不可以修改
				  //str1可以修改的原因是,它的类型是栈区的字符数组中
	printf("%s\n", str);
	printf("%s\n", str1);

	printf("%d\n", strlen(str));//strlen是计算字符串长度的,不算\0
	printf("%d\n", sizeof(str));//sizeof是计算大小的,由于\0也占用空间,所以要算


	return 0;
}
           

strlen函数的仿写

int MYstrlen(char* str);

int main()
{
	char str[5] = { 'a','b','c','d','\0' };
	printf("%d\n", MYstrlen(str));
}

int MYstrlen(char* str) 
{
	int count = 0;
	
	//知道次数时用for,不知道次数的时候用while
	//while (str!='\0')
	//应该是字符串里面的内容和\0比较,而不是str(指针)去进行比较,地址不可能等于\0,所以需要间接引用

	while (*str!='\0')
	{
		count++;
		str++;
	}//遍历字符串的套路~
	
	//当*str='\0'时就不符合循环条件了,因此会跳出循环,不执行while中的语句块,所以count不会+1。
	//计算长度时,\0不包括在内,所以返回count即可。

	return count;
}
           

strcpy(目标,源)

返回值是目标的首地址,没有返回值则错误,返回空NULL

int main()
{
	char str1[10];
	char str2[] = "abcd";
	strcpy_s(str1, sizeof(str1), str2);
	printf("%s\n", str1);
	//复制字符串,strcpy不安全,需要用strcpy_s来替换
	//不安全是因为如果目标的空间比较小或者比较大,那么会栈溢出或者乱码
	//strcpy_s(目标,目标的大小,源)	
	//返回值是int,如果成功返回0,如果失败返回非0值,不同值表示不同的错误,需要查阅手册
	return 0;
}

//仿写syrcpy
char* MYsyrcpy(char* str1, char* str2);

int main()
{
	char str1[10];
	char str2[] = "abcd";

	printf("%s\n", MYsyrcpy(str1, str2));

	return 0;
}

char* MYsyrcpy(char* str1, char* str2) 
{
	char* pmark = str1;
	while (*str2 != '\0')
	{
		*str1 = *str2; 
		str1++;
		str2++;
	}
	//str2的\0还没有复制过去,所以str1还不是字符串,所以需要再赋值\0
	*str1 = '\0';
	//return str1;//错误的原因是str1在程序中进行了++,所以已经不是首元素的地址了,所以需要在最前面先记录首元素地址
	return pmark;
}
           

部分复制:strncpy(目标,源,要复制多长)

//注意,也不安全,需要更换为strncpy_s

int main()
{
	char str1[10];
	char str2[] = "abcd";

	//strncpy(str1, str2, 3);
	strncpy_s(str1, sizeof(str1), str2, 3);
	printf("%s\n", str1);

	return 0;
}
           

字符串拼接:strcat

char* MYstrcat(char* str1, char* str2);

int main()
{
	char str1[10] = "abc";
	char str2[] = "123";
	//char str1[10];
	//str1[0] = 'a';
	//str1[1] = 'b';
	//str1[2] = '\0';
	//str1[3] = 'c';//	\0后面的不会输出,如果多个\0识别的是第一个,\0不一定会放在最后面

	//strcat(str1, str2);
	//strcat_s(str1, sizeof(str1), str2);
	//MYstrcat(str1, str2);

	//strncat(str1,str2,2);
	//会直接复制,在程序结束回收内存的时候才报错,显示的是栈溢出,依然不安全,只要往内存里放东西就有可能放出界
	//_s这个函数在发现装不下时就不会复制,直接给你报错,显示的是str1太小的错误,方便找问题
	strncat_s(str1, sizeof(str1), str2, 2);
	printf("%s\n", str1);

	return 0;
}


//仿写strcat
char* MYstrcat(char* str1, char* str2)
{
	char* pMark = str1;
	while (*str1 != '\0') 
	{
		str1++;
	}
	while (*str2 != '\0') 
	{
		//*str1++ = *str2++;//*和++的优先级同级,结合性是从右往左,相当于*(str1++)= *(str2++)
		//str2++和++str2的区别,str2++是先赋值给前面,再++,++str2是++完再赋值给前面
		*str1 = *str2;
		str1++;
		str2++;
	}
	*str1 = '\0';//str2的'\0'没有复制进去,所以手动加了一个
	//本程序中不加这条也不会乱码的原因是str1是不完全初始化,识别到第一个\0开始拼接,结束后str1是abc123\0\0\0…

	return pMark;
}
           

比较两个字符串:strcmp

//返回值Int类型,参数char*

//返回值为0时,字符串1等于字符串2;为-1时,字符串1小于字符串2;为1时,字符串1大于字符串2

//按位比较而不是比较长度~

//strncmp	比较部分字符串(前几位)

int MYstrcmp2(char* str1, char* str2);
int MYstrcmp(char* str1,char* str2);

int main()
{
	printf("%d\n", MYstrcmp("ac", "abc"));
	printf("%d\n", MYstrcmp("ab", "abc"));
	printf("%d\n", MYstrcmp("abc", "abc"));
	printf("----------------------\n");
	printf("%d\n", strcmp("ac", "abc"));//第二位上,c的ASCII码比b大,因此输出1
	printf("%d\n", strcmp("ab", "abc"));
	printf("%d\n", strcmp("abc", "abc"));
	printf("----------------------\n");
	printf("%d\n", MYstrcmp2("ac", "abc"));//第二位上,c的ASCII码比b大,因此输出1
	printf("%d\n", MYstrcmp2("ab", "abc"));
	printf("%d\n", MYstrcmp2("abc", "abc"));
	printf("----------------------\n");
	printf("%d\n", strncmp("ab", "abc", 2));

	return 0;
}


//strcmp函数的仿写

int MYstrcmp(char* str1,char* str2)
{
	while (*str1!='\0' && *str2!='\0')//只要有一个到'\0'就跳出循环
	{
		if (*str1<*str2)
		{
			return -1;
		}
		else if (*str2<*str1)
		{
			return 1;
		}
		else
		{
			str1++;
			str2++;
		}
	}

		if (*str1 < *str2)
		{
			return -1;
		}
		else if (*str2 < *str1)
		{
			return 1;
		}
		else
		{
			return 0;
		}

}

int MYstrcmp2(char* str1, char* str2) 
{
	while (*str1!='\0'||*str2!='\0')//两个都到'\0'才跳出循环
	{
		if (*str1 < *str2)
		{
			return -1;
		}
		else if (*str2 < *str1)
		{
			return 1;
		}
		else
		{
			str1++;
			str2++;
		}
	}
	return 0;
}
           

字符串整型互转

//整型转字符串

//itoa(要转换的数字,地址,进制)//不安全

//_itoa_s(要转换的数字,填入字符串的地址,字符串大小,进制)

//字符串转整型
//atoi(字符串)	返回整形
int main()
{
	char str[10];
	_itoa_s(10, str, sizeof(str), 2);
	printf("%s\n", str);
	printf("--------------------------\n");

	printf("%d\n", atoi("1234"));
	printf("%d\n", atoi("-1234"));
	printf("%d\n", atoi("--1234"));//只能识别一个正负号
	printf("%d\n", atoi("12+34"));//遇到非数字后面就无法识别
	printf("%d\n", atoi("12.34"));//遇到非数字后面就无法识别
	printf("%d\n", atoi("12a34"));//遇到非数字后面就无法识别
	printf("%d\n", atoi("a1234"));//遇到非数字后面就无法识别
	printf("%d\n", atoi("    1234"));//开头空格不限个数能识别但不显示
	printf("%d\n", atoi("12 34"));//遇到非数字后面就无法识别

	return 0;
}
           

继续阅读