c/c++零基础坐牢第九天

发布时间 2023-04-27 23:33:39作者: 寒心小呆

c/c++从入门到入土(9)

开始时间2023-04-27 19:27:23

结束时间2023-04-27 23:27:35

前言:哈哈,今天是五一假期前的狂欢了?不少明天没课的同学都飞奔回家咯。咳咳,都来玩星穹铁道,不玩星穹铁道都是轨子,我铁道兵要来打轨子啦!经过几天的沉淀,对函数多少有些理解,咱们今天就来进行函数编程的相关练习!

实验四 函数程序设计

第一题 应用函数将整数转换成字符串

一.问题描述

完成程序,设计实现函数int itoa(long int x,char a[]),其功能为将给定的整数x转换成字符串存储在a数组中。

函数接口定义:
int itoa(long int i,char a[]);/*功能为将给定的整数x转换成字符串存储在a数组中*/
裁判测试程序样例:
#include <stdio.h>
#define N 12

/* 请在这里填写答案 */

int main(){
    long int n;
    char a[N];
    scanf("%ld",&n);
    itoa(n,a);
    printf("%s",a);
    return 0;
}
输入格式:
请在一行中输入整数x的值。

输出格式:
对每一组输入的x,输出其字符串形式。

输入样例1:
72
输出样例1:
72
输入样例2:
0
输出样例2:
0
输入样例3:
-512
输出样例3:
-512
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 二.设计思路

既然是一道函数题,咱们首先看裁判样例,标准库函数下面宏定义N为12,主函数中声明长整型n,字符类数组a[N]然后输入n后便调用我们的自定义函数。我们要写的一个函数要满足的功能是将n又整型转换为字符型后存储,比如整型的72是一个数,但存入字符数组变为两个字符‘7’,‘2’。那我们应该如何来做?首先我们将所给整数每个位置上的数单拎出来,将该数加上‘0’便将整型数字变为字符数字 ,依次做循环,循环截止时,便将数字完全转化为各位的字符数字。值得一提,若所给数字为负数,那么我们要先判断符号,为负数,将数组内的元素设为-,然后将数字变为正数形式。

三.源代码

int itoa(long int i, char a[])

{
    int t=0,flag=1;
    char temp;
    if(i<0)
    {
        flag=-1;
        i=-i;
    }
   do
    {
        a[t++]=i%10+'0';
    }while(i/=10);
    if(flag==-1)
    {
        a[t++]='-';
    }
    a[t]='\0';
    for(t--,i=0;i<t;i++,t--)
    {
        temp=a[t];
        a[t]=a[i];
        a[i]=temp;
    }
    return a[N];
}

 

第二题 应用函数实现矩阵乘法

一.问题描述

完成程序,设计实现函数void f(int a[],int b[],int c[],int m,int n,int t),其功能为计算给定的两个整型数组(一个为m行n列,一个为n行t列)的乘积矩阵。

函数接口定义:
void f(int a[],int b[],int c[],int m,int n,int t);/*功能为计算给定的矩阵a(m行n列)和矩阵b(n行t列)的乘积矩阵c*/
裁判测试程序样例:
#include <stdio.h>

/* 请在这里填写答案 */

int main(){
    int i,j,a[3][4],b[4][3],c[3][3];
    for(i=0; i<3; i++)
        for(j=0; j<4; j++)
            scanf("%d",&a[i][j]);
    for(i=0; i<4; i++)
        for(j=0; j<3; j++)
            scanf("%d",&b[i][j]);
    f(a[0],b[0],c[0],3,4,3);
    for(i=0; i<3; i++){
        for(j=0; j<3; j++)
            printf("%5d",c[i][j]);
        printf("\n");
    }
}
输入格式:
首先输入整型数组a[3][4]的各元素的值,再输入整型数组b[4][3]的各元素的值,数据中间以空格为间隔。

