【c语言】函数+指针习题总结{代码优化}(实用)

Hi~ o(* ̄▽ ̄*)ブ,今天是习题习题~~~

目录

一、内容介绍

二、函数习题

1.1 小节梗概

1.2 习题一:输出素数回文数

①算法1 倒序输出数字的优化

 ②算法2 埃氏筛选法

③实现总代码

1.3 质数筛

①普通筛选

②三倍提升

三、指针习题 

1.1 小节梗概

1.2 对数组维度的认知

1.3习题一:比赛评分

算法① 传入一维以上数组的三种方法

1.4习题二:用c语言写出分割函数

四、总结 


一、内容介绍

   本篇内容包括函数与指针的几个习题,其中每个题都含有一些实用方法或者算法,希望能够帮到您!

二、函数习题
1.1 小节梗概

本小节主要介绍有关函数的几个方法:

1.埃氏筛选法

2.素数的特殊判断法

3.倒序输入数字的优化算法

1.2 习题一:输出素数回文数

题目描述:

因为 151151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151151 是回文质数。

写一个程序来找出范围 [a,b](5≤a<b≤100,000,000)[a,b](5≤a<b≤100,000,000)(一亿)间的所有回文质数。

输入格式:

第一行输入两个正整数 a 和 b。

输出格式:

输出一个回文质数的列表,一行一个。

输入输出案例:

5 500
5
7
11
101
131
151
181
191
313
353
373
383
①算法1 倒序输出数字的优化

这一步主要是用于判断一数字是否为回文串

这里用一个习题来举例

题目:输出一个数字的倒序

输入:

123

输出:

321

代码如下: 

#include <stdio.h>
void back(int n)
{
	int m=0;
	while(n!=0)
	{
	m=m*10+n%10;//找到最低位次
	n=n/10;	//减少位次
	}
	printf("%d",m);
}
int main()
{
	int n;
	scanf("%d",&n);
	back(n);
	return 0;
} 
 ②算法2 埃氏筛选法

这一步主要是判断得到的回文数是否为素数

同样用一个题目举例,这个题我之前发过一次,感兴趣的话可以去看看:https://blog.csdn.net/2301_79982543/article/details/134755558

题目:

任一个大于等于4的偶数都可以拆分为两个素数之和,验证这个定理

输入:

一个整数n( 4 <= n <= 200 )

输出:

将小于等于n的偶数拆分为2个质数之和,列出所有方案! 

代码如下:

#include <stdio.h>
#include <math.h>
#define s 1000
int p[s+1];
int xuan(int n)
{
    int i=0;
    for(int i=0;i<=n;i++)
    p[i]=1;
    p[0]=p[1]=0;
    int t;
    t=(int)sqrt(n);//与素数的定义有一定关系,一个素数是从2~根号(该素数)都除不尽的 
    for(i=2;i<=t;i++)
    if(p)
    for(int j=2*i;j<=n;j+=i)//筛去素数的整数倍 (从2倍开始,不得不说真是天才方法)相当于是2*i+i+i+i+i...即是i的倍数 
    p[j]=0;//让i的倍数为0,那么数组中为0的数都不是素数 
}
 
int fen(int n)
{
    for(int i=3;i<=n/2;i++)//把传进来的这个偶数从中间截断,然后用偶数减去左边的素数的方法找到右边的素数,不得不说,天才!!!! 
    {
        if(p[i]&&p[n-i])
        {
            printf("%d+%d=%d",i,n-i,n);
            break;
        }
    
    }
}
int main()
{
    int a;
    scanf("%d",&a);
    if(a%2!=0)
    a++;
    xuan(s);
    fen(a);
    return 0;
}
③实现总代码
#include <stdio.h>
#include <math.h>
int c[10000000];
void su(int n)
{
int i=0;
for(int i=0;i<=n;i++)
c[i]=1;
c[0]=c[1]=0;
int t;
t=(int)sqrt(n);//与素数的定义有一定关系,一个素数是从2~根号(该素数)都除不尽的?
for(i=2;i<=t;i++)
if(c[i])
for(int j=2*i;j<=n;j+=i)//筛去素数的整数倍 (从2倍开始,不得不说真是天才方法)相当于是2*i+i+i+i+i...即是i的倍数?
c[j]=0;//让i的倍数为0,那么数组中为0的数都不是素数?
}
int back(int n)
{
	int m=0;
	int t=n;//作为判断依据 
	while(n!=0)
	{
	m=m*10+n%10;
	n=n/10;	
	}
if(m==t)
return 1;
else
return 0;
}

int main()
{
int a,b;
scanf("%d%d",&a,&b);
if(b>=100000000)
b=9999999;

su(b);
if(a%2==0)a++;
if(a>b)
return 0;
for(int i=a;i<=b;i++)
{
	if(c[i]&&back(i))
     printf("%d\n",i);	
}	
return 0;
} 

1.3 质数筛

题目描述

输入 n 个不大于 105105 的正整数。要求全部储存在数组中,去除掉不是质数的数字,依次输出剩余的质数。

输入格式

第一行输入一个正整数 n,表示整数个数。

第二行输入 n 个正整数ai ​,以空格隔开。

输出格式

输出一行,依次输出ai中剩余的质数,以空格隔开。

输入输出样例

