从零学编程- C语言-第16天

今天是学习C语言的第16天

时间:2024/9/29 21:25分

使用编译器:vs2019

此贴记录自己的成长

今天学习内容如下

1.strlen及模拟

//strlen 模拟实现
//size_t strlen(const char * str)
int my_strlen(char arr[])
{
	int i = 0;
	while (arr[i])
	{
		i++;
	}
	return i;
}
int my_strlen(char* p)
{
	int i = 0;
	while (*p)
	{
		p++;
		i++;
	}
	return i;
}
int my_strlen(char* p)
{
	char* q = p;
	while (*p++);
	p--;
	return p - q;
}
int my_strlen(char *p)
{
	if (*p)
	{
		p++;
		return my_strlen(p) + 1;
	}
	else
	{
		return 0;
	}
}
int main()
{
	char arr[] = "abcd";
	printf("%d", my_strlen(arr));
	return 0;
}

2.strcpy及模拟

//strcpy
//char * strcpy(char *dest,const char *source)
1.必须\0
2.目标有足够空间放进去
3.目标空间是变量,不是常量
模拟实现
#include <assert.h>
char* my_strcpy(char* dest, const char* sour)
{
	assert(*sour);
	char* p = dest;
	while (*sour)
	{
		*dest = *sour;
		dest++;
		sour++;
	}
	*dest = *sour;
	return p;
}
int main()
{
	char name[20] = { 0 };
	//name = "zhangsan" 不可以,name是数组名是地址,地址是一个常量值,不能被赋值
	//strcpy(name, "zhangsan");
	//strcpy是找\0以前的复制进去, \0以后的不管
	//strcpy(name, 'a', 'b', 'c');这种不行,必须放一个\0进去,找的就是\0
	my_strcpy(name, "zhangsan");
	printf("%s", name);
	return 0;
}

3.strcat及模拟

//strcat 字符串追加
 1.目标空间足够追加进去
 2.目标空间可变,不是常量
 3.有\0
 4.不能自己追加自己,死循环,因为地址相同
模拟实现
#include<assert.h>
char* my_strcat(char* dest, const char* sour)
{
	assert(sour != NULL);
	char* p = dest;
	while (*p++); p--;
	while (*p++ = *sour++);
 	return dest;
}
int main()
{
	char name[20] = { "zhangsan" };
	my_strcat(name, "lisi");
	printf("%s", name);
	printf("\n%s", my_strcat(name,"haha"));
	return 0;
}

4.strcmp及模拟

//strcmp 字符串比较
// 模拟实现
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1&& *str2)
	{
		if (*str1 == *str2)
		{
			str1++;
			str2++;
		}
		else
		{
			return *str1 - *str2;
		}
	}
	return *str1 - *str2;
}
int main()
{
	char str1[20] = "abcdaa";
	char str2[20] = "abcdaaa";
	int cmp = my_strcmp(str1, str2);
	printf("%d", cmp);
	return 0;
}

5.长度限制函数

使用strcpy时, 如果dest空间不够, 还是能复制进去, 只是会有警告, 直接越界访问了
可以在第一行写上#define _CRT scanf那个东西, 就可以不越界访问, 直接编译拦截了
所以这些函数有些安全隐患, 会越界可能
所以c语言又提供了长度受限的字符串函数 strncpy strncmp strncat
这些函数相对安全

6.strncpy,strncat,strncmp

//strncpy
strcpy(dest, source);  strncpy(dest source, 5) 多了一个参数, 只拷贝前5个进去, 最后如果没字符自动补\0, 有字符还是原字符, 第6个还是dest字符串的第6个字符 不是\0
strncpy("abcdef", "hellolll", 5);   abcdef-- > hellof
如果sour只能3位, 而你参数写了5位, 那么后两位默认\0拷贝进去

//strncat
strncat(det, source, 5); 末尾自动补\0 如果dest里面有\0, source从\0开始追加, 后面直接覆盖了 参数多写也没用, 还是追加5个

//strncmp
strncmp(str1, str2, 5);

7.strstr查找函数

//strstr查找函数
//模拟实现
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	if (str2 == '\0')
	{
		return str2;
	}
	const char* str11 = NULL;
	const char* str22 = NULL;
	while (*str1)
	{
		str11 = str1;
		str22 = str2;
		while (*str11 == *str22&&*str11!='\0&&*str22!='\0)
		{
			str11++;
			str22++;
		}
		if (*str22 == '\0')
		{
			return str1;
		}
		str1++;
	}
	return NULL;
}
int main()
{
	char str1[] = "htttp//www.baidu.com";
	char str2[] = "www";
	if (my_strstr(str1, str2) == NULL)
	{
		printf("查找失败");
	}
	else
	{
		printf("%s", my_strstr(str1, str2));
	}
	return 0;
}
还有一种kmp算法,也是用来字符串查找的,效率比这个高,但是难度高


