zl程序教程

您现在的位置是:首页 >  后端

当前栏目

初识C语言必备经典程序(2)

C语言经典程序 必备 初识
2023-06-13 09:18:27 时间

     接下来我们来看一下C语言的核心部分也是最难的部分指针+字符串+数组,我们依然以实战和代码为主,一些较难的知识点和代码不易理解的地方,我会以附属形式写在博客中,使文章上下形式更加完整连贯。 1.字符串查找字符串

#include<stdio.h>
char* my_strstr(char* src, char* dest)
{
	//遍历字符串指针
	char* fsrc = src;
	//记录每一次相同的字符串首地址
	char* rsrc = src;
	char* tdest = dest;
	while (*fsrc)
	{
		rsrc = fsrc;
		while (*fsrc == *tdest && *fsrc != '\0')
		{
			fsrc++;
			tdest++;
		}
		if (*tdest == '\0')
		{
			return rsrc;
		}
		//回滚
		tdest = dest;//目标字符串更新到起始位置
		fsrc = rsrc;
		fsrc++;
	}
	return NULL;
}
int main()
{
	char src[] = "hello world";
	char dest[] = "llo";
	char* p = my_strstr(src, dest);
	printf("%s\n", p);
	return 0;
}

2.字符串追加

(1)数组写法

#include<stdio.h>
void my_strcat(char* ch1, char* ch2)
{//strlen(ch1);
	int i = 0;
	while (ch1[i] != '\0')
	{
		i++;
	}	//printf("%d\n",i);
	//printf("%d\n",strlen(ch1));
	int j = 0;
	while (ch2[j] != '\0')
	{
		ch1[i + j] = ch2[j];
		j++;
	}
}
 int main()
 {
	 char ch1[100] = "hello";
	 char ch2[] = "world";
	 my_strcat(ch1, ch2);
	 printf("%s\n", ch1);
	 return 0;
 }

(2)指针+偏移量写法

#include<stdio.h>
void my_strcat(char* ch1, char* ch2)
{
	int i = 0;
	while (*(ch1 + i) != '\0')
	{
		i++;
	}
	int j = 0;
	while (*(ch2 + j) != '\0')
	{
		*(ch1 + i + j) = *(ch2 + j);
		j++;
	}
}
int main()
{
	char ch1[100] = "hello";
	char ch2[] = "world";
	my_strcat(ch1, ch2);
	printf("%s\n", ch1);
	return 0;
}

(3)指针作为自动项写法

#include<stdio.h>
void my_strcat(char* ch1, char* ch2)
{
	while (*ch1)ch1++;
	while (*ch2)
	{
		*ch1 = *ch2;
		ch1++;
		ch2++;
	}
}
int main()
{
	char ch1[100] = "hello";
	char ch2[] = "world";
	my_strcat(ch1, ch2);
	printf("%s\n", ch1);
	return 0;
}

(4)纯指针写法

#include<stdio.h>
void my_strcat(char* ch1, char* ch2)
{
	while (*ch1)ch1++;
	while (*ch1++ = *ch2++);
}
int main()
{
	char ch1[100] = "hello";
	char ch2[] = "world";
	my_strcat(ch1, ch2);
	printf("%s\n", ch1);
	return 0;
}

3.字符串拷贝

(1)数组样式

#include<stdio.h>
void my_strcpy(char* dest, char* ch)
{
	int i = 0;
	while (ch[i] != '\0')
	{
		dest[i] = ch[i];
		i++;
	}
	dest[i] = 0;
}
int main()
{
	//字符串拷贝
	char ch[] = "hello world";
	char dest[100];
	my_strcpy(dest, ch);
	printf("%s\n", dest);
	return 0;
}

(2)指针+偏移量

#include<stdio.h>
void my_strcpy(char* dest, char* ch)
{
	int i = 0;
	while (*(ch + i))
	{
		*(dest + i) = *(ch + i);
		i++;
	}
	*(dest + i) = 0;
}
int main()
{
	char ch[] = "hello world";
	char dest[100];
	my_strcpy(dest, ch);
	printf("%s\n", dest);
	return 0;
}

(3)指针写法

