接着上篇文章再和大家分享一下有趣的代码!
目录
1.求母串中子串的个数
2.行走机器人
3.荷兰国旗问题
4.统计考研成绩
给定一个母串s和一个子串t,在主串s中寻找子串t的过程为字符串匹配。每匹配成功一次,即母串中含有一个子串,求母串中子串的个数。
其实,这个题目的关键有两点:①如何在母串中查找子串并计数 ?②查找后怎么进行下一次查找?具体方法在这里也不详细讲了,大家可以看下面这篇文章中第四题,那段代码能方便大家了解,而这题的代码也是在那段基础之上改进的。
有趣的代码——有故事背景的程序设计4-CSDN博客文章浏览阅读340次,点赞13次,收藏6次。前面讲过不少有故事背景的程序设计,但就知识点涉及层面还有所不足,所有,这个系列到目前为止还需更新,希望有兴趣的朋友们可以和我一起敲一敲,看看这些有背景的程序设计的实质到底是什么。目录1.鞍点2.凯撒加密3.字数统计4.字符串匹配https://blog.csdn.net/m0_74950144/article/details/134819294?spm=1001.2014.3001.550
算法实现如下:
设函数CmpNum实现在母串s中查找子串t,设变量count表示母串中含子串的个数。
1.初始化母串s的起始位置下标i=0;初始化子串t的起始下标j=0;
2.初始化比较的起始位置start=0;
3.重复下述操作,直到s的所有字符比较完毕:
3.1如果s[i]=t[i]
3.1.1继续比较母串s和子串t的下一对字符;
3.1.2如果t[i]='\0',则j=0,start=i,count++;
3.2将start后移一位,将i和j回溯,准备比较下一轮;
4.如果s中所有字符都比较完毕,则返回count;
代码实现如下:
#include
int CmpNum(char*arrs,char*arrt)
{
int i=0,j=0,start=0,count=0;
while(arrs[i]!='\0')//直接循环到arrs数组结束,这样才能查找母串中所有子串
{
if(arrs[i]==arrt[j])
{
i++;
j++;
if(arrt[j]=='\0')
{
j=0;
count++;//arrt结束一次,则代表含有一个子串
start=i;//一个子串结束,那么start也应该调整到其后面,从而减少程序的无用功
}
}
else
{
start++;
i=start;
j=0;//这里是很好的一点,让j=0,就能有效避免第一个字符相同,后面不相同时,调整使模式再次从头开始。
}
}
return count;
}
int main()
{
char s[100],t[20];
int index;
printf("请输入母串:");
gets(s);
printf("请输入子串:");
gets(t);
index=CmpNum(s,t);
printf("母串中含子串个数:%d",index);
return 0;
}
假设在平面直角坐标系内,机器人每次可以前进或后退一步、向左或向右行走一步。请模拟机器人控制系统中指令的翻译和执行过程,并给出机器人的行走路线。
在平面直角坐标系中想描述机器人的行走路线,我们肯定是要用(x,y)坐标来表示机器人的行进位置。我们可以定前进一步,位置坐标为(x+1,y),后退一步为(x-1,y),向左一步(x,y-1),向右一步到达(x,y-1)。
算法实现如下:
设变量command表示一条行走指令,函数Move模拟指令的翻译和执行系统。
1.获取机器人当前位置(x,y);
2.指令command可能存在以下四种情况:
①前进:到达位置(x+1,y);
②后退:到达位置(x-1,y);
③向左:到达位置(x,y-1);
④向右:到达位置(x,y-1);
代码实现如下:
#include
int x = 0 , y = 0 ;//全局变量哦
enum Direction
{
forward = 1,
back,
left,
right
};
void Move(enum Direction command)
{
switch(command)
{
case forward:
x++;
break;
case back:
--x;
break;
case left:
++y;
break;
case right:
--y;
break;
default:
break;
}
}
int main()
{
enum Direction command;
int i , temp ;
printf("请输入机器人的动作,用空格分隔\n");
printf("以下为指令:\n1.前进 2.后退 3.向左 4.向右\n");
printf("当前位置为(%d , %d)\n", x , y );
while(scanf("%d",&temp)!=0)
{
command = (enum Direction)temp;
Move(command);
printf("-->(%d , %d)\n", x , y );
}
return 0;
}
这道题其实单从代码的复杂度来说并不难做,只是题目背景是在有点新颖,不过,涉及的枚举类型的创建和枚举变量的定义倒是值得大家研究研究。另外,这里定义全局变量x,y有偷懒的意思,不过,这样使函数内x,y都能联系起来,方便我们处理。
重新排列一个由红,黄和蓝(这三种即是荷兰国旗的颜色)构成的数组,使得所有的红色都在最前面,白色在其次,蓝色在最后。
首先,这种红黄蓝作为数组元素的题目,我们当然可以很自然地和枚举类型或者字符型联系起来,在这里我们定义一个枚举类型。设数组arr[N]存储Red、White和Blue,设置三个参数i、j、k,其中i之前的元素全为(不包括arr[i])全部为红色;k之后的元素(不包括arr[k])全部为蓝色;i和j之间的元素全部为白色;j表示从前向后扫描。首先,将i初始化为0,k初始化为n-1;j初始化为0。j从前向后扫描,在扫描过程中根据arr[j]的颜色,将其交换到序列的前面或后面,当j=k时,算法结束。
算法实现如下:
设数组arr[N]有Red、White和Blue三种元素,函数Sort实现荷兰国旗问题。
1.初始化i=0,k=n-1,j=0;
2.当j<=k时,依次考查元素arr[j],有以下三种情况:
2.1如果arr[j]是Red,则交换arr[i]和arr[j];i++;j++;
2.2如果arr[j]是Blue,则交换arr[j]和arr[k];j++;k--;
2.3如果arr[j]是White,则j++;
代码实现如下:
#include
#define N 8
enum Color{
Red,
White,
Blue
};
void Sort (enum Color*a, int n);
/*留心观察的会发现我一般函数直接定义,很少先声明后定义,因为比较懒,
这里之所以先声明把定义放在后面,是因为两个函数的定义会比较长,那样
主函数的部分就太靠后,不便于观察,大家谨记!*/
void Print(enum Color*a, int n);
int main()
{
enum Color a[N]={White,Red,Blue,Red,Blue,White,Red};
Sort(a,N);
printf("排序后的序列为:");
Print(a,N);
return 0;
}
void Sort (enum Color*a, int n)
{
int i=0,k=n-1,j=0;
enum Color temp;
while(j
这题的设计实在是有些妙的,因为这题定义两个变量i,k作为两端,某种意义上来说,这属于双指针在数组中查找,极大地提高了代码的效率。
在计算机专业考研中,专业课考试科目包括数据结构、计算机组成原理、操作系统和计算机网络。对于一个考生,输入各科成绩,并计算总分。
因为这里一个考生的四门专业课成绩以及总分都与他有内在联系,所以我们在这里为了解决这种较为复杂的数据元素,理应构造结构体类型。
算法实现如下:
设变量totalScore存储考生的总分,变量spec1、spect2、spect3和spect4分别存储四科专业课的成绩。
1.输入一个考生的各项信息;
2.totalScore=spec1+spec2+spec3+spec4;
3.输出totalScore;
代码实现如下:
#include
struct Student
{
char no[10],name[10];
double spec1,spec2,spec3,spec4;
};
int main()
{
struct Student stu;
double totalScore;
printf("请输入考生的考号和姓名:\n");
scanf("%s%s",stu.no,stu.name);
printf("请输入四门专业课成绩,用空格分隔:\n");
scanf("%lf%lf%lf%lf",&stu.spec1,&stu.spec2,&stu.spec3,&stu.spec4);
totalScore=stu.spec1+stu.spec2+stu.spec3+stu.spec4;
printf("%s的总分是%5.1f\n",stu.name,totalScore);
return 0;
}