//自己写的模拟代码测试用的
#include  <string.h>
int my_strstr(const char* str1, const char* str2)
{
	int len = 0;
	char* str22 = str2;
	while (*str22) { str22++; len++; }
	while (*str1)
	{
		char* str11 = str1;
		str22 = str2;
		int count = 0;
		for (int i = 0; i < len; i++)
		{
			if (*str11 == *str22) { count++; }
			str11++;
			str22++;
		}
		if (count == len) return 1;
		str1++;
	}
	return 0;
}

8.strtok 切割字符串函数

//strtok 切割字符串
http//www.baidu.com
char* strtok(char* str, const char* sep) 第二个参数是分割符, @. / 类似的符号
zhangsan@lisi  会将@变成\0 然后返回z的地址
由于会改变字符串内容, 所以建议提前拷贝一份

9.strerror 返回错误信息函数

//strerror
//返回错误码
//c语言的库函数,在执行失败时都会自动设置错误码
头文件#include <errno.h>
char* (int errnum) errnum: 0, 1, 2, 3, 4,5等等
printf("%s", strerror(0));
printf("%s", strerror(1));
等等
FILE* pf = fopen("test.txt", "r");
printf("%s"strerror(errno)); 错误码是全局变量,errno

10.字符分类函数及其大小写转换

//字符分类函数
iscntrl  isspace isdigit islower isupper isalpha isalnum ispunct isgraph isprint
符合条件就为真
int tolower(int c) 字符转换大小写

11.memcpy跟memmove 内存拷贝函数

memcpy memmove
strcpy只能字符串, memcpy可以其他类型数组
void* memcpy(void* dest, const void* source, size_t num) num表示拷贝几个字节
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 0 };
memcpy(arr2, arr1, 20);  5个数 20个字节
memcpy不能用于处理重叠的数组或内存之间拷贝的, 例如不能memcpy(arr1, arr1, 20);
使用memmove可以

memmove
跟memcpy相同

12.memcmp 内存比较函数

//memcmp
内存比较
memcpy是一个字节一个字节比较, 不是一整个数比较
01 00 00 00 02 00 00 00
01 00 00 00 03 00 00 00   02 < 03

13.memset 内存设置函数

//memset 内存设置
	char arr[] = "hello,bit";
     memset(arr, 'x', 5);
	 然后arr里面全变x了 xxxxx, bit
	 memset(arr + 6, 'x', 3);
	 然后 hello, xxx
		不适合给整型数组初始化,因为单位是1个字节,不是4个字节
		 int arr[10] = {0};
	 memset(arr,1,40) 40个字节  但是这样的话每个字节都变01了,不是数是1

14. 输入一个数字,数字的每一位如果偶数变0,奇数变1

int main()
{
	int a = 222222;
	int sum = 0;
	while (a)
	{
		int i = a % 10;
		if (i % 2 == 0)
		{
			i = 0;
		}
		else
		{
			i = 1;
		}
		a = a / 10;
	  sum = sum * 10 + i;
	}
	printf("%d", sum);
	return 0;
}

15.4个凶手a说不是我, b说是cc,  说是d,  d说c胡说, 

       3个真话,1个假话,求凶手 

int main()
{
	int killer = 'a';
	for (; killer <= 'd'; killer++)
	{
		if ((killer != 'a') + (killer == 'c') + (killer == 'd') +( killer != 'd')==3)
		{ 
			printf("%c", killer);
		}
	}
}

16.字符串ABCD 左旋一个字符得到BCDA 左旋两个字符得到CDAB

void fun(char* arr,int num)
{
	if (num > strlen(arr))
	{
		printf("错误");
	}
	else
	{
		int i = 0;
		int tmp;
		for (int i = 1; i <= num; i++)
		{
			int k = 0;
			while (k < strlen(arr) - i)
			{
				tmp = arr[k];
				arr[k] = arr[k + 1];
				arr[k + 1] = tmp;
				k++;
			}
		}
	}
}
int main()
{
	char arr[] = "ABCD";
	int num = 2;
	fun(arr, num);
	printf("%s", arr);
	return 0;
}

C语言学习日志

时间:2024/9/29 21:25分

目标:一个月学完c语言

每天更新,不断更 

倒计时:14天

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值