输出格式:
对于输入的a数组和b数组,输出a和b的乘积矩阵c[3][3],其中每个元素显示格式为:占5列,右对齐。

输入样例:
1 2 3 4
2 3 4 5
3 4 5 6
1 2 3
2 3 4
3 4 5
4 5 6
输出样例:
   30   40   50
   40   54   68
   50   68   86
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.设计思路

看主函数,声明了i,j,二维数组a,二维数组b,和乘积二维数组c,在第一个嵌套循环中给a数组赋值,在第二个循环中给b数组赋值,接着调用函数。在函数中我们要做到的功能是,给到a数组和b数组,以矩阵相乘的形式得到c数组。要知道矩阵相乘第一行第一个数为矩阵a的第一行成矩阵b第一列,第一行第二个数为第一行第二个数为a的第一行乘b的第一列,第一行第三个数为a的第一行乘b的第三列,第二列同理。一个我们要做循环不仅满足相乘还要相加。

三.源代码

void f(int a[3][4],int b[4][3],int c[3][3],int m,int n,int t)
{
    int i,j,k;
    for(i=0;i<m;i++)
    {
        for(j=0;j<t;j++)
        {
            int sum=0;
            for(k=0;k<n;k++)
            {
                sum+=(a[i][k]*b[k][j]);
            }
            c[i][j]=sum;
        }
    }
}

 

第三题 应用递归函数求解N阶勒让德多项式

一.问题描述

完成程序,设计实现函数double p(int n,int x),其功能为计算给定参数n和x的N阶勒让德多项式

的值。N阶勒让德多项式

的递归公式如下所示:


函数接口定义:
double p(int n,int x);/*功能为计算给定参数n和x的N阶勒让德多项式的值*/
裁判测试程序样例:
#include <stdio.h>

/* 请在这里填写答案 */

int main(){
    int x,n;
    scanf("%d%d",&n,&x);
    printf("P%d(%d)=%.1f\n",n,x,p(n,x));
    return 0;
}
输入格式:
请在一行中输入整数n和x的值,数据中间以空格为间隔。

输出格式:
对每一组输入的n和x,按照以下格式输出N阶勒让德多项式pn(n , x)的值。

P< n >(< x >)=<值>。

输入样例:
2  2
输出样例:
P2(2)=2.0
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.设计思路

看主函数,声明两个基本整型x和n,然后输入x,n。函数功能为计算给定参数n和x的N阶勒让德多项式。首先这个勒让德多项式是跟n有关的,分三种情况,n=0,n=1,n>1.分别计算。

三.源代码

double p(int n,int x)
{
    if(n==0)
        return 0;
    else if(n==1)
        return x;
    else if(n>1)
        return ((2*n-1)*x-p(n-1,x)-(n-1)*p(n-2,x))/n;
}

 

第四题 应用递归函数实现起泡排序

一.问题描述

完成程序,设计实现递归函数void sort(int a[],int n),其功能为使用“起泡法”对a数组存储的n(n<=20)个数按从大到小排序,排列后任然存储a数组中。

函数接口定义:
void sort(int a[],int n);/*功能为使用“起泡法”对a数组存储的n(n<=20)个数按从大到小排序,排列后任然存储a数组中*/
裁判测试程序样例:
#include <stdio.h>
#define N 20

/* 请在这里填写答案 */

int main(){
    int a[N],i,n;
    scanf("%d",&n);
    if(n>20)  printf("error data");
    else{
        for(i=0; i<n; i++)
            scanf("%d",&a[i]);
        sort(a,n);
        for(i=0; i<n; i++)
            printf("%5d",a[i]);
        printf("\n");
    }
    return 0;
}
输入格式:
请在第一行中输入整数n的值,表示数据的个数。

在第二行中输入n个无序整数,数据中间以空格为间隔。

输出格式:
对每一组输入的n个无序整数,输出按照从小到大顺序的排序结果,其中每个数显示格式为:占5列,右对齐。