#include<stdio.h>
void my_strcpy(char* dest, char* ch)
{
	while (*ch)
	{
		*dest = *ch;
		dest++;
		ch++;
		//指针+1相当于指向数组下一个元素,内存地址变化了sizeof(char)
	}
	*dest = 0;
}
int main()
{
	char ch[] = "hello world";
	char dest[100];
	my_strcpy(dest, ch);
	printf("%s\n", dest);
	return 0;
}

(4)高阶指针写法

#include<stdio.h>
void my_strcpy(char* dest, char* ch)
{
	//1.*ch *dest取值 2.*dest = *ch 3.ch++,dest++
	while (*dest++ = *ch++);
}
int main()
{
	char ch[] = "hello world";
	char dest[100];
	my_strcpy(dest, ch);
	printf("%s\n", dest);
	return 0;
}

注:1.两个指针相加减得到的结果是两个指针的偏移量(步长)2.数组作为函数参数会退化为指针,丢失数组的精度。

4.字符串去空格

(1)初阶写法

#include<stdio.h>
void remove_space(char* ch)
{
	char str[100] = { 0 };
	int i = 0;
	int j = 0;
	while (ch[i] != '\0')
	{
		if (ch[i] != ' ')
		{
			str[j] = ch[i];
			j++;
		}
		i++;
	}
	printf("%s\n", str);
}
int main()
{
	char ch[] = "    h  e ll  o  w  o r l  d";
	remove_space(ch);
	return 0;
}

(2)进阶写法

#include<stdio.h>
void remove_space(char* ch)
{
	//用来遍历字符串
	char* ftemp = ch;
	//记录非空格字符串
	char* rtemp = ch;
	while (*ftemp)
	{
		if (*ftemp != ' ')
		{
			*rtemp = *ftemp;
			rtemp++;
		}
		ftemp++;
	}
	*rtemp = 0;
}
int main()
{
	char ch[] = "    h  e ll  o  w  o r l  d";
	remove_space(ch);
	printf("%s\n", ch);
	return 0;
}

5.指针作为函数返回值

(1)数组样式

#include<stdio.h>
char* my_strchr(char* str, char ch)
{
	int i = 0;
	while (str[i])
	{
		if (str[i] == ch)
		{
			return&str[i];
		}
		i++;
	}
	return NULL;
}
int main()
{
	char str[] = "hello world";
	char* p = my_strchr(str, 'm');
	if (p == NULL)
	{
		printf("未找到\n");
	}
	else
	{
		printf("%s\n", p);
	}
	return 0;
}

(2)指针样式

#include<stdio.h>
char* my_strchr(char* str, char ch)
{
	while (*str)
	{
		if (*str == ch)
		{
			return str;
			str++;
		}
		return NULL;
	}
	
}
int main()
{
	char str[] = "hello world";
	char* p = my_strchr(str, 'm');
	if (p == NULL)
	{
		printf("未找到\n");
	}
	else
	{
		printf("%s\n", p);
	}
	return 0;
}

6..字符指针作为函数参数

(1)普通样式

#include<stdio.h>
int my_strlen(char* ch)
{
	//计算字符串有效长度
	int i = 0;
	while (ch[i] != '\0')
	{
		i++;
	}
	return i;
}
int main()
{
	char ch[] = "hello world";
	int len = my_strlen(ch);
	printf("%d\n", len);
	return 0;
}

(2)指针样式

#include<stdio.h>
int my_strlen(char* ch)
{
	char* temp = ch;
	while (*temp != '\0')temp++;
	return temp - ch;
}
int main()
{
	char ch[] = "hello world";
	int len = my_strlen(ch);
	printf("%d\n", len);
	return 0;
}

注:例:char ch[] = "hello world";//栈区字符串    char*p="hello world";//数据区常量区字符串

7. 字符串出现次数

