C站的小伙伴们,大家好呀!😊😊✨✨这一篇是C语言之经典题目篇,除程序设计,还有一些不错的程序分析,快来和我一起进入C语言的世界吧!✨✨✨
💕C语言其他·刷题篇在这里哦:
【C语言经典题目(一)】
【C语言经典题目(二)】
【C语言字符串刷题篇】
【C语言 语言篇数组和字符串】
C语言经典题目三
- 程序分析
- 一:输出指向字符的指针
- 二:for循环和switch语句体中break和continue
- 三 :双指针完成赋值
- 求数组相邻两个数之和
- 删除值为x的数组元素
程序分析
一:输出指向字符的指针
分析一下程序执行后的输出结果:___________
#include <stdio.h>
int main (void)
{
char *string="I love China!"; //(1)
printf("%s\n",string); //(2)
string+=7; //(3)
while(*string) //(4)
{
putchar(string[0]);
string++;
}
return 0; //(5)
}
对于指针类题目,画图可以更加直观地帮助我们分析理解。
(1)
字符型指针string指向了字符串"I love China!"的第一个元素,即C。
(2)
第二条语句,printf()函数中格式控制字符%s
控制输出项是指向字符的指针,输出方式是从该指针指向的字符即'C'
开始输出,直到遇到'\0'
输出结束。故第二条语句输出结果为 I love China!
(3)
指针向下移动7位,指向了元素’C’。
(4)
进入循环体,当*string (即指针指向的元素的值)为非零
值时,执行循环体中的语句。此语句依次输出’C’ ‘h’ ‘i’ ‘n’ ‘a’ ‘!’
故该程序所有的输出结结果为:
二:for循环和switch语句体中break和continue
分析程序执行后的输出结果______________
#include <stdio.h>
int main(void)
{
char str[]="ssswlia",c; \\(1)
int k;
for (k=2;(c=str[k])!='\0';k++) \\(2)
{
switch(c)
{
case 'i':++k;break;
case 'l':continue;
default:putchar(c);continue;
}
putchar('*'); \\(3)
}
printf("\n");
return 0;
}
(1)
定义字符数组,将字符串存入字符数组。
注意,字符串的长度(用strlen()函数计算)为7
,而字符数组的长度为8
(用sizeof()函数计算,得到字符数组的字节数,再除以char型元变量所占的字节数,即1,即可得到字符数组的长度。)
(2)
指针进行for循环。
循环体是个switch语句,这里要搞清楚switch和break的用法。
break
只用于循环体或者switch语句体中。当用于循环体中时,它的作用是退出循环。当用于switch语句体内时,作用只是跳出该switch语句体,注意此时并不能终止循环。
continue
语句只用于循环体,它的作用是跳过本次循环体中剩下尚未执行的语句,立即进行下一次的循环条件判定。
分析
对于这个题目的分析,如下图。
- 指针指向’s’,进入for循环,for循环的第一条语句是switch语句,符合switch第三条语句,输出’s’,这是遇到continue语句(注意continue语句是对于for语句而言的),不执行在for循环体中该语句之后的语句,(即 putchar()语句),进行下一次的循环,k++,指针向下移动。
- 指针指向’w’,这个情况和刚刚的指针指向’s’的情况过程一样。
- 下一步,指针指向’l’,在这种情况下,执行continue语句,即要直接进行下一次的for循环,指针向下移动。
- 下一步,指针指向’i’,在这种情况下,执行switch语句体里的两条语句。指向向下移动,指向’a’,执行break语句,退出switch语句体,(注意此时并不会退出for循环),执行putchar()语句,输出’*’。指针移动,指向’\0’。结束for循环。
- 因此最终的输出结果为 sw*
三 :双指针完成赋值
#include <stdio.h>
int main(void)
{
void fun(char *); //(1)
char str[]="abcdefggedcba"; //(2)
fun(str); //(3)
puts(str);
}
void fun(char *p) //(4)
{
int i,j;
for (i=0;*(p+i)!='\0';i++)
if (*(p+i)>='d')
{
*(p+j)=*(p+i);
j++;
}
*(p+j)=0;
}
(1)
在主函数中声明被调函数。
(2)
将字符串存入字符数组。
(3)
调用被调函数。
(4)
分析大概思路
主函数将str传递给指针p,即将字符数组第一个元素’a’的首地址传递给了指针p,p指向a。
在被调函数体,有两个指针。它们初始状态都是指向a。
p+i不断移动,当满足for循环体中的条件时,p+j移动。
具体执行过程
指针p+i不断移动,p+0,p+1,p+2,所指向的值都小于’e’,因此p+j不移动(j=0)
当p+i(i=3时),满足if条件,*p+j(j=0)赋值为d,并向下移动……
最后,将p+j所指向的元素的值赋值为0。
求数组相邻两个数之和
求数组a中相邻两个元素之和,并将这些和存在数组b中,按每行3个元素的形式输出。
#include <stdio.h>
int main (void)
{
int a[10],b[10],i;
//初始化数组a
for (i=0;i<10;i++)
scanf("%d",&a[i]);
//将相邻两个数之和依次赋值给数组b
for (i=1;i<10;i++)
b[i]=a[i]+a[i-1];
//输出数组b
for (i=1;i<10;i++)
{
printf("3d",b[i]);
if (i%3==0) printf("\n");//控制格式
}
return 0;
}
删除值为x的数组元素
主要思路
对数组中的元素进行遍历,检验每一个元素是否等于目标元素x,若是相等,则删除?
怎样实现删除
呢?就是自这个元素起,将其后面的每一个元素向前移动一位。
在这个过程我们使用指针实现,要注意指针越界行为。
#include <stdio.h>
int main(void)
{
int a[10]={1,3,5,2,2,6,8,10,0,2};
int x,*p,count=0,i;
x=2;
for (p=a;p<a+10-count;p++) //(1)
{
if (*p=x) //(2)
{
count++;
for (i=p-a;i<10-count;i++) //(3)
a[i]=a[i+1];
p--; //(4) //注意这里的p--防止漏掉某个元素的检验
}
}
for (p=a;p<a+10-count;p++)
printf("5d",*p);
printf("\n");
return 0;
}
(1)
指针p初识指向数组a的第一个元素,即指向1。
这里设置的循环条件是为了防止指针越界。
1,3,5都不等于目标元素2,所以指针的指向不变。
(2)
当指针移动到下一个元素即2时,count++,这时会使得指针的下界向左移动。
(3)
在里层的for循环中,将p指针所指的位置开始,把后面的元素的值赋值给前一个元素。这样就实现了删除
。
(4)
假设这里没有p–,那么执行完for循环循环体中的语句,会p++(for循环(1)中),注意这时可以已经删掉一个目标元素后的数组,那么移动后p所指向的元素检验了吗?还没有,就又移动到了下一个元素。所以没有 p–这条语句,会使得漏掉一些元素,最终没法达到目的。