输入样例1:
10
1 2 3 4 5 0 9 8 7 6
输出样例1:
    9    8    7    6    5    4    3    2    1    0
输入样例2:
45
输出样例2:
error data
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.设计思路

看裁判程序样例,头文件下方宏定义N为20,在主函数中,首先声明i,n和数组a,输入n的值,以n的值进行判断n<20程序继续走,从键盘输入数组a,调用sort函数,注意!在c++中sort函数在库中存在,但在c中没有,此处给出sort函数的自定义。函数功能为将数组a从大到小排序,存进数组a中。冒泡排序在趣味算法里讲过,不赘述嗷。

三,源代码

void sort(int a[N],int n)
{
    int i,j,temp;
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-1-i;j++)
        {
            if(a[j]<a[j+1])
            {
                temp=a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
            }
        }
    }
}

 

第五题 应用函数求最大公约数

一.问题描述

完成程序,设计实现函数int gcd(int a,int b),其功能为计算给定的两个正整型数a和b的最大公约数。

函数接口定义:
int gcd(int a,int b);/*功能为计算给定的两个正整型数a和b的最大公约数*/
裁判测试程序样例:
#include <stdio.h>

/* 请在这里填写答案 */

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d",gcd(a,b));
    return 0;
}
输入格式:
请在一行中输入整数a和b的值,数据中间以空格为间隔。

输出格式:
对每一组输入的a和b,输出它们的最大公约数。

输入样例:
24 36
输出样例:
12
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.设计思路

在主函数中,首先声明整型a,b,然后给a,b赋值,输出a,b的最大公约数。很显然,在函数中我们要求解ab之间的最大公约数,我们怎么做呢,定义两个整型n和r,用一个数a取余一个数b,剩下的值给到r作为循环表达式,如果a能够取余b,则把a的值赋给b,剩下的值r赋给a,继续循环,最后a的值为最大公约数。

三.源代码

int gcd(int a,int b)
{
    int n,r;
    while(r=b%a)
    {
        b=a;
        a=r;
    }
    n=a;
    return n;
}

 

第六题 方程的根

一.问题描述

(谭浩强,《C程序设计(第四版)》,清华大学出版社:第七章,P218,第2题)

完成程序,设计实现函数void f(double a,double b,double c),其功能为输出方程的根,要求考虑a=0、a=0&b=0



等情况。

函数接口定义:
void f(double a,double b,double c);/*功能为输出一元二次方程的根,要求考虑参数的所有情况*/
裁判测试程序样例:
#include <stdio.h>
#include <math.h>

/* 请在这里填写答案 */

int main(){
    double a,b,c;
    scanf("%lf%lf%lf",&a,&b,&c);
    f(a,b,c);
    return 0;
}
输入格式:
请在一行中输入方程参数a、b和c的值,数据中间以空格为间隔。

输出格式:
对每一组输入的方程参数,输出方程的根。

输入样例1:
1.0  2.0  3.0
输出样例1:
-1.000000+1.414214i,-1.000000-1.414214i
输入样例2:
1.0  2.0  1.0
输出样例2:
-1.000000
输入样例3:
0.0  2.0  2.0
输出样例3:
-1.000000
输入样例4:
1.0  4.0  1.0
输出样例4:
-0.267949,-3.732051
输入样例5:
0.0  0.0  1.0
输出样例5:
error data
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.设计思路

分析裁判程序,在标准库函数下有数学库文件头,引入双精度浮点型a,a,c,并对a,b,c赋值,再调用函数。

三.源代码