#include<stdio.h>
char* my_strstr(char* src, char* dest)
{
	//用作于循环遍历的指针
	char* fsrc = src;
	//记录每次相同的首地址
	char* rsrc = src;
	char* tdest = dest;
	while (*fsrc)
	{
		rsrc = fsrc;
		while (*fsrc == *tdest && *fsrc != '\0')
		{
			fsrc++;
			tdest++;
		}
		if (*tdest == '\0')
		{
			return rsrc;
		}
		//回滚
		fsrc = rsrc;
		tdest = dest;
		fsrc++;
	}
	return NULL;
}
int main()
{
	char* str = "11abcd111122abcd3322abcd33333322qqq";
	char ch[] = "abcd";
	char* p = my_strstr(str, ch);
	int count = 0;//记录个数
	while (p != NULL)
	{
		count++;
		p += strlen(ch);
		p = my_strstr(p, ch);
	}
	printf("abcd在字符串中出现:%d次\n", count);
	return 0;
}

8.非空格字符串个数

(1)普通版

#include<stdio.h>
int getstrcount(char* ch)
{
	int i = 0;
	int count = 0;
	while (ch[i])
	{
		if (ch[i] != ' ')
		{
			count++;
		}
		i++;
	}
	return count;
}
int main()
{
	char ch[] = "    hello world   ";
	int len = getstrcount(ch);
	printf("%d\n", len);
	return 0;
}

(2)指针版

#include<stdio.h>
int getstrcount(char* ch)
{
	int count = 0;
	while (*ch)
	{
		if (*ch != ' ')count++;
		ch++;
	}
	return count;
}
int main()
{
	//统计字符串出现个数
	char ch[] = "     hello   world    ";
	//存储字符串出现次数
	int arr[26] = { 0 };
	for (int i = 0; i < strlen(ch); i++)
	{
		arr[ch[i] - 'a']++;
	}
	for (int i = 0; i < 26; i++)
	{
		if (arr[i])
		printf("字母:%c出现次数:%d\n",i + 'a', arr[i]);
	}
	return 0;
}

9.字符串逆置

(1)数组样式

#include<stdio.h>
void inverse(char* ch)
{
	int i = 0;
	int j = strlen(ch) - 1;
	while (i < j)
	{
		char temp = ch[i];
		ch[i] = ch[j];
		ch[j] = temp;
		i++;
		j--;
	}
	return;
}
int main()
{
	char ch[] = "hello world";
	inverse(ch);
	printf("%s\n", ch);
	return 0;
}

(2)指针样式

#include<stdio.h>
void inverse(char* ch)
{
	char* ftemp = ch;
	char* btemp = ch + strlen(ch) - 1;
	while (ftemp < btemp)
	{
		char temp = *ftemp;
		*ftemp = *btemp;
		*btemp = temp;
		ftemp++;
		btemp--;
	}
	return;
}
int main()
{
	char ch[] = "hello world";
	inverse(ch);
	printf("%s\n", ch);
	return 0;
}

10.回文字符串

#include<stdio.h>
int symm(char* ch)
{
	char* ftemp = ch;
	char* btemp = ch + strlen(ch) - 1;
	while (ftemp < btemp)
	{
		if (*ftemp != *btemp)
			return 1;
		ftemp++;
		btemp--;
	}
	return 0;
}
int main()
{
	char ch[] = "abcba";
	int value = symm(ch);
	if (!value)
	{
		printf("相同\n");
	}
	else
	{
		printf("不相同\n");
	}
	return 0;
}

以上代码均已经过严格的调试,同时上面的代码均是通过数组样式和指针样式写的,只想让大家比较一下二者的代码量,最后和大家说一下指针的重要性,但凡触碰过C语言的人无疑都知道指针是整个C语言中最难的,考点特别综合还不好理解。但是我个人认为,指针也是我们进入编程的敲门砖,也是我们走上IT的一条必经之路,指针虽难,但是学会了以后可以大幅度的简化我们的代码量,这也是我们和有些辅学C语言的人拉开差距的开始,我们写的指针代码绝大多数情况下都是真真正正的编程人才能真正理解的,不是吗?所以指针虽难,请大家坚持下去,学下去。它也是我们日后是选择学C++还是JAVA的一个选择,因为C++还需要学指针嘛,真正的掌握C++和C,JAVA甚至更多的语言以后,我们不禁会发现对编程的理解也更加深了。最后祝愿看到此博客的全体成员能攻克现在所处的困难,未来的路都能扬帆起航,谢谢大家!