5
3 4 5 6 7
3 5 7
①普通筛选
#include <stdio.h>
#include <math.h>
void st(long a[],long n)
{
for(int i=0;i<n;i++)
{
	for(int j=2;j<=a[i];j++)
	{
		if(a[i]%j==0&&a[i]!=j)
		{
			a[i]=0;
			break;
		}
	}
	if(a[i]!=0&&a[i]!=1)
	printf("%ld ",a[i]);
}
}
int main()
{
	long n;
	scanf("%ld",&n);
	long a[n];
	for(int i=0;i<n;i++)
	scanf("%ld",&a[i]);
	st(a,n);
	return 0; 
}

②三倍提升
int st(int n)
{
    if(n<=1) return 0;
    if(n==2||n==3) return 1;
    if(n%6!=1&&n%6!=5) return 0;
    for(int i=5;i*i<=n;i+=6) //2~根号本身
if(n%i==0||n%(i+2)==0) return 0;
    return 1;
}

参考思路:

除2,3外,其他所有素数都必须是6n+1或6n+5,因为6n+2=2(3n+1),6n+3=3(2n+1),6n+4=2(3n+2),都有非1和本身因数,不是素数

三、指针习题 
1.1 小节梗概

1,指针数组和数组指针的区别

2,一维二维三维·······对维度的认知

3,将数组传入函数

1.2 对数组维度的认知

1.3习题一:比赛评分

题目描述

n(n≤100) 名同学参加歌唱比赛,并接受 m(m≤20) 名评委的评分,评分范围是 0到 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m−2 个评分的平均数。请问得分最高的同学分数是多少?评分保留 22 位小数。

输入格式

第一行两个整数n,m。
接下来 n 行,每行各 m 个整数,表示得分。

输出格式

输出分数最高的同学的分数,保留两位小数。

输入输出样例

7 6
4 7 2 6 10 7
0 5 0 10 3 10
2 6 8 4 3 6
6 3 6 7 5 8
5 9 3 3 8 1
5 9 9 3 2 0
5 8 0 4 1 10
6.00
算法① 传入一维以上数组的三种方法 

这里有多种方法,我们以二维数组为例:

方法一:全局变量

#include <stdio.h>
int m;
int n;
int a[1000][1000];//实际上它就可以一直存在在函数中了,严格来说都不算传进去的
double st(int i,int n)
{
	int max=0,min=100;
	int sum=0;
	for(int j=0;j<n;j++)
		{
			if(a[i][j]>max)
			max=a[i][j];
			if(a[i][j]<min)
			min=a[i][j];
			sum+=a[i][j];
		}
		sum=sum-(max+min);
return sum/(double)(n-2);
}
int main()
{
	double max=0;double every;
	scanf("%d%d",&m,&n);
	for(int i=0;i<m;i++)
	for(int j=0;j<n;j++)
	scanf("%d",&a[i][j]);
	for(int i=0;i<m;i++)
	{	
	every=st(i,n);
	if(every>max)
		max=every;
	}
	printf("%.2lf",max);
	return 0;
}

方法二:分成n次传

#include <stdio.h>
int m;
int n;
double st(int n,int a[])
{
	int max=0,min=100;
	int sum=0;
	for(int j=0;j<n;j++)
		{
			if(a[j]>max)
			max=a[i][j];
			if(a[j]<min)
			min=a[j];
			sum+=a[j];
		}
		sum=sum-(max+min);
return sum/(double)(n-2);
}
int main()
{
	double max=0;double every;
	scanf("%d%d",&m,&n);
	for(int i=0;i<m;i++)
	for(int j=0;j<n;j++)
	scanf("%d",&a[i][j]);

	for(int k=0;k<m;k++)
	every=st(n,*(a+1));//核心:相当于每次传入一个一维数组
	
if(every>max)
		max=every;
	printf("%.2lf",max);
	return 0;
}

方法三:返回二维指针

int a[1000][1000];
double st(int m,int n,int **a)
{
	int max=0,min=100;
	int sum=0;
	for(int i=0;i<=m;i++)
	for(int j=0;j<n;j++)
		{
			if(a[i][j]>max)
			max=a[i][j];
			if(a[i][j]<min)
			min=a[i][j];
			sum+=a[i][j];
		}
		sum=sum-(max+min);
return sum/(double)n;
}
int main()
{
	double max=0;double every;
	scanf("%d%d",&m,&n);
	for(int i=0;i<m;i++)
	for(int j=0;j<n;j++)
	scanf("%d",&a[i][j]);
	int *p,**q;
for(int k=0;k<=m;k++,p++)
   p=a[k];	
   for(int j=0;j<=m;p++,q++)
   q=&p;
   st(m,n,q);
	if(every>max)
		max=every;
	printf("%.2lf",max);
	return 0;
}
1.4习题二:用c语言写出分割函数
#include <stdio.h>
#include <string.h>
#define SIZE 10

int my_split(char *p[SIZE], char str[], char const *sep) {
    int num = 0;
    for (p[num] = strtok(str, sep); p[num] != NULL; p[++num] = strtok(NULL, sep));
    return num; // 返回被分割成单独部分的个数
}

int main() {
    char line[] = "split@string/to#many single,part]ok";
    char *p[SIZE];
    char const *token = " ,/@#]";
    int num = my_split(p, line, token);
    for (int i = 0; i < num; i++) {
        printf("%s\n", p[i]);
    }
    return 0;
}

如果对strtok函数的实现感兴趣的话,请关注我吧,下一篇会出(^-^)V

四、总结 

1.掌握了几种优化算法,得到了复习

2.对解决不同问题有了更多的看法

3.祝看到这篇文章的您有所收获,今天也要开心(^U^)ノ~YO!!!

拜拜!!下次见~~~┏(^0^)┛哈哈哈

  • 32
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值