void f(double a,double b,double c)
{
    double x,x1,x2,m,n,dt;
    if(a==0&&b==0)
        printf("error data\n");
    else if(a==0&&b!=0)
        {
         x=-c/b;
        printf("%f",x);
        }
    else if(a!=0)
    {
         dt=b*b-4*a*c;
        if(dt==0)
        {    x=((-b)+sqrt(dt))/(2*a);
            printf("%f",x);
        }
        else if(dt>0)
        {
            x1=((-b)+sqrt(dt))/(2*a);
            x2=((-b)-sqrt(dt))/(2*a);
            printf("%f,%f",x1,x2);
        }
        else if(dt<0)
        {
             m=-b/(2*a);
             n=sqrt(-dt)/(2*a);
            printf("%f+%fi,%f-%fi",m,n,m,n);
        }
    }
}

 

第七题 矩阵转置

一.问题描述

完成程序,设计实现函数void f(int a[][N],int n),其功能为实现一个给定的n*n(n<=N,N=10)的二维整形数组转置。

函数接口定义:
void f(int a[][N],int n);/*功能为实现一个给定的n*n(n<=N,N=10)的二维整形数组转置*/
裁判测试程序样例:
#include <stdio.h>
#define N 10

/* 请在这里填写答案 */

int main(){
    int a[N][N],n,i,j;
    scanf("%d",&n);
    if(n<1||n>10)  printf("error data");
    else{
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
                scanf("%d",&a[i][j]);
        f(a,n);
        for(i=0; i<n; i++){
            for(j=0; j<n; j++)
                printf("%5d",a[i][j]);
            printf("\n");
        }
    }
    return 0;
}
输入格式:
请在第一行中输入二维矩阵a[n][n]的维数大小n的值。

然后输入该二维矩阵的元素的值,数据中间以空格为间隔。

输出格式:
对输入的二维矩阵,以方阵形式输出转置后的二维矩阵,其中每个元素显示格式为:占5列,右对齐。

输入样例1:
5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
输出样例1:
    1    6   11   16   21
    2    7   12   17   22
    3    8   13   18   23
    4    9   14   19   24
    5   10   15   20   25
输入样例2:
15
输出样例2:
error data
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.程序设计

我们要做的功能是矩阵转置,也就是说,将二维数组的行全部变为列,将所有的列变为行。

三.源代码

void f(int a[][N],int n)
{
    int i,j,t;
    for(i=0;i<n;i++)
        for(j=i+1;j<n;j++)
        {
            t=a[i][j];
            a[i][j]=a[j][i];
            a[j][i]=t;
        }
}

 

第八题 最长单词

一.问题描述

完成程序,设计实现函数void f(char a[]),其功能为输出a[]存储的字符串中最长的单词,如有多个最长单词,则输出位置最靠前的。字符串的总长度小于100。

函数接口定义:
void f(char a[]);/*输出a[]存储的字符串中最长的单词*/
裁判测试程序样例:
#include <stdio.h>
#define N 100

/* 请在这里填写答案 */

int main(){
    char c[N];
    gets(c);
    f(c);
    return 0;
}
输入格式:
请输入一行单词,总长度小于100。

输出格式:
对于输入的字符串,输出其中最长的单词。

输入样例:
It adopts (greatest common denominator) principle to provide a union set of components that appear on every platform.
输出样例:
denominator
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.源代码

void f(char a[])
{
int pos,tpos,len=0,tlen=0;
int i=0;
do
{
    if ((a[i]>='a' && a[i]<='z')||(a[i]>='A' && a[i]<='Z'))
    {
        if (!tlen)//记录字符位置和长度R
        tpos=i;
        tlen++;
        //printf("%d%d\n",tpos,tlen);//可查看字符位置和长度R
    }

    else
    {   //printf("%d%d\n",pos,len);//查看上一步字符位置和长度R
        if (tlen>len)//此时单词结束与上一个单词长度进行比较R
        {
        pos=tpos;
        len=tlen;
        //printf("%d%d\n",pos,len);//可查看比较后结果R
        }
    tlen=0;
    }
}
while (a[i++]);
for (i=0;i<len;i++)
    printf("%c",a[pos+i]);//打印最长单词R
}

 

第九题 牛顿迭代法

一.问题描述

完成程序,设计实现函数double f(double a,double b,double c,double d,double x),其功能为运用牛顿迭代法求方程


在x附近的一个实根。

函数接口定义:
double f(double a,double b,double c,double d,double x);/*功能为运用牛顿迭代法求给定方程在x附近的一个实根*/
裁判测试程序样例:
#include <stdio.h>
#include <math.h>

/* 请在这里填写答案 */

int main(){
    double a,b,c,d,x;
    scanf("%lf%lf%lf%lf%lf",&a,&b,&c,&d,&x);
    printf("%lf\n",f(a,b,c,d,x));
    return 0;
}
输入格式:
请在一行中输入方程系数a、b、c、d和实数x,数据中间以空格为间隔。

输出格式:
对每一组输入的数据,输出牛顿迭代法求出的实根。

输入样例:
1.0  2.0  3.0  4.0  1.0
输出样例:
-1.650629
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二..设计思路

具体过程:设 x* 是 f(x) = 0 的根,选取 x0 作为 x* 的初始近似值,过点 (x0,f(x0)) 作曲线 y = f(x) 的切线 L,L:y = f(x0) + f'(x0)(x - x0),则 L 与 x 轴交点的横坐标为:,称 x1 为 x* 的一次近似值。过点 (x1, f(x1)) 作曲线 y = f(x) 的切线,切线与 x 轴的交点横坐标为:,称 x2 为 x* 的二次近似值。重复上述过程,得 x* 的近似值序列,其中:称为 x* 的 n + 1 次近似值,上式称为牛顿迭代公式。

三.源代码

double f(double a,double b,double c,double d,double x)/*功能为运用牛顿迭代法求给定方程在x附近的一个实根*/
{
    double x0,f,f1;
    do
    {
        x0=x;
        f=((a*x0+b)*x0+c)*x0+d;
        f1=(3*x0*a+2*b)*x0+c;
        x=x0-f/f1;
    }while(fabs(x-x0)>=1e-3);
    return(x);
}

 

第十题 学生成绩

一.问题描述

程序输入n(0<n<=10)名学生5门课程的成绩,分别调用函数实现以下功能:

(1)设计实现函数void aver(int a[][5],double ave[],int n),其功能为计算每位学生的平均分。

(2)设计实现函数void couAver(int a[][5],double couAve[5],int n),其功能为计算每门课程的平均分。

(3)设计实现函数void max(int a[][5],char courName[][10],int n),其功能为输出所有分数中最高分数对应的学生的序号(从1开始)、课程名称及成绩,每个最高分的信息占一行。

(4)设计实现函数double averVari(double ave[],int n),其功能为计算n名同学的平均分方差:

其中

为某一学生的平均分。

函数接口定义:
void aver(int a[][5],double ave[],int n);/*功能为计算每位学生的平均分*/
void couAver(int a[][5],double couAve[5],int n);/*功能为计算每门课程的平均分*/
void max(int a[][5],char courName[][10],int n);/*功能为输出所有分数中最高分数对应的学生的序号(从1开始)、课程名称及成绩,每个最高分的信息占一行*/
double averVari(double ave[],int n);/*功能为计算n名同学的平均分方差*/
裁判测试程序样例:
#include <stdio.h>
#include <math.h>
#define N 10

/* 请在这里填写答案 */

int main(){
    char courName[5][10];/*课程名称*/
    int n,i,j,a[N][5];/*n学生人数,a学生成绩*/
    double ave[N],couAve[5];/*ave学生平均成绩,couAve课程平均成绩*/
    for(i=0; i<5; i++)
        gets(courName[i]);
    scanf("%d",&n);
    for(i=0; i<n; i++)
        for(j=0; j<5; j++)
            scanf("%d",&a[i][j]);
    aver(a,ave,n);
    printf("Average:\n");
    for(i=0; i<n; i++){
        printf("[No.%d]Average=%f\n",i+1,ave[i]);
    }
    couAver(a,couAve,n);
    printf("CourseAverage:\n");
    for(i=0; i<5; i++){
        printf("[%s]CourseAverage=%f\n",courName[i],couAve[i]);
    }
    max(a,courName,n);
    printf("Averagevariance=%f",averVari(ave,n));
    return 0;
}
输入格式:
首先输入5门课程的课程名称,每门课程名称占一行,且长度小于10字符。

再输入学生人数n,n小于10。

再输入n名学生的5门课程成绩,每名同学的成绩占一行,数据中间以空格为间隔。

输出格式:

对每一组输入的学生成绩,首先以以下格式输出每位学生的平均分,每位同学占一行:[No.<序号>]Average=<平均成绩>

再者以以下格式输出每门课程的平均分,每门课程占一行:[<课程名称>]CourseAverage=<课程平均分>

再者以以下格式输出最高分数对应的学生的序号(从1开始)、课程名称及成绩,每个最高分的信息占一行:No.<序号>[<课程名称>]=成绩

最后以以下格式输出输出n名同学的平均分方差:Averagevariance=<平均分方差>。

输入样例:
YuWen
ShuXue
YingYu
DiLi
LiShi
3
100 98 87 76 100
95 78 79 69 89
100 59 92 85 87
输出样例:
Average:
[No.1]Average=92.200000
[No.2]Average=82.000000
[No.3]Average=84.600000
CourseAverage:
[YuWen]CourseAverage=98.333333
[ShuXue]CourseAverage=78.333333
[YingYu]CourseAverage=86.000000
[DiLi]CourseAverage=76.666667
[LiShi]CourseAverage=92.000000
Max:
No.1[YuWen]=100
No.1[LiShi]=100
No.3[YuWen]=100
Averagevariance=18.728889
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

 

二.源代码

void aver(int a[][5],double ave[],int n)
    /*功能为计算每位学生的平均分*/
{int i,j;
double sum;
    for(i=0;i<n;i++)
    {
        for(j=0;j<5;j++)
        {
            sum+=a[i][j];
        }
        ave[i]=sum/5;
        sum=0;
    }
}
void couAver(int a[][5],double couAve[5],int n)
    /*功能为计算每门课程的平均分*/
{int i,j;
 double s;
    for(i=0;i<5;i++)
    {
        for(j=0;j<n;j++)
        {
            s+=a[j][i];
        }
        couAve[i]=s/n;
        s=0;
    }
     return 0;
}
void max(int a[][5],char courName[][10],int n)
{
    int b[50]={1,2,3},c[50];//b数组存学号 c数组存成绩 
    char d[50][10]={'\0'}   ;//d数组存科目 
    int e=a[0][0];
    int i,j,k=0,m;
    printf("Max:\n");
    for(i=0;i<n;i++)
    {
        for(j=0;j<5;j++)
        {
            if(e<a[i][j])
            {
                e=a[i][j];
            }
        }
    }//找到最大值
    for(i=0;i<n;i++)
    {
        for(j=0;j<5;j++)
        {
            if(e==a[i][j])
            {
                b[k]=i+1;
                for(m=0;courName[j][m]!='\0';m++)
                {
                    d[k][m]=courName[j][m];
                }    
                c[k]=e;
                k++; 
            }
        }
    }
    for(i=0;i<k;i++)
    {
        printf("No.%d[",b[i]);
        for(j=0;d[i][j]!='\0';j++)
        {
            printf("%c",d[i][j]);
        }
        printf("]=%d\n",c[i]);
    }
}
double averVari(double ave[],int n)
/*功能为计算n名同学的平均分方差*/
{
    int i,j;
    double sum,sum2,fc;
    for(i=0;i<n;i++)
    {
        sum2+=ave[i];
        sum=sum+ave[i]*ave[i];
    }
    fc=sum/n-sum2*sum2/n/n;
    return(fc);
}

总结:祝大家五一假期快乐!