C语言 · 2022年5月26日 1

计算思维报告(文末有word文档)

哈尔滨工程大学

《计算思维二》实验报告

基础实践一

姓    名:           班    级:        

学    号:                                 

实验时间:     2022     年       4     月      15     日

成绩 

哈尔滨工程大学计算机基础课程教学中心

实验一:运行环境及顺序结构

实验题目1:物品折旧计算器

【问题描述】

某种物品的每年折旧费的线性计算方法如下:每年折旧费=(购买价格-废品价值)/产品设计寿命(年)。而折旧价值的计算方法如下:购买价格-每年折旧费*使用年限。

请编写一个程序,当输入物品的购买价格、废品价值、产品设计寿命和使用年限后,程序能计算出该物品的每年折旧费(结果保留两位小数),以及在到达某使用年限时的折旧价值(即残余价值,结果保留两位小数)。

【输入形式】

在一行内按顺序输入4个数据,分别为购买价格、废品价值、产品设计寿命和使用年限,每两个数据之间用逗号分隔

【输出形式】

在一行内按顺序输出每年折旧费和残余价值,用逗号分隔

【样例输入】

113.56,20.81,30,7

【样例输出】

3.09,91.92

设计思想:折旧计算

实验代码及注释:

#include<stdio.h>

int main()

{

    float a, b, c, d, e, f; //购买价格,废品价值,产品设计寿命,使用年限,每年折旧费,折旧价值

    scanf(“%f,%f,%f,%f”,&a,&b,&c,&d);

    e = (a-b)/c;

    f = a – e*d;

    printf(“%.2f,%.2f\n”,e,f);

    return 0;

}

验证与结论:完全正确

总结与心得体会:数据的计算输出

实验题目2:字母密码

【问题描述】

从键盘任意输入5个小写英文字母,将其加密后输出。加密规则是:用原来英文字母后面的第4个字母代替原来的字母。例如,小写字母a后面第4个字母是e,e代替a。再如,小写字母w后面第4个字母是a,a代替w。请编程实现上述加密方案。

【输入形式】

在一行内连续输入5个小写英文字母原文

【输出形式】

在一行内连续输出5个小写英文字母密文

【样例输入】

china

【样例输出】

glmre

【样例说明】

【评分标准】

设计思想:对字符串遍历,每个字符加4,如果值大于z,则再减26。

实验代码及注释:

#include <stdio.h>

int main()

{

    char a[5], *p;

    scanf(“%s”, a);

    for(p=a;*p!=’\0′;p++)

    {

        *p += 4;

        if(*p > ‘z’)

            *p -= 26;

    }

    printf(“%s”, a);

}

验证与结论:完全正确

总结与心得体会:对字符串的操作

实验题目3:简单的四则运算实现

【问题描述】

由键盘输入两个整数,分别计算这两个数的和、差、积、商,并输出结果。

【输入形式】

所输入的两个整数用逗号分隔

【输出形式】

输出4行数据,自上而下每行分别为两个数的和、差、积、商的结果

【样例输入】

3,-5

【样例输出】

a+b=-2

a-b=8

a*b=-15

a/b=0

【样例说明】无
【评分标准】

设计思想:四则运算

实验代码及注释:

#include<stdio.h>

int main()

{

    int a,b;

    scanf(“%d,%d”, &a, &b);

    printf(“a+b=%d\na-b=%d\na*b=%d\na/b=%d\n”,a+b,a-b,a*b,a/b);

    return 0;

}

验证与结论:完全正确

总结与心得体会:四则运算

实验题目4:C编程环境

【问题描述】

编写C程序,输出“Hello World”。编辑完成后存盘、编译、连接、运行并查看结果。

【输入形式】
【输出形式】
【样例输入】

【样例输出】

Hello World!

【样例说明】

必须输出“Hello World!”

【评分标准】

设计思想:输出hello world

实验代码及注释:

#include<stdio.h>

int main()

{

    printf(“Hello World!”);

    return 0;

}

验证与结论:完全正确 

总结与心得体会:输出hello word

实验二:选择结构

实验题目1:数字转单词

【问题描述】

编写一个程序,要求用户输入一个两位数,然后输出显示该数的英文单词。提示:把数分解为两个数字。用一个switch语句显示第一位数字对应的单词(“twenty”、“thirty”等),用第二个switch语句显示第二位数字对应的单词。不要忘记11~19需要特殊处理。

【输入形式】

一个十进制两位整数

【输出形式】

输入的整数所对应的英文单词(所含字母均小写)

【样例输入】

85

【样例输出】

eighty-five

【样例说明】

【评分标准】

正确性

设计思想:使用switch

实验代码及注释:

#include<stdio.h>

int main()

{

    int n, a, b;

    scanf(“%d”, &n);

    a = n%10;

    b = (n-a)/10;

    if(n>=10 && n<=19)

    {

        switch(n)

        {

            case 10:printf(“ten”);break;

            case 11:printf(“eleven”);break;

            case 12:printf(“twelve”);break;

            case 13:printf(“thirteen”);break;

            case 14:printf(“fourteen”);break;

            case 15:printf(“fifteen”);break;

            case 16:printf(“sixteen”);break;

            case 17:printf(“seventeen”);break;

            case 18:printf(“eighteen”);break;

            case 19:printf(“nineteen”);break;

            default:break;

        }

    }

    else

    {

        switch(b)

        {

            case 1:break;

            case 2:printf(“twenty”);break;

            case 3:printf(“thirty”);break;

            case 4:printf(“forty”);break;

            case 5:printf(“fifty”);break;

            case 6:printf(“sixty”);break;

            case 7:printf(“seventy”);break;

            case 8:printf(“eighty”);break;

            case 9:printf(“ninety”);break;

            default:break;

        }

        if(b>1 && a != 0)

            printf(“-“);

        switch(a)

        {

            case 1:printf(“one”);break;

            case 2:printf(“two”);break;

            case 3:printf(“three”);break;

            case 4:printf(“four”);break;

            case 5:printf(“five”);break;

            case 6:printf(“six”);break;

            case 7:printf(“seven”);break;

            case 8:printf(“eight”);break;

            case 9:printf(“nine”);break;

            default:break;

        }

    }

    printf(“\n”);

}

验证与结论:完全正确

总结与心得体会:Switch的使用

实验题目2:电费计算器

【问题描述】

一个电表按照如下的比率计费:

前200度电:每度0.8元;

后100度电:每度0.9元;

超过300度电:每度1元。

所有用户都是按最少100元进行收费。如果总费用大于400元,还要加收总数的15%的费用。请编写程序,从键盘输入用电量,经过计算后输出显示应收电费。


【输入形式】

一个整数,为用电量

【输出形式】

一个浮点数(保留小数点后两位),为应收电费

【样例输入】

100

【样例输出】

100.00

【样例说明】

【评分标准】

正确性

设计思想:电费计算

实验代码及注释:

#include<stdio.h>

int main()

{

    int n;

    scanf(“%d”, &n);

    float fee;

    if(n<=200)

    {

        fee = n * 0.8;

    }

    else if(n<=300)

    {

        fee = 200 * 0.8 + (n-200) * 0.9;

    }

    else if(n>300)

    {

        fee = 250 + n-300;

        if(fee>400)

            fee += fee * 0.15;

    }

    if(fee<100)

        fee = 100;

    printf(“%.2f\n”, fee);

}

验证与结论:完全正确

总结与心得体会:电费计算

实验题目3:比较大小并求和

【问题描述】

输入4个整数,求其前两个数中较小的数与后两个数中较大的数之和。

【输入形式】

输入4个整数,每两个整数之间用逗号分隔

【输出形式】

输出1个整数

【样例输入】

3,2,1,4

【样例输出】

6

【样例说明】

【评分标准】

正确性

设计思想:比较大小并求和

实验代码及注释:

#include<stdio.h>

int main()

{

    int a, b, c, d, max, min;

    scanf(“%d,%d,%d,%d”, &a, &b, &c, &d);

    if(a>b)

        min = b;

    else

        min = a;

    if(c>d)

        max = c;

    else

        max = d;

    printf(“%d\n”, min + max);

    return 0;

}

验证与结论:完全正确

总结与心得体会:比较大小并求和

实验题目4:商品优惠计算器

【问题描述】

使用if语句编程实现输入购货金额,输出实际付款金额。购货折扣率如下:

购货金额≤500元 不打折

500元<购货金额≤1000元 9折

1000元<购货金额 8折

【输入形式】

一个浮点数

【输出形式】

一个浮点数(保留小数点后两位)

【样例输入】

500.01

【样例输出】

450.01

【样例说明】


【评分标准】

正确性

设计思想:输入购货金额,输出实际付款金额

实验代码及注释:

#include <stdio.h>

int main()

{

    float money;

    scanf(“%f”, &money);

    if(money<=500)

        money = money;

    else if(money>500 && money <=1000)

        money *= 0.9;

    else

        money *= 0.8;

    printf(“%.2f”, money);

    return 0;

}

验证与结论:完全正确

总结与心得体会:输入购货金额,输出实际付款金额

实验题目5:if双分支结构简单应用

【问题描述】

输入一个整数,如果输入的数是偶数或者负数,则输出其平方,否则输出其一半的值。

【输入形式】

整型数据

【输出形式】

整型数据

【样例输入】

7

【样例输出】

3

【样例说明】

【评分标准】

正确性

设计思想:输出偶数和负数的平方,输出其他数的一半

实验代码及注释:

#include<stdio.h>

int main()

{

    int n;

    scanf(“%d”, &n);

    if(n%2==0 || n<0)

        printf(“%d\n”, n*n);

    else

        printf(“%d\n”, n/2);

    return 0;

}

验证与结论:完全正确

总结与心得体会:if的应用

实验三:循环结构

实验题目1:水仙花数

【问题描述】

打印出所有“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个水仙花数,因为153=13+53+33。

【输入形式】

【输出形式】

每行输出一个水仙花数,有多少个水仙花数,就输出多少行


【评分标准】

正确性

设计思想:计算一个数各位数,计算立方和,判断是否为水仙花数

实验代码及注释:

#include<stdio.h>

int main()

{

    int a, b, c;

    for(int n=100;n<1000;n++)

    {

        a = n%10;

        b = (n/10)%10;

        c = n/100;

        if(n == (a*a*a + b*b*b + c*c*c))

        {

            printf(“%d\n”, n);

        }

    }

    return 0;

}

验证与结论:完全正确

总结与心得体会:使用循环,计算一个数各位数,判断水仙花数

实验题目2:寻找完数

【问题描述】

完数是指一个整数恰好等于它的因子之和(除自身外),则称这个数为完数。从键盘先后输入两个不大于9999的正整数m和n,若m>n,则交换两数。然后求m~n(m和n均为正整数且m≤n)之间的所有完数。

【输入形式】

先后输入两个正整数m和n,用逗号分隔

【输出形式】

输出所有完数,每两个数之间用逗号分隔。若输入非法,则输出“error”

【样例输入】

1,2000

【样例输出】

6,28,496

【样例说明】

【评分标准】

正确性

设计思想:for循环,if判断

实验代码及注释:

#include <stdio.h>

void join_ints(const int* arr, size_t length, const char* sep) {

    for (size_t i = 0; i < length; ++i)

        printf(“%s%d”, i ? sep : “”, arr[i]);

}

int main()

{

    int m, n, temp, len=0;

    int s[4], *p; p=s;

    scanf(“%d,%d”,&m, &n);

    if(m>9999 || n>9999 || n<1 || m<1)

    {

        printf(“error\n”);

    }

    else

    {

        if(m>n)

        {

            temp=m;m=n;n=temp;

        }

        for(int i=m;i<=n;i++)

        {

            int k = 0;

            for(int j=1;j<i;j++)

            {

                if(i%j==0)

                {

                    k += j;

                }

            }

            if(i==k)

            {

                *p = k;

                p++;

                len++;

            }

        }

        join_ints(p-len,len,”,”);

        printf(“\n”);

    }

    return 0;

}

验证与结论:完全正确

总结与心得体会:for、if的使用

实验题目3:猴子吃桃问题

【问题描述】

猴子第一天摘下若干个桃子,当即就吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃一个。以后每天早上都吃了前一天剩下的一半多一个。到第10天早上想再吃时,发现只剩下一个桃子了。求第一天共摘多少个桃子?

【输入形式】

【输出形式】

输出一个整数,表示第一天所摘桃子的数量


【评分标准】

正确性

设计思想:for循环

实验代码及注释:

#include<stdio.h>

int main()

{

    int days = 10,n = 1;

    for(int i=1;i<days;i++)

    {

        n = (n+1)*2;

    }

    printf(“%d\n”,n);

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了for循环的使用

实验题目4:计算乘方和

【问题描述】

从键盘为整型变量a赋值,如果a的值为闭区间[3,10]之间的整数,则计算并输出a4+(a+3)4+(a+6)4+(a+9)4+(a+12)4+(a+15)4的值;否则输出“error”。

【输入形式】

按题意

【输出形式】

按题意

【样例输入】

3

【样例输出】

184275

【样例说明】

【评分标准】

正确性

设计思想:简单的乘方计算

实验代码及注释:

#include <stdio.h>

#include <math.h>

int main()

{

    int a,b;

    scanf(“%d”, &a);

    if(a>=3 && a<=10)

    {

        b = pow(a,4) + pow(a+3,4) +pow(a+6,4) + pow(a+9,4) + pow(a+12,4) + pow(a+15,4);

        printf(“%d\n”, b);

    }

    else

    {

        printf(“error”);

    }

    return 0;

}

验证与结论:完全正确

总结与心得体会:简单的乘方计算

实验题目5:偶数之和

【问题描述】

输入8个整数,求其中所有偶数的和。

【输入形式】

输入8个整数,每两个整数之间均以空格分隔

【输出形式】

输出1个整数

【样例输入】

1 -2 2 3 5 8 10 4

【样例输出】

22

【样例说明】

【评分标准】

正确性

设计思想:遍历数组,判断偶数求和

实验代码及注释:

#include <stdio.h>

#include <math.h>

int main()

{

    int a[8], res=0;

    scanf(“%d%d%d%d%d%d%d%d”, &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7]);

    for(int i=0;i<8;i++)

    {

        if(a[i]%2==0)

            res += a[i];

    }

    printf(“%d\n”, res);

    return 0;

}

验证与结论:完全正确

总结与心得体会:偶数的判断

实验四:函数

实验题目1:闰年问题

【问题描述】

定义一个带参数的宏,以判别某个年份是否为闰年。其中年份year应从键盘输入。

【源文件名】

ex406.c

【输入形式】

输入一个整数,为年份

【输出形式】

输出所输入的年份是或不是闰年,请参见样例输出

【样例输入】

1990

【样例输出】

1990 is not a leap year

【样例说明】

【样例输入】

2000

【样例输出】

2000 is a leap year

【样例说明】

【评分标准】

设计思想:宏定义判断闰年

实验代码及注释:

#include <stdio.h>

#define if_leap(year) year%400==0 || (year%4==0 && year%100!=0)? printf(“%d is a leap year\n”,year) : printf(“%d is not a leap year\n”,year)

int main()

{

    int year;

    scanf(“%d”, &year);

    if_leap(year);

    return 0;

}

验证与结论:完全正确

总结与心得体会:宏的定义

实验题目2:求解勒让德多项式

【问题描述】

使用递归方法求n阶勒让德多项式的值,递归公式为:

其中:n和x为int型;Pn(x)为float型。


【源文件名】

ex405.c

【输入形式】

先后从键盘输入n和x,用逗号分隔

【输出形式】

若n小于0,则输出“error”。若n大于等于0,则输出Pn(x),保留小数点后两位

【样例输入】

-1,3

【样例输出】

error

【样例说明】

【样例输入】

2,-3

【样例输出】

-3.50

【样例说明】

【评分标准】

设计思想:递归

实验代码及注释:

#include <stdio.h>

float P(int n,int x)

{

    float res;

    if(n == 0)

    {

        res = 1;

    }

    else if(n == 1)

    {

        res = x;

    }

    else if(n > 1)

    {

        res = ((2*n-1)*x – P(n-1,x) – (n-1)*P(n-2,x))/n;

    }

    return res;

}

int main()

{

    int n, x;

    scanf(“%d,%d”, &n, &x);

    if(n < 0)

        printf(“error\n”);

    else

        printf(“%.2f\n”, P(n,x));

}

验证与结论:完全正确

总结与心得体会:递归

实验题目3:储蓄账户余额计算器

【问题描述】

假设你每月在储蓄账户上存100元,年利率是5%,则每月的利率是0.05/12=0.00417。

第一个月后,账户上的值变成100×(1+0.00417)=100.417;

第二个月后,账户上的值变成(100+100.417)×(1+0.00417)=201.252;

第三个月后,账户上的值变成(100+201.252)×(1+0.00417)=302.507;

以此类推。

写一个函数,根据用户输入的每月存款数、年利率和月份数,计算给定月份后账户上的钱数并输出。


【源文件名】

ex404.c

【输入形式】

输入每月存款数、年利率、月份数,每两个数据之间用逗号分隔

【输出形式】

月末账户本息余额(保留小数点后两位)

【样例输入】

100,0.05,3

【样例输出】

302.51

【样例说明】

【评分标准】

设计思想:函数,循环

实验代码及注释:

#include<stdio.h>

double money(double a, double b, int c)

{

    double res = 0;

    for(int i=0;i<c;++i)

    {

        res = (a + res) * (1 + (b/12));

    }

    return res;

}

int main()

{

    double ammount, rate;

    int month;

    scanf(“%lf,%lf,%d”, &ammount, &rate, &month);

    printf(“%.2lf\n”, money(ammount, rate, month));

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了函数、循环

实验题目4:寻找回文数

【问题描述】

所谓回文数就是将一个数从左向右读与从右向左读是一样的,例如,121和1331都是回文数。编写一个函数实现求正整数n以内的回文数。

【源文件名】

ex403.c

【输入形式】

输入一个正整数,为n的值

【输出形式】

每行输出10个回文数,每两个回文数之间用逗号分隔

【样例输入】

150

【样例输出】

0,1,2,3,4,5,6,7,8,9,

11,22,33,44,55,66,77,88,99,101,

111,121,131,141,

【样例说明】

【评分标准】

设计思想:判断回文数

实验代码及注释:

#include<stdio.h>

void FindPalindromeNum(int x)

{

    int s[10000], len, n, count = 0, flag;

    for(int i=0;i<=x;i++)

    {

        len = 0, n = i, flag = 0;

        while(n!=0)                                          //位数

        {

            n /= 10;

            ++len;

        }

        n = i;

        for(int k=0;k<len;k++)                              //各位数写进数组

        {

            s[k] = n % 10;

            n /= 10;

        }

        for(int j=0;j<len/2;j++)                            //判断是否回文

        {

            flag = 0;

            if(s[j] == s[len-1-j])

            {  

                flag = 1;

            }

            else

            {

                flag = 0;

                break;

            }

        }

        if(flag==1 || i<10)

        {

            printf(“%d,”,i);

            ++count;

        }

        while(count%10==0)

        {

            printf(“\n”);

            break;

        }

    }

}

int main()

{

    int x;

    scanf(“%d”, &x);

    FindPalindromeNum(x);

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了判断回文数

实验题目5:寻找双质数

【问题描述】

所谓“双质数”是指对于两个质数p和q,如果满足p = q + 2,则p和q为双质数。请编程实现利用函数求解闭区间[m, n]之间的双质数,其中m和n均为正整数且m < n。

【源文件名】

ex402.c

【输入形式】

从键盘先后输入两个正整数(分别为m和n),用逗号分隔

【输出形式】

每行输出一对双质数,用逗号分隔。若有多对双质数,则分多行输出

【样例输入】

3,100

【样例输出】

3,5

5,7

11,13

17,19

29,31

41,43

59,61

71,73

【样例说明】

【评分标准】

设计思想:for遍历

实验代码及注释:

#include<stdio.h>

void FindDouble(int m, int n)

{

    int temp, p, q;

    if(m>n)

    {    

        temp = m; m = n ; n = temp;

    }

    for(int q = m, p = m+2;p<=n;p++,q++)

    {

        int flag1 = 0, flag2 = 0;

        for(int j=2;j<p;j++)

        {

            if(p%j==0)

                flag1 = 1;

        }

        for(int j=2;j<q;j++)

        {

            if(q%j==0)

                flag2 = 1;

        }

        if(flag1 == 0 && flag2 == 0)

        {

            printf(“%d,%d\n”, q, p);

        }

    }

}

int main()

{

    int m, n;

    scanf(“%d,%d”, &m, &n);

    FindDouble(m,n);

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了寻找双质数

实验题目6:数列前n项和

【问题描述】

写一个函数,求解以下数列前n项之和并输出,其中n(正整数)应从键盘输入。


【源文件名】

ex401.c

【输入形式】

输入一个正整数(int型),表示数列的项数

【输出形式】

输出一个实数(float型),保留小数点后两位

【样例输入】

3

【样例输出】

5.17

【样例说明】

【评分标准】

设计思想:斐波那契数列

实验代码及注释:

#include<stdio.h>

int Fibonacci(int n)//输出斐波那契第n项

{

    int a[n];

    a[0] = 1;

    a[1] = 1;

    for(int i=2;i<n;i++)

    {

        a[i] = a[i-1] + a[i-2];

    }

    return a[n-1];

}

float SumSequence(int n)//计算前n项和

{

    float sum = 0, x, y;

    for(int i=1;i<=n;i++)

    {

       x = Fibonacci(i+2); y = Fibonacci(i+1);

       sum += x/y;

    }

    return sum;

}

int main()

{  

    int n;

    scanf(“%d”, &n);

    printf(“%.2f\n”, SumSequence(n));

    return 0;

}

验证与结论:完全正确

总结与心得体会:数列前n项和

哈尔滨工程大学

《计算思维二》实验报告

基础实践二

姓    名:        班    级:       

学    号:                                 

实验时间:     2022    年     4       月     23      日

成绩 

哈尔滨工程大学计算机基础课程教学中心

实验五:数组

实验题目1:数组元素遍历

【问题描述】

输入一个整型数组a[10],并计算其中的前9个元素的平均值,然后将这个值替换a[9]中的内容,最后输出该数组的所有元素。

【输入形式】

从键盘先后输入数组元素值,每两个值之间用空格分隔

【输出形式】

在一行内输出数组的所有元素值,每两个值之间用逗号分隔

【样例输入】

0 1 2 3 4 5 6 7 8 9

【样例输出】

0,1,2,3,4,5,6,7,8,4

【样例说明】


【评分标准】

正确性

设计思想:for遍历数组

实验代码及注释:

#include<stdio.h>

int main()

{

    int a[10], total = 0;

    scanf(“%d%d%d%d%d%d%d%d%d%d”, &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9]);

    for(int i=0;i<9;i++)

    {

        total += a[i];

    }

    a[9] = total/9;

    for(int i=0;i<10;i++)

    {

        printf(“%d”,a[i]);

        if(i != 9)

            printf(“,”);

    }

    printf(“\n”);

    return 0;

}

验证与结论:完全正确

总结与心得体会:for遍历数组

实验题目2:寻找子串

【问题描述】

有两个字符串str1和str2,它们的长度都不超过100个字符。请编程实现在str1中查找str2的初始位置。

【输入形式】

有两行输入,第一行输入字串str1,第二行输入字串str2

【输出形式】

一个整数。若该整数为正整数,则表示str2在str1中的初始位置。若该整数为-1,则表示str2中在str1不存在,或者str2的长度大于str1的长度

【样例输入】

Hello World!

o

【样例输出】

5

【样例输入】

How are you!

habin

【样例输出】

-1

【样例输入】

Hello World!

Hello World! I love you!

【样例输出】

-1

【样例说明】

【评分标准】

正确性

设计思想:查找字串

实验代码及注释:

#include<stdio.h>

#include<string.h>

int  main(void)

{

    char s1[100];

    char s2[100];

    int i,j;

    scanf(“%[^\n]%*c”, s1);scanf(“%[^\n]%*c”, s2);

    if(strlen(s1)<strlen(s2))printf(“-1”);

    else

    {

        char*str;

        str=strstr(s1,s2);

        if(str)

        {

            for(i=0; i<strlen(s1); i++)

            {

                if(s1[i]==s2[0])

                {

                    printf(“%d”,i+1);

                    break;

                }

            }

        }

        else printf(“-1”);

    }

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了查找子串

实验题目3:字串处理

【问题描述】

现有两个字符串s1和s2,它们最多都只能包含255个字符。编写程序,将字符串s1中所有出现在字符串s2中的字符删去,然后输出s1。

【输入形式】

有两行输入。第一行输入为字符串s1,第二行输入为字符串s2

【输出形式】

输出被处理过的字符串s1

【样例输入】

I love you!8767%$#&*Yeah

o7W$hB*

【样例输出】

I lve yu!86%#&Yea

【样例说明】

【评分标准】

正确性

设计思想:指针遍历字符串

实验代码及注释:

#include<stdio.h>

int main()

{

    char s1[255], s2[255], *p, *q;

    int num = 0;

    scanf(“%[^\n]%*c”, s1);

    scanf(“%[^\n]%*c”, s2);

    p = s1; q = s2;

    for(;*q != ‘\0’;q++)

    {

        num++;

    }

    q = s2;

    for(int k=0;k<num;k++)

    {

        p = s1;

        for(int i=0;*p != ‘\0’;p++,i++)

        {

            if(*p == *q)

            {

                for(int j=i;s1[j] != ‘\0’;j++)

                {

                    s1[j] = s1[j+1];

                }

            }

        }

        q++;

    }

    printf(“%s\n”, s1);

    return 0;

}

验证与结论:完全正确

总结与心得体会:指针遍历字符串

实验题目4:填充矩阵

【问题描述】

编程实现自动填充n×n矩阵元素数值,填充规则为:从第一行最后一列矩阵元素开始按逆时针方向螺旋式填充数值1,2,…,n×n,其中:n从键盘输入且3≤n≤20。最后向显示器输出该矩阵所有元素。

【输入形式】

输入一个正整数,为矩阵的行数和列数

【输出形式】

按行列顺序输出n×n矩阵的所有元素。

(1)每行n列矩阵元素均需在一行内输出显示

(2)输出每行矩阵元素后均需换行输出下一行,共输出n行

(3)每个矩阵元素数值的域宽均为4位且右对齐

【样例输入】

11

【样例输出】

  11  10   9   8   7   6   5   4   3   2   1

  12  49  48  47  46  45  44  43  42  41  40

  13  50  79  78  77  76  75  74  73  72  39

  14  51  80 101 100  99  98  97  96  71  38

  15  52  81 102 115 114 113 112  95  70  37

  16  53  82 103 116 121 120 111  94  69  36

  17  54  83 104 117 118 119 110  93  68  35

  18  55  84 105 106 107 108 109  92  67  34

  19  56  85  86  87  88  89  90  91  66  33

  20  57  58  59  60  61  62  63  64  65  32

  21  22  23  24  25  26  27  28  29  30  31

【样例说明】

在样例输出中,对于数值域宽的控制,请参见教材中关于printf函数的格式控制(教材P54表3-7)。输入和输出的格式控制效果如下图所示,请以此图为标准设计程序的输入和输出格式。

【评分标准】

正确性

设计思想:填充矩阵

实验代码及注释:

#include<stdio.h>

void Visit(int a[][400],int n)

{

    int p=n-1,q=0,i;

    int count=0;

    while(count<n*n)  

    {

        for(i=p;i>=q;i–)

            {a[q][i]=count+1;

            count+=1;}

        for(i=q+1;i<=p;i++)

            {a[i][q]=count+1;

            count+=1;}

        for(i=q+1;i<=p;i++)

            {a[p][i]=count+1;

            count+=1;}

        for(i=p-1;i>=q+1;i–)

            {a[i][p]=count+1;

            count+=1;}

            p–;

            q++;

    }

}

void Print(int a[][400],int n)

{  

int h,j;

    for(h=0;h<n;h++)

    {

        for(j=0;j<n;j++)

        {

printf(“%3d “,a[h][j]);}

             printf(“\n”);

        }

}

int main()

{

    int n,a[400][400];

    scanf(“%d”,&n);

    Visit(a,n);

    Print(a,n);

    return 0;

}

验证与结论:完全正确 

总结与心得体会:学会了填充矩阵

实验题目5:数组合并与排序

【问题描述】

输入两个整数数组,每个数组有5个整数,将二者进行合并,然后按照数值从小到大排序输出。

【输入形式】

有两行输入,分别为第一个数组和第二个数组的元素赋值。每行输入中的每两个数值之间用空格分隔

【输出形式】

有两行输出,第一行输出为合并之后的数组元素值,第二行输出为排序后的数组元素值。每行输出中的每两个数值之间用逗号分隔

【样例输入】

9 1 5 3 7

8 0 6 4 2

【样例输出】

9, 1, 5, 3, 7, 8, 0, 6, 4, 2

0, 1, 2, 3, 4, 5, 6, 7, 8, 9

【样例说明】

【评分标准】

正确性

设计思想:将不同的数合并到第一个数组

实验代码及注释:

#include<stdio.h>

int main()

{

    int s1[5], s2[5], s[10];

    scanf(“%d%d%d%d%d”, &s1[0], &s1[1], &s1[2], &s1[3], &s1[4]);

    scanf(“%d%d%d%d%d”, &s2[0], &s2[1], &s2[2], &s2[3], &s2[4]);

    for(int i=0;i<5;i++)

    {

        s[i] = s1[i];

    }

    for(int i=5;i<10;i++)

    {

        s[i] = s2[i-5];

    }

    for(int i=0;i<10;i++)

    {

        printf(“%d”,s[i]);

        if(i != 9)

            printf(“,”);

    }

    printf(“\n”);

    int temp;

    for(int i=0;i<9;i++)

    {

        for(int j=0;j<9;j++)

        {

            if(s[j]>s[j+1])

            {

                temp = s[j];

                s[j] = s[j+1];

                s[j+1] = temp;

            }

        }

    }

    for(int i=0;i<10;i++)

    {

        printf(“%d”,s[i]);

        if(i != 9)

            printf(“,”);

    }

    printf(“\n”);

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了数组合并与排序

实验六:指针

实验题目1:单词排序

【问题描述】

编程实现从键盘输入5个英文单词(每个单词不超过20个字母),然后将它们按照字典序(即字母从小到大的顺序)排序后打印输出。要求:编写assign函数、sort函数、show函数,分别用于实现单词的键盘输入、单词的排序、单词的输出。目前,已完成main函数的编写,请编写assign、sort和show函数,对这三个函数的定义及要求如下所示。

#include <stdio.h>#include <string.h>#define ROWS 5#define COLUMNS 20/*@Filename: ex603.c@Author: @Version: 1.0@Date: 2021-03-18@Description: Sort Words@Features: 基于字符数组指针(行指针)实现*/ /* * 函数名称:assign * 函数功能:通过键盘输入为多个一维字符数组(字串)赋值 * 形式参数:arr为一维字符数组指针(行指针);rows为int型,单词字串个数 * 返 回 值:无 */void assign(char (*arr)[COLUMNS], int rows){// 请编码实现assign函数 } /* * 函数名称:show * 函数功能:输出显示所有单词(字串) * 形式参数:arr为一维字符数组指针(行指针);rows为int型,单词字串个数 * 返 回 值:无 */void show(char (*arr)[COLUMNS], int rows){// 请编码实现show函数 } /* * 函数名称:sort * 函数功能:对多个一维字符数组(字串)进行排序 * 形式参数:arr为一维字符数组指针(行指针);rows为int型,单词字串个数 * 返 回 值:无 */void sort(char(*arr)[COLUMNS], int rows){// 请编码实现sort函数 } int main(void){//ch为二维字符数组,包含ROWS个单词,每个单词最多COLUMNS个字母char ch[ROWS][COLUMNS];memset(ch,0,sizeof(ch)); //p是一个指向字符数组的指针,称为行指针,请参见教材Page189//必须给p指定长度,否则编译不报错,运行也不报错,但会不正常//p与ch等价,因此既可引用p,也可引用chchar (*p)[COLUMNS] = ch; //从键盘输入ROWS个单词,为ch赋值assign(p, ROWS); //对ch中的ROWS个单词进行排序sort(p, ROWS); //输出显示单词排序结果show(p, ROWS); return 0;}

注:

(1)在assign、sort、show这三个函数中是使用一维字符数组指针(行指针)对多个单词(字串)进行逐一处理的。

(2)请注意区分“字符数组指针(行指针)”与“字符指针数组”的不同。

● “字符数组指针(行指针)”:请参见教材P189

● “字符指针数组”:请参见教材P195。另需注意,在教材P197页的【例7-21】中,是使用“字符指针数组”进行字串处理的,而上述三个函数则是使用“行指针”。

【输入形式】

输入5个英文单词(字符串),每行输入一个单词

【输出形式】

输出排序结果,每行输出一个单词

【样例输入】

sunshine

china

english

worth

believe

【样例输出】

believe

china

english

sunshine

worth

【样例说明】

输入和输出的实际效果如下图所示。

【评分标准】

正确性

设计思想:单词排序

实验代码及注释:

#include <stdio.h>

#include <string.h>

#define ROWS 5

#define COLUMNS 20

/*

@Filename: ex603.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Sort Words

@Features: 基于字符数组指针(行指针)实现

*/

/*

 * 函数名称:assign

 * 函数功能:通过键盘输入为多个一维字符数组(字串)赋值

 * 形式参数:arr为一维字符数组指针(行指针);rows为int型,单词字串个数

 * 返 回 值:无

 */

void assign(char (*arr)[COLUMNS], int rows){

    // 请编码实现assign函数

    for(int i = 0; i < rows; i++)

        {

            scanf(“%s”, arr+i);

        }

}

/*

 * 函数名称:show

 * 函数功能:输出显示所有单词(字串)

 * 形式参数:arr为一维字符数组指针(行指针);rows为int型,单词字串个数

 * 返 回 值:无

 */

void show(char (*arr)[COLUMNS], int rows){

    // 请编码实现show函数

    for(int i = 0; i < rows; i++)

        {

            printf(“%s\n”, arr+i);

        }

}

/*

 * 函数名称:sort

 * 函数功能:对多个一维字符数组(字串)进行排序

 * 形式参数:arr为一维字符数组指针(行指针);rows为int型,单词字串个数

 * 返 回 值:无

 */

void sort(char(*arr)[COLUMNS], int rows){

    // 请编码实现sort函数

    char temp[20];

        for(int i = 0; i < rows – 1; i++)

        {

            for(int j = 0; j < rows – 1; j++)

            {

                if(strcmp(*(arr+j),*(arr+j+1)) > 0)

                {

                    strcpy(temp,*(arr+j));

                    strcpy(*(arr+j),*(arr+j+1));

                    strcpy(*(arr+j+1),temp);

                }

            }

        }

}

int main(void){

    //ch为二维字符数组,包含ROWS个单词,每个单词最多COLUMNS个字母

    char ch[ROWS][COLUMNS];

    //p是一个指向字符数组的指针,称为行指针,请参见教材Page189

    //必须给p指定长度,否则编译不报错,运行也不报错,但会不正常

    //p与ch等价,因此既可引用p,也可引用ch

    char (*p)[COLUMNS] = ch;

    //从键盘输入ROWS个单词,为ch赋值

    assign(p, ROWS);

    //对ch中的ROWS个单词进行排序

    sort(p, ROWS);

    //输出显示单词排序结果

    show(p, ROWS);

    return 0;

}

验证与结论:完全正确

总结与心得体会:学会了利用指针进行单词排序

实验题目2:数字与月份

【问题描述】

输入一个三位数,计算该数各位上的数字之和,如果在[1, 12]之内,则输出与数字之和相对应的月份的英文单词,否则输出***。要求:用指针数组记录各月份英文单词的首地址,且不得使用全局变量。目前仅完成了main函数和bizProcess函数,请编程实现hundredsDigit函数、tensDigit函数、unitsDigit函数、searchMonth函数和getNumber函数。

#include <stdio.h> /*@Filename: ex604.c@Author: @Version: 1.0@Date: 2021-03-18@Description: Number to Month*/ /* * 函数名称:hundredsDigit * 函数功能:获取形参整数位于百位上的数字 * 形式参数:num,一个整型数 * 返 回 值:返回形参整数位于百位上的数字 */static int hundredsDigit(int num){// 请编程实现本函数 } /* * 函数名称:tensDigit * 函数功能:获取形参整数位于十位上的数字 * 形式参数:num,一个整型数 * 返 回 值:返回形参整数位于十位上的数字 */static int tensDigit(int num){// 请编程实现本函数 } /* * 函数名称:unitsDigit * 函数功能:获取形参整数位于个位上的数字 * 形式参数:num,一个整型数 * 返 回 值:返回形参整数位于个位上的数字 */static int unitsDigit(int num){// 请编程实现本函数 } /* * 函数名称:searchMonth * 函数功能:对num进行判断,若1≤num≤12,返回month[num];否则返回month[0] * 形式参数:month,为表示月份单词的字符指针数组 *           num,为一个整数 * 返 回 值:字符指针,为月份单词的首地址 */static char *searchMonth(char *month[], int num){// 请编程实现本函数 } /* * 函数名称:getNumber * 函数功能:从键盘输入一个三位正整数,若不符合要求,则重新输入 * 形式参数:无 * 返 回 值:返回所输入的三位正整数 */int getNumber(){// 请编程实现本函数 } /* * 函数名称:bizProcess * 函数功能:业务处理函数,功能定义如下。 *  (1)调用hundredsDigit等函数,对一个三位数的各位进行拆分并计算数字和 *  (2)调用searchMonth函数,对上述数字和进行检索返回其月份单词 *  (3)按题目要求的格式,打印输出上述结果 * 形式参数:month,为一个指针数组,指向月份单词的字串数组 *           num,一个整数 * 返 回 值:无 */void bizProcess(char *month[], int num){int unitsD, tensD, hundredsD, sum;unitsD = unitsDigit(num);tensD = tensDigit(num);hundredsD = hundredsDigit(num);sum = unitsD + tensD+hundredsD; printf(“%s”,searchMonth(month, sum));} int main(void){/*定义数据结构*/char *month[]={“***”,”January”, “February”, “March”,”April”, “May”, “June”,”July”, “August”, “September”,”October”, “November”, “December”};/*获取一个三位正整数*/int number = getNumber();/*业务逻辑判断处理*/bizProcess(month, number); return 1;}

注:应耐心研读各函数模块功能及其逻辑关系。

【输入形式】

输入一个三位正整数

【输出形式】

月份英文单词或***

【样例输入】

520

【样例输出】

July

【样例输入】

999

【样例输出】

***

【样例说明】

【评分标准】

正确性

设计思想:指针

实验代码及注释:

#include <stdio.h>

/*

@Filename: ex604.c

@Author:

@Version: 1.0

@Date: 2021-03-18

@Description: Number to Month

*/

/*

 * 函数名称:hundredsDigit

 * 函数功能:获取形参整数位于百位上的数字

 * 形式参数:num,一个整型数

 * 返 回 值:返回形参整数位于百位上的数字

 */

static int hundredsDigit(int num){

    // 请编程实现本函数

    return num / 100;

}

/*

 * 函数名称:tensDigit

 * 函数功能:获取形参整数位于十位上的数字

 * 形式参数:num,一个整型数

 * 返 回 值:返回形参整数位于十位上的数字

 */

static int tensDigit(int num){

    // 请编程实现本函数

    return (num – (num/100)*100)/10;

}

/*

 * 函数名称:unitsDigit

 * 函数功能:获取形参整数位于个位上的数字

 * 形式参数:num,一个整型数

 * 返 回 值:返回形参整数位于个位上的数字

 */

static int unitsDigit(int num){

    // 请编程实现本函数

    return num%10;

}

/*

 * 函数名称:searchMonth

 * 函数功能:对num进行判断,若1≤num≤12,返回month[num];否则返回month[0]

 * 形式参数:month,为表示月份单词的字符指针数组

 *           num,为一个整数

 * 返 回 值:字符指针,为月份单词的首地址

 */

static char *searchMonth(char *month[], int num){

    // 请编程实现本函数

    if(num >= 1 && num <=12)

        return month[num];

    else

        return month[0];

}

/*

 * 函数名称:getNumber

 * 函数功能:从键盘输入一个三位正整数,若不符合要求,则重新输入

 * 形式参数:无

 * 返 回 值:返回所输入的三位正整数

 */

int getNumber(){

    // 请编程实现本函数

    int num;

        scanf(“%d”, &num);

        return num;

}

/*

 * 函数名称:bizProcess

 * 函数功能:业务处理函数,功能定义如下。

 *  (1)调用hundredsDigit等函数,对一个三位数的各位进行拆分并计算数字和

 *  (2)调用searchMonth函数,对上述数字和进行检索返回其月份单词

 *  (3)按题目要求的格式,打印输出上述结果

 * 形式参数:month,为一个指针数组,指向月份单词的字串数组

 *           num,一个整数

 * 返 回 值:无

 */

void bizProcess(char *month[], int num){

    int unitsD, tensD, hundredsD, sum;

    unitsD = unitsDigit(num);

    tensD = tensDigit(num);

    hundredsD = hundredsDigit(num);

    sum = unitsD + tensD+hundredsD;

    printf(“%s”,searchMonth(month, sum));

}

int main(void){

    /*定义数据结构*/

    char *month[]=

        {

            “***”,

            “January”, “February”, “March”,

            “April”, “May”, “June”,

            “July”, “August”, “September”,

            “October”, “November”, “December”

        };

    /*获取一个三位正整数*/

    int number = getNumber();

    /*业务逻辑判断处理*/

    bizProcess(month, number);

    return 1;

}

验证与结论:完全正确

总结与心得体会:学会了对指针的操作

实验题目3:指针形参及函数指针应用

【问题描述】

任意输入两个整数,编写三个函数分别实现:(1)计算两个数的加法和;(2)计算两个整数的减法差;(3)交换这两个整数的数值。要求用“函数指针”调用这三个函数,结果在主函数中输出。目前已编写完成main函数,请编程实现sum函数、minus函数和swap函数,函数功能和要求如下所示。

/*@Filename: ex601.c@Author: @Version: 1.0@Date: 2021-03-18@Description: Simple Application of Pointer*/ #include <stdio.h> /*主函数*/int main(void){int sum(int *a, int *b);int minus(int *a, int *b);void swap(int *a, int *b); int a, b;int *pa = &a, *pb = &b;scanf(“%d,%d”, &a, &b); int (*p)(int *, int *);p = sum;printf(“%d”, (*p)(pa, pb));p = minus;printf(“\n%d”, (*p)(pa, pb)); void (*q)(int *,int *);q = swap;(*q)(pa, pb); printf(“\n%d,%d”, a, b); return 1;} /* * 函数名称:sum * 函数功能:对两个整数进行加法计算 * 形式参数:a,整型指针 * 形式参数:b,整型指针 * 返 回 值:int型,为两个整数的加法和 */int sum(int *a, int *b){//请编程实现本函数 } /* * 函数名称:minus * 函数功能:对两个整数进行减法计算 * 形式参数:a,整型指针 * 形式参数:b,整型指针 * 返 回 值:int型,为两个整数的减法差 */int minus(int *a, int *b){//请编程实现本函数 } /* * 函数名称:swap * 函数功能:交换两个整数数值 * 形式参数:a,整型指针 * 形式参数:b,整型指针 * 返 回 值:无 */void swap(int *a, int *b){//请编程实现本函数 }

注:不得使用全局变量。

【输入形式】

输入两个整数,用逗号分隔

【输出形式】

有三行输出,分别为:

第1行:输出两个整数的加法和

第2行:输出两个整数的减法差

第3行:输出两个整数交换数值后的结果,用逗号分隔

【样例输入】

10,20

【样例输出】

30

-10

20,10

【样例说明】

【评分标准】

正确性

设计思想:指针形参及函数指针应用

实验代码及注释:

/*

@Filename: ex601.c

@Author:

@Version: 1.0

@Date: 2021-03-18

@Description: Simple Application of Pointer

*/

#include <stdio.h>

/*主函数*/

int main(void){

    int sum(int *a, int *b);

    int minus(int *a, int *b);

    void swap(int *a, int *b);

    int a, b;

    int *pa = &a, *pb = &b;

    scanf(“%d,%d”, &a, &b);

    int (*p)(int *, int *);

    p = sum;

    printf(“%d”, (*p)(pa, pb));

    p = minus;

    printf(“\n%d”, (*p)(pa, pb));

    void (*q)(int *,int *);

    q = swap;

    (*q)(pa, pb);

    printf(“\n%d,%d”, a, b);

    return 1;

}

/*

 * 函数名称:sum

 * 函数功能:对两个整数进行加法计算

 * 形式参数:a,整型指针

 * 形式参数:b,整型指针

 * 返 回 值:int型,为两个整数的加法和

 */

int sum(int *a, int *b){

    //请编程实现本函数

    return *a + *b;

}

/*

 * 函数名称:minus

 * 函数功能:对两个整数进行减法计算

 * 形式参数:a,整型指针

 * 形式参数:b,整型指针

 * 返 回 值:int型,为两个整数的减法差

 */

int minus(int *a, int *b){

    //请编程实现本函数

    return *a – *b;

}

/*

 * 函数名称:swap

 * 函数功能:交换两个整数数值

 * 形式参数:a,整型指针

 * 形式参数:b,整型指针

 * 返 回 值:无

 */

void swap(int *a, int *b){

    //请编程实现本函数

    int temp;

        temp = *a;

        *a = *b;

        *b = temp;

}

验证与结论:完全正确

总结与心得体会:学会了指针形参及函数指针应用

实验题目4:指针作为函数参数

【问题描述】

一维整型数组a有5个元素,请编写assign函数和max函数分别实现为数组元素赋值和求解数组元素最大值。目前,除了assign和max这两个函数以外,其他代码已编写完成,如下所示。请编码实现上述两个函数。

#include <stdio.h> /*@Filename: ex602.c@Author: @Version: 1.0@Date: 2021-03-18@Description: Pointer As Function Parameter*/ int main(void){void assign(int *array, int length);int max(int *array, int length);int a[5];assign(a, 5); /* 为数组a元素赋值 */printf(“max=%d”,max(a, 5)); /* 求数组元素最大值并输出 */ return 0;} /* * 函数名称:assign * 函数功能:通过键盘输入为一维数组元素赋值 * 形式参数:array为int型指针;length为int型,可用于表示一维数组长度 * 返 回 值:无 */void assign(int *array,int length){// 请编码实现assign函数 } /* * 函数名称:max * 函数功能:求解一维数组元素最大值 * 形式参数:array为int型指针;length为int型,可用于表示一维数组长度 * 返 回 值:int型,为数组元素最大值 */int max(int *array,int length){// 请编码实现max函数 }

注:在程序中不得使用全局变量。

【输入形式】

在assign函数中,从键盘输入整型数据为数组元素赋值,用逗号分隔

【输出形式】

在main函数中,输出数组元素最大值,为整型数据

【样例输入】

-9 28 76 45 34

【样例输出】

max=76

【样例说明】

样例输入和输出的效果如下图所示。

【评分标准】

正确性

设计思想:指针作为函数参数

实验代码及注释:

#include <stdio.h>

/*

@Filename: ex602.c

@Author:

@Version: 1.0

@Date: 2021-03-18

@Description: Pointer As Function Parameter

*/

int main(void){

    void assign(int *array, int length);

    int max(int *array, int length);

    int a[5];

    assign(a, 5); /* 为数组a元素赋值 */

    printf(“max=%d”,max(a, 5)); /* 求数组元素最大值并输出 */

    return 0;

}

/*

 * 函数名称:assign

 * 函数功能:通过键盘输入为一维数组元素赋值

 * 形式参数:array为int型指针;length为int型,可用于表示一维数组长度

 * 返 回 值:无

 */

void assign(int *array,int length){

    // 请编码实现assign函数

    for(int i = 0; i<length; i++)

        {

            scanf(“%d”, array + i);

        }

}

/*

 * 函数名称:max

 * 函数功能:求解一维数组元素最大值

 * 形式参数:array为int型指针;length为int型,可用于表示一维数组长度

 * 返 回 值:int型,为数组元素最大值

 */

int max(int *array,int length){

    // 请编码实现max函数

    int temp;

        for(int i = 0; i < length – 1; i++)

        {

            for(int j = 0; j < length – 1; j++)

            {

                if(*(array + j) < *(array + j +1))

                {

                    temp = *(array + j);

                    *(array + j) = *(array + j + 1);

                    *(array + j + 1) = temp;

                }

            }

        }

        return *array;

}

验证与结论:完全正确

总结与心得体会:学会了指针作为函数参数

实验题目5:循环移动数组元素

【问题描述】

定义一个长度为10的一维整型数组,并编写三个函数分别实现如下功能:

(1)函数input:对数组的各元素实现从键盘输入赋值。

(2)函数output:将数组的所有元素向屏幕打印输出。

(3)函数moveToRight:向右循环移动数组元素

(4)函数moveToLeft:向左循环移动数组元素

(5)函数move:将数组元素向左或向右循环移动m个位置。移动规则为:

● 若m>0,调用moveToRight函数,执行向右循环移动;

● 若m=0,不做任何移动;

● 若m<0,调用moveToLeft函数,执行向左循环移动。

目前已编写完成main函数和move函数,请编程实现input函数、output函数、moveToRight函数和moveToLeft函数。

/*@Filename: ex605.c@Author: @Version: 1.0@Date: 2021-03-18@Description: Loopy Moving of Array Element*/#include <stdio.h>#include <stdlib.h>#define LENGTH 10/*主函数*/int main(void){/*声明函数*/void input(int *p, int n);void output(int *p, int n);void move(int *p, int length, int m); /*定义数据结构*/int a[LENGTH], m;//m表示数组元素循环移动的位置个数int *p = a; /*调用input函数,通过键盘输入为数组a赋值*/input(p, LENGTH); /*从键盘输入为循环移动位置个数m赋值*/scanf(“%d”, &m);/*调用move函数,完成数组元素的循环移动*/move(p, LENGTH, m); /*调用output函数,输出移动后的数组元素*/output(p, LENGTH);return 0;}/* * 函数名称:input * 函数功能:通过键盘输入为一维数组元素赋值 * 输入格式:各输入数据之间以空格分隔 * 形式参数:p,int型指针变量,一维整型数组首地址 * 形式参数:n,int型,一维数组长度 * 返回值:无 */void input(int *p, int n){// 请编程实现本函数 }/* * 函数名称:output * 函数功能:向屏幕打印输出一维数组元素值 * 输出格式:各输出数据之间以空格分隔 * 形式参数:p,int型指针变量,一维整型数组首地址 * 形式参数:n,int型,一维数组长度 * 返回值:无 */void output(int *p, int n){// 请编程实现本函数 } /* * 函数名称:moveToRight * 函数功能:使一维数组各元素向右循环移动m个位置 * 形式参数:p,int型指针变量,一维整型数组首地址 * 形式参数:length,int型,一维数组长度 * 形式参数:m,int型,循环移动的位置数 * 返 回 值:无 */void moveToRight(int *p, int length, int m){// 请编程实现本函数 } /* * 函数名称:moveToLeft * 函数功能:使一维数组各元素向左循环移动m个位置 * 形式参数:p,int型指针变量,一维整型数组首地址 * 形式参数:length,int型,一维数组长度 * 形式参数:m,int型,循环移动的位置数 * 返 回 值:无 */void moveToLeft(int *p, int length, int m){// 请编程实现本函数 } /* * 函数名称:move * 函数功能:使一维数组元素循环向左或向右移动m个位置 * 形式参数:p,int型指针变量,一维整型数组首地址 * 形式参数:length,int型,一维数组长度 * 形式参数:m,int型,表示循环移动的方向和移动的位置个数 *          当m>0时,执行向右循环移动(水平方向从左向右循环移动) *          当m=0时,不做任何移动 *          当m<0时,执行向左循环移动(水平方向从右向左循环移动) * 返 回 值:无 */void move(int *p, int length, int m){if(m > 0){/*向右循环移动*/moveToRight(p, length, m); }else if(m == 0){/*不移动*/; //空语句,什么都不做 }else{/*向左循环移动*/moveToLeft(p, length, m); }}

注:不得使用全局变量。

【输入形式】

有两行输入,第1行输入为数组元素赋值,第2行输入为m赋值

【输出形式】

有一行输出,输出循环移动后的数组各元素值

【样例输入】

1 2 3 4 5 6 7 8 9 10

3

【样例输出】

8 9 10 1 2 3 4 5 6 7

【样例输入】

1 2 3 4 5 6 7 8 9 10

-3

【样例输出】

4 5 6 7 8 9 10 1 2 3

【样例说明】

【评分标准】

正确性

设计思想:指针

实验代码及注释:

/*

@Filename: ex605.c

@Author:

@Version: 1.0

@Date: 2021-03-18

@Description: Loopy Moving of Array Element

*/

#include <stdio.h>

#include <stdlib.h>

#define LENGTH 10

/*主函数*/

int main(void){

    /*声明函数*/

    void input(int *p, int n);

    void output(int *p, int n);

    void move(int *p, int length, int m);

    /*定义数据结构*/

    int a[LENGTH], m;//m表示数组元素循环移动的位置个数

    int *p = a;

    /*调用input函数,通过键盘输入为数组a赋值*/

    input(p, LENGTH);

    /*从键盘输入为循环移动位置个数m赋值*/

    scanf(“%d”, &m);

    /*调用move函数,完成数组元素的循环移动*/

    move(p, LENGTH, m);

    /*调用output函数,输出移动后的数组元素*/

    output(p, LENGTH);

    return 0;

}

/*

 * 函数名称:input

 * 函数功能:通过键盘输入为一维数组元素赋值

 * 输入格式:各输入数据之间以空格分隔

 * 形式参数:p,int型指针变量,一维整型数组首地址

 * 形式参数:n,int型,一维数组长度

 * 返回值:无

 */

void input(int *p, int n){

    // 请编程实现本函数

    for(int i = 0; i < n; i++)

        {

            scanf(“%d”, p+i);

        }

}

/*

 * 函数名称:output

 * 函数功能:向屏幕打印输出一维数组元素值

 * 输出格式:各输出数据之间以空格分隔

 * 形式参数:p,int型指针变量,一维整型数组首地址

 * 形式参数:n,int型,一维数组长度

 * 返回值:无

 */

void output(int *p, int n){

    // 请编程实现本函数

    for(int i = 0; i<n; i++)

        {

            printf(“%d”, *(p+i));

            if(i != n-1)

            {

                printf(” “);

            }

        }

        printf(“\n”);

}

/*

 * 函数名称:moveToRight

 * 函数功能:使一维数组各元素向右循环移动m个位置

 * 形式参数:p,int型指针变量,一维整型数组首地址

 * 形式参数:length,int型,一维数组长度

 * 形式参数:m,int型,循环移动的位置数

 * 返 回 值:无

 */

void moveToRight(int *p, int length, int m){

    // 请编程实现本函数

    int temp;

        for(int i = 0; i < m; i++)

        {

            temp = *(p + length – 1);

            for(int j = 0; j < length; j++)

            {

                *(p + length – 1 -j) = *(p + length -j – 2);

            }

            *p = temp;

        }

}

/*

 * 函数名称:moveToLeft

 * 函数功能:使一维数组各元素向左循环移动m个位置

 * 形式参数:p,int型指针变量,一维整型数组首地址

 * 形式参数:length,int型,一维数组长度

 * 形式参数:m,int型,循环移动的位置数

 * 返 回 值:无

 */

void moveToLeft(int *p, int length, int m){

    // 请编程实现本函数

    int temp;

        for(int i = 0; i > m; i–)

        {

            temp = *p;

            for(int j = 0; j < length; j++)

            {

                *(p + j) = *(p + j + 1);

            }

            *(p + length -1) = temp;

        }

}

/*

 * 函数名称:move

 * 函数功能:使一维数组元素循环向左或向右移动m个位置

 * 形式参数:p,int型指针变量,一维整型数组首地址

 * 形式参数:length,int型,一维数组长度

 * 形式参数:m,int型,表示循环移动的方向和移动的位置个数

 *          当m>0时,执行向右循环移动(水平方向从左向右循环移动)

 *          当m=0时,不做任何移动

 *          当m<0时,执行向左循环移动(水平方向从右向左循环移动)

 * 返 回 值:无

 */

void move(int *p, int length, int m){

    if(m > 0){

        /*向右循环移动*/

        moveToRight(p, length, m);

    }else if(m == 0){

        /*不移动*/

        ; //空语句,什么都不做

    }else{

        /*向左循环移动*/

        moveToLeft(p, length, m);

    }

}

验证与结论:完全正确

总结与心得体会:学会了循环移动数组元素

实验七 结构体

实验题目1:反转单链表

【问题描述】

编程实现对一个单向链表的结点进行反转,也就是将链表结点按逆序排列,排序后链头将成为链尾,而链尾将成为链头。自定义函数名称及函数功能要求如下:

(1)定义“createNode”函数,实现创建一个新结点。

(2)定义“createList”函数,实现一个单向链表的创建。

● 在创建结点时通过键盘输入为每个结点的数据成员value进行赋值。

● 使用“头插法”将每个结点逐一插入到链表中。

(3)定义“display”的函数,实现对链表所有结点的遍历输出。

(4)定义“reverse”的函数,实现对链表结点的反转。

目前,已经编辑完成“createNode”函数、“createList”函数和“main”函数,请编程实现“display”函数和“reverse”函数。

/*@Filename: ex704.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: Reverse Single Linked List*/ #include <stdio.h>#include <stdlib.h> struct node{int value;struct node *next;}; int main(){/* 声明函数 */struct node *createList(int codeNum);struct node * reverse(struct node *pHead);void display(struct node *pHead); /* 生成新链表 */int num;scanf(“%d”,&num);struct node *pHead = createList(num); /* 输出链表结点(反转前) */printf(“\n”);display(pHead); /* 反转单链表*/pHead = reverse(pHead); /* 输出链表结点(反转后) */printf(“\n”);display(pHead);return 0;} /* * 函数名称:createList * 函数功能:使用头插法创建单链表,创建每个结点的同时为其value字段从键盘输入赋值 * 形式参数:int型,链表结点个数 * 返 回 值:返回struct node型指针,为单链表头结点 */struct node *createList(int codeNum){/* 声明函数 */struct node* createNode();/* 声明一个头结点 */struct node *pHead = NULL;/* * 生成单链表。有两种链表:空头链表和无空头链表 * 下面创建的是无空头链表 */int i;for(i = 1; i<=codeNum; i++){/* 创建新结点 */struct node *newNode = createNode();/* * 将新结点插入链表中,常用方式有:头插法、尾插法等。 * 头插法算法简单,但结点次序与输入数据的顺序不一致。 * 若希望两者次序一致,可采用尾插法。 * * 以下采用头插法 */newNode->next = pHead; /*将newNode指向上一步的头结点*/pHead = newNode; /*将newNode作为新的头结点*/}return pHead;} /* * 函数名称:createNode * 函数功能:创建一个新结点 * 形式参数:无 * 返 回 值:无 */struct node* createNode(){// 动态申请内存,创建新结点struct node *newNode = (struct node*)malloc(sizeof(struct node));if(newNode != NULL){// 为新结点的各字段赋值scanf(“%d”, &newNode->value);newNode->next = NULL; // 好习惯,不要让指针处于未赋值状态}return newNode;} /* * 函数名称:display * 函数功能:输出单链表所有结点的value字段值 * 输出格式:在一行内输出所有结点的value字段值,用空格分隔 * 形式参数:struct node型指针,为单链表头结点 * 返 回 值:无 */void display(struct node *pHead){// 请编程实现本函数 } /* * 函数名称:reverse * 函数功能:反转单链表 * 算法特点:可采用迭代算法、递归算法、尾递归算法等算法实现 * 形式参数:struct node型指针,为单链表头结点 * 返 回 值:返回struct node型指针,为反转后的单链表头结点 */struct node * reverse(struct node *pHead){// 请编程实现本函数 } 

【输入形式】

有2行输入。

第1行:输入链表结点个数

第2行:输入所有结点的value字段值,用空格分隔

【输出形式】

有2行输出。

第1行:输出反转前所有结点value值,用空格分隔

第2行:输出反转后所有结点value值,用空格分隔

【样例输入】

3

11 22 33

【样例输出】

33 22 11

11 22 33

【样例说明】

输入和输出格式效果如下图所示。

【评分标准】

正确性

设计思想:链表

实验代码及注释:

/*

@Filename: ex704.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Reverse Single Linked List

*/

#include <stdio.h>

#include <stdlib.h>

struct node{

    int value;

    struct node *next;

};

int main(){

    /* 声明函数 */

    struct node *createList(int codeNum);

    struct node * reverse(struct node *pHead);

    void display(struct node *pHead);

    /* 生成新链表 */

    int num;

    scanf(“%d”,&num);

    struct node *pHead = createList(num);

    /* 输出链表结点(反转前) */ 

    printf(“\n”);

    display(pHead);

    /* 反转单链表*/

    pHead = reverse(pHead);

    /* 输出链表结点(反转后) */

    printf(“\n”);

    display(pHead);

    return 0;

}

/*

 * 函数名称:createList

 * 函数功能:使用头插法创建单链表,创建每个结点的同时为其value字段从键盘输入赋值

 * 形式参数:int型,链表结点个数

 * 返 回 值:返回struct node型指针,为单链表头结点

 */

struct node *createList(int codeNum){

    /* 声明函数 */

    struct node* createNode();

    /* 声明一个头结点 */

    struct node *pHead = NULL;

    /*

     * 生成单链表。有两种链表:空头链表和无空头链表

     * 下面创建的是无空头链表

     */

    int i;

    for(i = 1; i<=codeNum; i++){

        /* 创建新结点 */

        struct node *newNode = createNode();

        /*

         * 将新结点插入链表中,常用方式有:头插法、尾插法等。

         * 头插法算法简单,但结点次序与输入数据的顺序不一致。

         * 若希望两者次序一致,可采用尾插法。

         *

         * 以下采用头插法

         */

        newNode->next = pHead; /*将newNode指向上一步的头结点*/

        pHead = newNode; /*将newNode作为新的头结点*/

    }

    return pHead;

}

/*

 * 函数名称:createNode

 * 函数功能:创建一个新结点

 * 形式参数:无

 * 返 回 值:无

 */

struct node* createNode(){

    // 动态申请内存,创建新结点

    struct node *newNode = (struct node*)malloc(sizeof(struct node));

    if(newNode != NULL){

        // 为新结点的各字段赋值

        scanf(“%d”, &newNode->value);

        newNode->next = NULL; // 好习惯,不要让指针处于未赋值状态

    }

    return newNode;

}

/*

 * 函数名称:display

 * 函数功能:输出单链表所有结点的value字段值

 * 输出格式:在一行内输出所有结点的value字段值,用空格分隔

 * 形式参数:struct node型指针,为单链表头结点

 * 返 回 值:无

 */

void display(struct node *pHead){

    // 请编程实现本函数

    struct node *temp;

        temp=pHead;

        while(temp!=NULL){

        printf(“%d “,temp->value);

        temp=temp->next;

        }

}

/*

 * 函数名称:reverse

 * 函数功能:反转单链表

 * 算法特点:可采用迭代算法、递归算法、尾递归算法等算法实现

 * 形式参数:struct node型指针,为单链表头结点

 * 返 回 值:返回struct node型指针,为反转后的单链表头结点

 */

struct node * reverse(struct node *pHead){

    // 请编程实现本函数

    struct  node  *temp;

        struct  node  *p;

        temp=pHead->next;

        if(temp->next!=NULL)

        {

        p=reverse(pHead->next);

        temp->next=pHead;

        pHead->next=NULL;

        return p;

        }

        else

        {

        temp->next=pHead;

        pHead->next=NULL;

        return temp;

        }

}

验证与结论:完全正确

总结与心得体会:学会了反转单链表

实验题目2:复数加减法运算器

【问题描述】

定义一个结构体类型,用于描述复数结构数据。分别编写函数实现复数的加法和减法运算,在主函数中调用这些函数进行计算并输出计算结果。目前已完成main函数的编写,请编程实现add函数和minus函数。具体要求如下所示。

/*@Filename: ex702.c@Author: @Version: 1.0@Date: 2021-03-18@Description: Complex Addition and Subtraction*/ #include <stdio.h> struct complex{int re; // real part(实部)int im; // imaginary part(虚部)}; int main(){struct complex add(struct complex a, struct complex b);struct complex minus(struct complex a, struct complex b); struct complex x, y, z;// 输入实数x的实部和虚部scanf(“%d,%d”, &x.re, &x.im);// 输入实数y的实部和虚部scanf(“%d,%d”, &y.re, &y.im); // 计算并输出复数加法和z = add(x, y);printf(“%d+%di\n”,z.re, z.im);// 计算并输出复数减法差z = minus(x, y);printf(“%d+%di”,z.re, z.im); return 0;} /* * 函数名称:add * 函数功能:实现复数加法运算 * 形式参数:struct complex a,操作数 * 形式参数:struct complex b,操作数 * 返 回 值:struct complex型,返回形参a和形参b的加法结果 */struct complex add(struct complex a, struct complex b){// 请编程实现本函数 } /* * 函数名称:minus * 函数功能:实现复数减法运算 * 形式参数:struct complex a,操作数 * 形式参数:struct complex b,操作数 * 返 回 值:struct complex型,返回形参a和形参b的减法结果 */struct complex minus(struct complex a, struct complex b){// 请编程实现本函数 } 

【输入形式】

输入有两行。

第1行输入两个整数,用逗号分隔,分别表示复数x的实部和虚部

第2行输入两个整数,用逗号分隔,分别表示复数y的实部和虚部

【输出形式】

输出有两行。

第1行输出复数x和复数y的加法和

第2行输出复数x和复数y的减法差

【样例输入】

3,6

4,5

【样例输出】

7+11i

-1+1i

【样例说明】

输入和输出格式效果如下图所示。

【样例输入】

-18,-27

-34,15

【样例输出】

-52+-12i

16+-42i

【样例说明】

输入和输出格式效果如下图所示。

【样例输入】

8,3

-2,3

【样例输出】

6+6i

10+0i

【样例说明】

输入和输出格式效果如下图所示。

【样例输入】

9,5

9,18

【样例输出】

18+23i

0+-13i

【样例说明】

输入和输出格式效果如下图所示。

【样例输入】

138,-236

138,-236

【样例输出】

276+-472i

0+0i

【样例说明】

输入和输出格式效果如下图所示。

【评分标准】

正确性

设计思想:复数加减运算器

实验代码及注释:

/*

@Filename: ex702.c

@Author:

@Version: 1.0

@Date: 2021-03-18

@Description: Complex Addition and Subtraction

*/

#include <stdio.h>

struct complex{

    int re; // real part(实部)

    int im; // imaginary part(虚部)

};

int main(){

    struct complex add(struct complex a, struct complex b);

    struct complex minus(struct complex a, struct complex b);

    struct complex x, y, z;

    // 输入实数x的实部和虚部

    scanf(“%d,%d”, &x.re, &x.im);

    // 输入实数y的实部和虚部

    scanf(“%d,%d”, &y.re, &y.im);

    // 计算并输出复数加法和

    z = add(x, y);

    printf(“%d+%di\n”,z.re, z.im);

    // 计算并输出复数减法差

    z = minus(x, y);

    printf(“%d+%di”,z.re, z.im);

    return 0;

}

/*

 * 函数名称:add

 * 函数功能:实现复数加法运算

 * 形式参数:struct complex a,操作数

 * 形式参数:struct complex b,操作数

 * 返 回 值:struct complex型,返回形参a和形参b的加法结果

 */

struct complex add(struct complex a, struct complex b){

    // 请编程实现本函数

        a.re=a.re+b.re;

        a.im=a.im+b.im;

        return a;

}

/*

 * 函数名称:minus

 * 函数功能:实现复数减法运算

 * 形式参数:struct complex a,操作数

 * 形式参数:struct complex b,操作数

 * 返 回 值:struct complex型,返回形参a和形参b的减法结果

 */

struct complex minus(struct complex a, struct complex b){

    // 请编程实现本函数

        a.re=a.re-b.re;

        a.im=a.im-b.im;

        return a;

}

验证与结论:完全正确

总结与心得体会:学会了复数加减运算器

实验题目3:简单的图书管理程序

【问题描述】

现有3本图书,每本图书的信息包括:书号、书名、作者、价格。

(1)编写input函数,实现从键盘输入若干本图书信息,存放在结构体数组中。

(2)编写output函数,遍历结构体数组,输出所有图书信息。

(3)编写findBookByID函数,实现按书号检索图书。

(4)编写findBookByName函数,实现按书名检索图书。

目前,已编写完成main函数、input函数和findBookByName函数,请编程实现output函数和findBookByID函数。程序结构及具体要求如下。

/*@Filename: ex703.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: Simple Library Management Program*/ #include <stdio.h>#include <string.h> typedef struct book{int id; // 书号char name[30]; // 书名char author[30]; //作者float price; //价格}BOOK; int main(){/* 声明函数 */void input(struct book *p, int num);void output(struct book *p, int num);struct book * findBookByID(struct book *p, int num, int id);struct book * findBookByName(struct book *p, int num, char name[]); /* 声明变量 */const int NUM = 3;struct book myBooks[NUM];struct book *pBook = myBooks;BOOK *theBook; /* 为myBooks数组的所有元素赋值 */input(pBook, NUM); /* 按ID检索图书 */int bookID;scanf(“%d”, &bookID);fflush(stdin); /*清空输入缓冲区*/theBook = findBookByID(pBook, NUM, bookID); /*按书号检索*/output(theBook, 1); /*输出检索结果*/ /* 输出myBooks数组的所有元素值 */output(pBook, NUM); return 0;} /* * 函数名称:input * 函数功能:从键盘输入为book型结构体数组元素赋值 * 输入格式:(1)共输入num本图书信息 *           (2)对每本图书,在一行内分别输入书号、书名、作者、价格,各数据之间以空格分隔 *           (3)书名和作者不能包含空格 * 形式参数:p,book型指针,book型一维数组首地址 * 形式参数:num,int型,图书数量 * 返 回 值:无 */void input(struct book *p, int num){int i;for(i = 0; i < num; i++){scanf(“%d %s %s %f”, &(p+i)->id, (p+i)->name, (p+i)->author, &(p+i)->price);}} /* * 函数名称:output * 函数功能:输出显示book型结构体数组元素值 * 输出格式:(1)一行输出一本图书信息,共输出num行 *           (2)每行先后输出书号、书名、作者、价格(保留小数点后2位),用逗号分隔图书信息 *           (3)若形参p为空指针,则输出字串NULL * 形式参数:p,book型指针,book型一维数组首地址 * 形式参数:num,int型,图书数量 * 返 回 值:无 */void output(struct book *p, int num){// 请编程实现本函数} /* * 函数名称:findBookByID * 函数功能:按书号检索图书 * 形式参数:p,book型指针,book型一维数组首地址 * 形式参数:num,int型,图书数量 * 形式参数:id,int型,书号 * 返 回 值:返回book型指针。若没有找到图书,则返回空指针NULL;否则,仅返回第1本符合检索条件的图书 */struct book * findBookByID(struct book *p, int num, int id){// 请编程实现本函数} /* * 函数名称:findBookByName * 函数功能:按书名检索图书 * 形式参数:p,book型指针,book型一维数组首地址 * 形式参数:num,int型,图书数量 * 形式参数:name,字符数组,书名 * 返 回 值:返回book型指针。若没有找到图书,则返回空指针NULL;否则,仅返回第1本符合检索条件的图书 */struct book * findBookByName(struct book *p, int num, char name[]){struct book *theBook = NULL;if(p == NULL){return theBook;}int i;for(i = 0; i < num; i++){if(strcmp((p + i) -> name, name) == 0){theBook = p + i;break; //检索到第一个符合条件的图书后就强制退出}}return theBook;} 

【输入形式】

共4行输入。

(1)第1行~第 3行分别输入为第1本~第3本图书信息;对每本图书,在一行内分别输入书号、书名、作者、价格,各数据之间以空格分隔;书名和作者不能包含空格。

(2)第4行输入需进行检索的图书书号(ID)

【输出形式】

共4行输出。

(1)第1行输出为按书号检索的结果。若没有图书,则输出字串NULL;若找到图书,则在一行内先后输出书号、书名、作者、价格(保留小数点后两位),用逗号分隔。

(2)第2行~第4行分别为所有图书信息,每行输出一本图书信息,输出格式同上。

【样例输入】

1001 CLanguage ZhangSan 29.99

1002 English LiSi 36.1823

1003 Math WangWu 65.739

1002

【样例输出】

1002,English,LiSi,36.18

1001,CLanguage,ZhangSan,29.99

1002,English,LiSi,36.18

1003,Math,WangWu,65.74

【样例说明】

输入和输出格式效果如下图所示。

【样例输入】

1 JavaScript LiuBeibei 78.23567

2 OperatingSystem GuanYuyu 62.398

3 C++ ZhangFeifei 18.9834

110

【样例输出】

NULL

1,JavaScript,LiuBeibei,78.24

2,OperatingSystem,GuanYuyu,62.40

3,C++,ZhangFeifei,18.98

【样例说明】

输入和输出格式效果如下图所示。

【评分标准】

正确性

设计思想:链表

实验代码及注释:

/*

@Filename: ex703.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Simple Library Management Program

*/

#include <stdio.h>

#include <string.h>

typedef struct book{

    int id; // 书号

    char name[30]; // 书名

    char author[30]; //作者

    float price; //价格

}BOOK;

int main(){

    /* 声明函数 */

    void input(struct book *p, int num);

    void output(struct book *p, int num);

    struct book * findBookByID(struct book *p, int num, int id);

    struct book * findBookByName(struct book *p, int num, char name[]);

    /* 声明变量 */

    const int NUM = 3;

    struct book myBooks[NUM];

    struct book *pBook = myBooks;

    BOOK *theBook;

    /* 为myBooks数组的所有元素赋值 */

    input(pBook, NUM);

    /* 按ID检索图书 */

    int bookID;

    scanf(“%d”, &bookID);

    fflush(stdin); /*清空输入缓冲区*/

    theBook = findBookByID(pBook, NUM, bookID); /*按书号检索*/

    output(theBook, 1); /*输出检索结果*/

    /* 输出myBooks数组的所有元素值 */

    output(pBook, NUM);

    return 0;

}

/*

 * 函数名称:input

 * 函数功能:从键盘输入为book型结构体数组元素赋值

 * 输入格式:(1)共输入num本图书信息

 *           (2)对每本图书,在一行内分别输入书号、书名、作者、价格,各数据之间以空格分隔

 *           (3)书名和作者不能包含空格

 * 形式参数:p,book型指针,book型一维数组首地址

 * 形式参数:num,int型,图书数量

 * 返 回 值:无

 */

void input(struct book *p, int num){

    int i;

    for(i = 0; i < num; i++){

        scanf(“%d %s %s %f”, &(p+i)->id, (p+i)->name, (p+i)->author, &(p+i)->price);

    }

}

/*

 * 函数名称:output

 * 函数功能:输出显示book型结构体数组元素值

 * 输出格式:(1)一行输出一本图书信息,共输出num行

 *           (2)每行先后输出书号、书名、作者、价格(保留小数点后2位),用逗号分隔图书信息

 *           (3)若形参p为空指针,则输出字串NULL

 * 形式参数:p,book型指针,book型一维数组首地址

 * 形式参数:num,int型,图书数量

 * 返 回 值:无

 */

void output(struct book *p, int num){

    // 请编程实现本函数

    int i;

        if(p==NULL)

        printf(“NULL \n”);

        else

         for(i  =  0;  i  <  num;  i++){

                        printf(“%d,%s,%s,%0.2f\n”, (p+i)->id,  (p+i)->name,  (p+i)->author,  (p+i)->price);

                }

}

/*

 * 函数名称:findBookByID

 * 函数功能:按书号检索图书

 * 形式参数:p,book型指针,book型一维数组首地址

 * 形式参数:num,int型,图书数量

 * 形式参数:id,int型,书号

 * 返 回 值:返回book型指针。若没有找到图书,则返回空指针NULL;否则,仅返回第1本符合检索条件的图书

 */

struct book * findBookByID(struct book *p, int num, int id){

    // 请编程实现本函数

    struct  book  *theBook  =  NULL;

                if(p  ==  NULL){

                        return  theBook;

                }

                int  i;

                for(i  =  0;  i  <  num;  i++){

                        if((p  +  i)  -> id==id){

                                theBook  =  p  +  i;

                                break;  

                        }

                }

                return  theBook;

}

/*

 * 函数名称:findBookByName

 * 函数功能:按书名检索图书

 * 形式参数:p,book型指针,book型一维数组首地址

 * 形式参数:num,int型,图书数量

 * 形式参数:name,字符数组,书名

 * 返 回 值:返回book型指针。若没有找到图书,则返回空指针NULL;否则,仅返回第1本符合检索条件的图书

 */

struct book * findBookByName(struct book *p, int num, char name[]){

    struct book *theBook = NULL;

    if(p == NULL){

        return theBook;

    }

    int i;

    for(i = 0; i < num; i++){

        if(strcmp((p + i) -> name, name) == 0){

            theBook = p + i;

            break; //检索到第一个符合条件的图书后就强制退出

        }

    }

    return theBook;

}

验证与结论:完全正确

总结与心得体会:学会了简单的图书管理程序

实验题目4:教师信息管理

【问题描述】

定义一个包含5个教师成员的结构体数组,教师信息包括职工号、姓名和工资。要求从键盘输入所有教师的信息,并设计一个sort函数实现结构体数组按教师工资由少到多排序。目前,已编辑完成main函数,请编程实现input函数、output函数和sort函数,分别实现教师信息的录入、输出与排序。

/*@Filename: ex701.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: Salary Management System*/ #include <stdio.h>#include <string.h> typedef struct teacher{int id; // 职工号char name[100]; // 姓名int salary; // 工资 }teacher; const int NUM = 5; int main(){void input(teacher *t, int n);void output(teacher *t, int n);void sort(teacher *t, int n); teacher t[NUM]; //教师数组teacher *pt = t; input(pt, NUM); //为教师数组元素赋值 printf(“Before sorting:\n”);output(pt, NUM); //排序前输出 sort(pt, NUM); //按工资排序 printf(“After sorting:\n”);output(pt, NUM); //排序后输出 return 0;} /* * 函数名称:input * 函数功能:实现教师信息的键盘输入 * 输入格式:每行输入一个教师的信息,一个教师的各个数据之间用空格分隔; *           教师姓名不能包含空格 * 形式参数:t, struct teacher型指针,教师数组首地址 * 形式参数:n, int型,教师数组元素个数 * 返 回 值:无 */void input(teacher *t, int n){// 请编程实现本函数 } /* * 函数名称:output * 函数功能:输出教师信息 * 输出格式:每行只输出一个教师的信息,各信息数据以逗号分隔 * 形式参数:t, struct teacher型指针,教师数组首地址 * 形式参数:n, int型,教师数组元素个数 * 返 回 值:无 */void output(teacher *t, int n){// 请编程实现本函数 } /* * 函数名称:sort * 函数功能:对教师数组元素按工资由小到大进行排序 * 形式参数:t, struct teacher型指针,教师数组首地址 * 形式参数:n, int型,教师数组元素个数 * 返 回 值:无 */void sort(teacher *t, int n){// 请编程实现本函数} 

【输入形式】

共有5行输入,每行输入一名教师信息,每个教师的各个数据之间用空格分隔,教师姓名不能包含空格

【输出形式】

共有12行输出。

第1行:输出“Before sorting:”

第2~6行:输出排序前教师信息;每行输出一个教师信息;每个教师数据用逗号分隔

第7行:输出“After sorting:”

第8~12行:输出排序后教师信息;每行输出一个教师信息;每个教师数据用逗号分隔

【样例输入】

1 LiuBeibei 26000

2 GuanYuyu 24890

3 ZhangFeifei 22000

4 WangWu 3610

5 LiSi 1860

【样例输出】

Before sorting:

1,Liu Beibei,26000

2,Guan Yuyu,24890

3,Zhang Feifei,22000

4,Wang Wu,3610

5,Li Si,1860

After sorting:

5,Li Si,1860

4,Wang Wu,3610

3,Zhang Feifei,22000

2,Guan Yuyu,24890

1,Liu Beibei,26000

【样例说明】

输入和输出格式效果如下图所示。

【样例输入】

101 ZhangSan 9800

102 ZhangSi 5100

103 ZhangWu 48000

104 ZhangLiu 3200

105 ZhangQi 6800

【样例输出】

Before sorting:

101,Zhang San,9800

102,Zhang Si,5100

103,Zhang Wu,48000

104,Zhang Liu,3200

105,Zhang Qi,6800

After sorting:

104,Zhang Liu,3200

102,Zhang Si,5100

105,Zhang Qi,6800

101,Zhang San,9800

103,Zhang Wu,48000

【样例说明】

【评分标准】

正确性

设计思想:链表

实验代码及注释:

/*

@Filename: ex701.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Salary Management System

*/

#include <stdio.h>

#include <string.h>

typedef struct teacher{

    int id; // 职工号

    char name[100]; // 姓名

    int salary; // 工资

}teacher;

const int NUM = 5;

int main(){

    void input(teacher *t, int n);

    void output(teacher *t, int n);

    void sort(teacher *t, int n);

    teacher t[NUM]; //教师数组

    teacher *pt = t;

    input(pt, NUM); //为教师数组元素赋值

    printf(“Before sorting:\n”);

    output(pt, NUM); //排序前输出

    sort(pt, NUM); //按工资排序

    printf(“After sorting:\n”);

    output(pt, NUM); //排序后输出

    return 0;

}

/*

 * 函数名称:input

 * 函数功能:实现教师信息的键盘输入

 * 输入格式:每行输入一个教师的信息,一个教师的各个数据之间用空格分隔;

 *           教师姓名不能包含空格

 * 形式参数:t, struct teacher型指针,教师数组首地址

 * 形式参数:n, int型,教师数组元素个数

 * 返 回 值:无

 */

void input(teacher *t, int n){

    // 请编程实现本函数

        int i;

        teacher*p=t;  

        for(i=0;i<n;i++)

        {

        scanf(“%d%s%d”,&(p+i)->id,(p+i)->name,&(p+i)->salary);

        }

}

/*

 * 函数名称:output

 * 函数功能:输出教师信息

 * 输出格式:每行只输出一个教师的信息,各信息数据以逗号分隔

 * 形式参数:t, struct teacher型指针,教师数组首地址

 * 形式参数:n, int型,教师数组元素个数

 * 返 回 值:无

 */

void output(teacher *t, int n){

    // 请编程实现本函数

    int i;

        teacher*p=t;  

        for(i=0;i<n;i++)

        {

        printf(“%d,%s,%d\n”,(p+i)->id,(p+i)->name,(p+i)->salary);

        }

}

/*

 * 函数名称:sort

 * 函数功能:对教师数组元素按工资由小到大进行排序

 * 形式参数:t, struct teacher型指针,教师数组首地址

 * 形式参数:n, int型,教师数组元素个数

 * 返 回 值:无

 */

void sort(teacher *t, int n){

    // 请编程实现本函数

    int i;

        int j;

        struct teacher p;  

        for(i=0;i<n-1;i++)

         for(j=i+1;j<n;j++)

        {

        if(t[i].salary>t[j].salary)

        {

        p=t[i];

        t[i]=t[j];

        t[j]=p;

        }

        }

}

验证与结论:完全正确

总结与心得体会:学会了教师信息管理

实验八 文件

实验题目1:统计文本文件

【问题描述】

请编程实现读取并统计文本文件“ex802.txt”中字母、数字和其它字符的个数,然后将统计结果输出到屏幕。注:该文本文件与源码文件保存在同一个文件夹中。

目前已完成main函数的编写,请编程实现statisticsFromFile函数,函数的功能和要求如下所示。

/*@Filename: ex802.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: File Character Statistics*/ #include<stdio.h>#include <stdlib.h>#include <string.h> int main(void){int statisticsFromFile(int *num, char *fileName, char *mode); /* * 定义数组num,包含三个元素: * 第1个元素表示字母个数; * 第2个元素表示数字个数; * 第3个元素表示其他字符个数 */int num[3]={0,0,0};char fileName[] = “ex802.txt”; /*读取文件并分类统计字符个数*/statisticsFromFile(num, fileName, “r”); /*输出显示各类字符个数*/printf(“letter:%d\n”,num[0]);printf(“number:%d\n”,num[1]);printf(“other:%d”,num[2]); return 0;} /* * 函数名称:statisticsFromFile * 函数功能:读取文件并分类统计字符个数,统计结果保存在形参数组num中 * 形式参数:int *,一维整型数组首地址 * 形式参数:char *fileName,文件路径及名称 * 形式参数:char *mode,文件使用方式 * 返 回 值:int型,若文件打开异常,返回 -1;否则返回读取文件的字符数 */int statisticsFromFile(int *num, char *fileName, char *mode){// 请编程实现本函数} 

【输入形式】

文件输入:事先创建“ex802.txt”文件并录入任意字串作为文件输入内容

【输出形式】

标准输出:在显示器中有3行输出

第1行:字母个数

第2行:数字个数

第3行:其他字符个数

【样例输入】

ksiwkslapUWJ827301*&!@&&^%*!

【样例输出】

letter:12

number:6

other:10

【样例说明】

图1 文件输入内容样例

图2 标准输出内容样例

【评分标准】

正确性

设计思想:文件操作

实验代码及注释:

/*

@Filename: ex802.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: File Character Statistics

*/

#include<stdio.h>

#include <stdlib.h>

#include <string.h>

int main(void){

    int statisticsFromFile(int *num, char *fileName, char *mode);

    /*

     * 定义数组num,包含三个元素:

     * 第1个元素表示字母个数;

     * 第2个元素表示数字个数;

     * 第3个元素表示其他字符个数

     */

    int num[3]={0,0,0};

    char fileName[] = “ex802.txt”;

    /*读取文件并分类统计字符个数*/

    statisticsFromFile(num, fileName, “r”);

    /*输出显示各类字符个数*/

    printf(“letter:%d\n”,num[0]);

    printf(“number:%d\n”,num[1]);

    printf(“other:%d”,num[2]);

    return 0;

}

/*

 * 函数名称:statisticsFromFile

 * 函数功能:读取文件并分类统计字符个数,统计结果保存在形参数组num中

 * 形式参数:int *,一维整型数组首地址

 * 形式参数:char *fileName,文件路径及名称

 * 形式参数:char *mode,文件使用方式

 * 返 回 值:int型,若文件打开异常,返回 -1;否则返回读取文件的字符数

 */

int statisticsFromFile(int *num, char *fileName, char *mode){

    // 请编程实现本函数

        FILE*fp;

        fp=fopen(“ex802.txt”,”r”);

        if(fp==NULL)

        {

        return -1;

        }

        char c;

        while((c=fgetc(fp))!=-1)

        {

        if(c>=’a’&&c<=’z’)

        num[0]++;

        else

        if(c>=’A’&&c<=’Z’)

        num[0]++;

        else

        if(c>=’0’&&c<=’9′)

        num[1]++;

        else

        num[2]++;

        }

}

验证与结论:完全正确

总结与心得体会:学会了文件统计文本文件

实验题目2:格式化写文件

【问题描述】

创建一个学生结构体,如下所示。

struct stu{

int id; //学号

    char name[20]; //姓名

    int age; //年龄

    int score; //成绩

};

然后从键盘录入两名学生的信息,最后将上述信息格式化写入到文件。写入格式要求:将每个同学的信息写入到文件中的一行,每行中的各个数据之间以空格分隔。目前,已经完成了main函数的编写,请编程实现“stdinForStu”函数和“writeFileForStu”函数。

注:需写入的文本文件“ex803.txt”应与源文件“ex803.c”保存在同一个文件夹中。

/*@Filename: ex803.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: Format Input and Output*/ #include <stdio.h>struct stu{int id; //学号    char name[20]; //姓名    int age; //年龄    int score; //成绩}; int main(){/*声明函数及变量*/void stdinForStu(struct stu *p, int num);void writeFileForStu(struct stu *p, int num, char filename[],char mode[]);const int NUM = 2; //学生数量    struct stu students[NUM]; //stu型数组struct stu *p = students; //stu型指针char filename[] = “ex803.txt”; //待写入文件路径及名称        /*从键盘获取输入*/    stdinForStu(p, NUM);        /*向文件写入数据*/    writeFileForStu(p, NUM, filename, “w”);        return 0;} /* * 函数名称:stdinForStu * 函数功能:从键盘输入数据,保存到指针 p 所指向的数组中 * 输入格式:共输入 num 行;每行输入一个 stu 型数据,每个成员变量之间用空格分隔 * 形式参数:struct stu * p,指向 stu 型一维数组首地址 * 形式参数:int num,一维数组元素个数 * 返 回 值:无 */void stdinForStu(struct stu *p, int num){// 请编程实现本函数} /* * 函数名称:writeFileForStu * 函数功能:向文件格式化写入数据 * 写入格式:共写入 num 行;每行写入一个 stu 型数据,每个成员变量之间用空格分隔 * 形式参数:struct stu * p,指向 stu 型一维数组首地址。该数组数据将被写入文件 * 形式参数:int num,一维数组元素个数,也即写入到文件的行数 * 形式参数:char filename[],待写入的文件路径及名称 * 形式参数:char mode[],文件使用方式 * 返 回 值:无 */void writeFileForStu(struct stu *p, int num, char filename[],char mode[]){// 请编程实现本函数} 

【输入形式】

标准输入:有2行。每行输入一个同学信息;每行中数据之间以空格分隔

【输出形式】

文件输出:有2行。每行写入一个同学信息;每行中数据之间以空格分隔

【样例输入】

1001 zhangfeifei 18 100

1002 liubeibei 19 80

【样例输出】

1001 zhangfeifei 18 100

1002 liubeibei 19 80

【样例说明】

图1 标准输入内容样例

图2 文件输出内容样例


【评分标准】

正确

设计思想:文件操作

实验代码及注释:

/*

@Filename: ex803.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Format Input and Output

*/

#include <stdio.h>

struct stu{

    int id; //学号

    char name[20]; //姓名

    int age; //年龄

    int score; //成绩

};

int main(){

    /*声明函数及变量*/

    void stdinForStu(struct stu *p, int num);

    void writeFileForStu(struct stu *p, int num, char filename[],char mode[]);

    const int NUM = 2; //学生数量

    struct stu students[NUM]; //stu型数组

    struct stu *p = students; //stu型指针

    char filename[] = “ex803.txt”; //待写入文件路径及名称

    /*从键盘获取输入*/

    stdinForStu(p, NUM);

    /*向文件写入数据*/

    writeFileForStu(p, NUM, filename, “w”);

    return 0;

}

/*

 * 函数名称:stdinForStu

 * 函数功能:从键盘输入数据,保存到指针 p 所指向的数组中

 * 输入格式:共输入 num 行;每行输入一个 stu 型数据,每个成员变量之间用空格分隔

 * 形式参数:struct stu * p,指向 stu 型一维数组首地址

 * 形式参数:int num,一维数组元素个数

 * 返 回 值:无

 */

void stdinForStu(struct stu *p, int num){

    // 请编程实现本函数

    int i;

        for(i=0;i<=num-1;i++)

        {

        scanf(“%d%s%d%d”,&(p+i)->id,(p+i)->name,&(p+i)->age,&(p+i)->score);

        }

}

/*

 * 函数名称:writeFileForStu

 * 函数功能:向文件格式化写入数据

 * 写入格式:共写入 num 行;每行写入一个 stu 型数据,每个成员变量之间用空格分隔

 * 形式参数:struct stu * p,指向 stu 型一维数组首地址。该数组数据将被写入文件

 * 形式参数:int num,一维数组元素个数,也即写入到文件的行数

 * 形式参数:char filename[],待写入的文件路径及名称

 * 形式参数:char mode[],文件使用方式

 * 返 回 值:无

 */

void writeFileForStu(struct stu *p, int num, char filename[],char mode[]){

    // 请编程实现本函数

    int i;

        FILE*fp;

        fp=fopen(filename,mode);

        for(i=0;i<=num-1;i++)

        {

        fprintf(fp,”%d %s %d %d\n”,(p+i)->id,(p+i)->name,(p+i)->age,(p+i)->score);

        }

}

验证与结论:完全正确

总结与心得体会:学会了格式化写文件

实验题目3:写入文本文件

【问题描述】

从键盘输入一个长度不超过100个字符的字符串,然后做如下操作:

(1)将字串中的小写字母转为大写,大写字母转为小写,而其它字符不作处理。

(2)将字串输出保存到一个名为“ex801.txt”的文本文件中。注:文本文件ex801.txt应与源码文件ex801.c保存在同一个文件夹中。

目前,已编写完成main函数,请编程实现writeToFile函数,具体功能和要求如下所示。

/*@Filename: ex801.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: File Character Reading and Writing*/ #include <stdio.h>#include <stdlib.h>#include <string.h> int main(int argc,char *argv[]){/*(1)声明函数及变量*/int writeToFile(char *str, char *fileName, char *mode); char str[100];char fileName[] = “ex801.txt”; /*(2)获取键盘输入字串*/fgets(str, 100, stdin);//gets(str); //将回车看作字串输入结束标志,字串中可以有空格//scanf(“%s”, str); //将空格看作字串输入结束标志,字串中不能有空格 /*(3)将字串写入文件*/int charNum = writeToFile(str, fileName, “w”);if(charNum < 0){//printf(“write error”);//用于调试return -1;} return 0;} /* * 函数名称:writeToFile * 函数功能:将字串写入文件 * 形式参数:char *str,一维字符数组(字符串)首地址 * 形式参数:char *fileName,待写入的文件路径及名称 * 形式参数:char *mode,文件使用方式 * 返 回 值:int型,若文件打开异常,返回 -1;否则返回写入到文件的字符数 */int writeToFile(char *str, char *fileName, char *mode){// 请编程实现本函数 } 

【输入形式】

标准输入:从键盘任意输入不超过100个字符的字串

【输出形式】

文件输出:将字串转换后输出到文件

【样例输入】

I Love You!78$%2kjhaEWF

【样例输出】

i lOVE yOU!78$%2KJHAewf

【样例说明】

图1 标准输入内容样例

图2 文件输出内容样例

【评分标准】

正确性

设计思想:文件操作

实验代码及注释:

/*

@Filename: ex801.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: File Character Reading and Writing

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main(int argc,char *argv[]){

    /*(1)声明函数及变量*/

    int writeToFile(char *str, char *fileName, char *mode);

    char str[100];

    char fileName[] = “ex801.txt”;

    /*(2)获取键盘输入字串*/

    fgets(str, 100, stdin);

    //gets(str); //将回车看作字串输入结束标志,字串中可以有空格

    //scanf(“%s”, str); //将空格看作字串输入结束标志,字串中不能有空格

    /*(3)将字串写入文件*/

    int charNum = writeToFile(str, fileName, “w”);

    if(charNum < 0){

        //printf(“write error”);//用于调试

        return -1;

    }

    return 0;

}

/*

 * 函数名称:writeToFile

 * 函数功能:将字串写入文件

 * 形式参数:char *str,一维字符数组(字符串)首地址

 * 形式参数:char *fileName,待写入的文件路径及名称

 * 形式参数:char *mode,文件使用方式

 * 返 回 值:int型,若文件打开异常,返回 -1;否则返回写入到文件的字符数

 */

int writeToFile(char *str, char *fileName, char *mode){

    // 请编程实现本函数

            FILE *fp;

        int i=0;

        fp=fopen(fileName,mode);

        while(str[i]!=’\0′)

        {

        int temp=0;

        if(str[i]>=’a’&&str[i]<=’z’)

        temp=-32;

        if(str[i]>=’A’&&str[i]<=’Z’)

        temp=32;

        fprintf(fp,”%c”,str[i]+temp);

        i++;

        }

}

验证与结论:完全正确

总结与心得体会:学会了写入文本文件

实验题目4:格式化读文件

【问题描述】

从文本文件“ex804.txt”格式化读取学生信息,然后将学生信息封装到结构体数组中,最后在标准输出设备中输出显示。

(1)“ex804.txt”的存储组织格式为:每行只保存一个同学信息;每行(每个同学)共有4个数据,分别为学号、姓名、年龄、成绩,每个数据之间以空格分隔。注:文本文件“ex804.txt”应与源文件“ex804.c”保存在同一个文件夹中。

(2)学生结构体定义如下:

struct stu{

int id; //学号

char name[20]; //姓名

int age; //年龄

int score; //成绩

};

目前,已完成main函数的编写,请编程实现“readFileForStu”函数和“stdoutForStu”函数。

/*@Filename: ex804.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: Format Input and Output*/ #include <stdio.h> struct stu{int id; //学号char name[20]; //姓名int age; //年龄int score; //成绩}; int main(){/*声明函数及变量*/void readFileForStu(struct stu *p, int num, char filename[],char mode[]);void stdoutForStu(struct stu *p, int num);const int NUM = 2; //学生数量struct stu students[NUM]; //stu型数组struct stu *p = students; //stu型指针char filename[] = “ex804.txt”; //待读取的文件路径及名称 /*从文件获取输入*/readFileForStu(p, NUM, filename, “r”); /*向屏幕输出显示*/stdoutForStu(p, NUM);return 0;} /* * 函数名称:readFileForStu * 函数功能:从文件格式化读取数据 * 写入格式:共读取 num 行;每行读出一个 stu 型数据,每个成员变量之间用空格分隔 * 形式参数:struct stu * p,指向 stu 型一维数组首地址。该数组用于保存文件读取数据 * 形式参数:int num,一维数组元素个数,也即读取文件的行数 * 形式参数:char filename[],待读取的文件路径及名称 * 形式参数:char mode[],文件使用方式 * 返 回 值:无 */void readFileForStu(struct stu *p, int num, char filename[],char mode[]){// 请编程实现本函数} /* * 函数名称:stdoutForStu * 函数功能:向显示器输出显示数据 * 输出格式:共输出 num 行;每行输出一个 stu 型数据,每个成员变量之间用空格分隔 * 形式参数:struct stu * p,指向 stu 型一维数组首地址 * 形式参数:int num,一维数组元素个数 * 返 回 值:无 */void stdoutForStu(struct stu *p, int num){// 请编程实现本函数}

【输入形式】

文件输入:在文件中每行只保存一个同学信息,共有2行;每行(每个同学)共有4个数据,分别为学号、姓名、年龄、成绩,每个数据之间以空格分隔

【输出形式】

标准输出:每行输出一个同学信息,每行中数据之间以空格分隔

【样例输入】

1 libai 100 100

2 lihei 200 200

【样例输出】

1 libai 100 100

2 lihei 200 200

【样例说明】

图1 文件输入内容样例

图2 标准输出内容样例


【评分标准】

正确性

设计思想:文件操作

实验代码及注释:

/*

@Filename: ex804.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Format Input and Output

*/

#include <stdio.h>

struct stu{

    int id; //学号

    char name[20]; //姓名

    int age; //年龄

    int score; //成绩

};

int main(){

/*声明函数及变量*/

    void readFileForStu(struct stu *p, int num, char filename[],char mode[]);

    void stdoutForStu(struct stu *p, int num);

    const int NUM = 2; //学生数量

    struct stu students[NUM]; //stu型数组

    struct stu *p = students; //stu型指针

    char filename[] = “ex804.txt”; //待读取的文件路径及名称

    /*从文件获取输入*/

    readFileForStu(p, NUM, filename, “r”);

    /*向屏幕输出显示*/

    stdoutForStu(p, NUM);

    return 0;

}

/*

 * 函数名称:readFileForStu

 * 函数功能:从文件格式化读取数据

 * 写入格式:共读取 num 行;每行读出一个 stu 型数据,每个成员变量之间用空格分隔

 * 形式参数:struct stu * p,指向 stu 型一维数组首地址。该数组用于保存文件读取数据

 * 形式参数:int num,一维数组元素个数,也即读取文件的行数

 * 形式参数:char filename[],待读取的文件路径及名称

 * 形式参数:char mode[],文件使用方式

 * 返 回 值:无

 */

void readFileForStu(struct stu *p, int num, char filename[],char mode[]){

    // 请编程实现本函数

    FILE *fp;

        int i;

        fp=fopen( filename, mode);

        for(i=0;i<=num-1;i++)

        {

        fscanf(fp,”%d%s%d%d”,&(p+i)->id,(p+i)->name,&(p+i)->age,&(p+i)->score);

        }

}

/*

 * 函数名称:stdoutForStu

 * 函数功能:向显示器输出显示数据

 * 输出格式:共输出 num 行;每行输出一个 stu 型数据,每个成员变量之间用空格分隔

 * 形式参数:struct stu * p,指向 stu 型一维数组首地址

 * 形式参数:int num,一维数组元素个数

 * 返 回 值:无

 */

void stdoutForStu(struct stu *p, int num){

    // 请编程实现本函数

    int i;

        for(i=0;i<=num-1;i++)

        {

        printf(“%d %s %d %d\n”,(p+i)->id,(p+i)->name,(p+i)->age,(p+i)->score);

        }

}

验证与结论:完全正确

总结与心得体会:学会了格式化读文件

实验题目5:读写二进制文件

【问题描述】

        现有一个结构体用来描述学生信息,结构体数据成员包括:学号、姓名、三门课程成绩和平均成绩。

         typedef struct student{

        char sno[SNO_LENGTH]; //学号

        char name[NAME_LENGTH]; //姓名

        int score[COURSE_NUMBER]; //课程成绩数组

        float average; //所有课程的平均成绩

}STU;

(1)从键盘输入3个学生的学号、姓名和三门课成绩,然后计算每个学生的平均成绩。之后,将每个学生的结构体数据存放在二进制磁盘文件“ex805.dat”(与源文件“ex805.c”存放于同一个文件夹)中。

(2)读取二进制磁盘文件“ex805.dat”,然后输出到显示器。

目前,已编辑完成main函数、input函数和output函数。请编程实现writeFile函数和readFile函数。具体函数功能及要求如下所示。

/*@Filename: ex805.c@Author: Ju Chengdong@Version: 1.0@Date: 2021-03-18@Description: Data File Processing*/ #include <stdio.h>#include <stdlib.h>#include <string.h> #define SNO_LENGTH 10#define NAME_LENGTH 20#define COURSE_NUMBER 3#define STU_NUMBER 3 /* * 定义结构体类型student */typedef struct student{char sno[SNO_LENGTH]; //学号char name[NAME_LENGTH]; //姓名int score[COURSE_NUMBER]; //课程成绩数组float average; //所有课程的平均成绩}STU; int main(){/*声明函数*/void input(struct student *p, int rows);void output(STU *p, int rows);int writeFile(STU *p, int rows, char filename[], char mode[]);int readFile(STU *p, int rows, char filename[], char mode[]); /*定义student型结构体数组*/STU stu[STU_NUMBER], stu2[STU_NUMBER]; /*从标准输入为stu数组元素赋值*/input(stu,STU_NUMBER); /*将stu数组元素值写入二进制文件,并输出成功写入的数据块个数*/printf(“%d\n”, writeFile(stu, STU_NUMBER, “ex805.dat”, “wb”));//writeFile(stu, STU_NUMBER, “ex805.dat”, “wb”); /*读取二进制文件并填充stu2数组中,并输出成功读取的数据块个数*/printf(“%d\n”, readFile(stu2, STU_NUMBER, “ex805.dat”, “rb”)); /*输出显示stu2数组元素*/output(stu2, STU_NUMBER);return 0;} /* * 函数名称:input * 函数功能:为形参 p 所指向的结构体数组元素以键盘输入方式进行赋值 * 输入格式:所有学生的所有数据均需分行输入,即: *           每个学生均有 5 行输入,自上而下分别为学号、姓名、三门课程成绩, *           其中,学号和姓名不能包含空格 * 形式参数:struct student型指针,p 指向结构体数组首地址 * 形式参数:int型,rows 为结构体数组元素个数 * 返 回 值:无 */void input(struct student *p, int rows){int i, j;for(i = 0; i < rows; i++){//printf(“\nInput the information of student %d:\n”, (i + 1));//输入学号//printf(“sno:\t”);scanf(“%s”, (p + i) -> sno);//gets((p + i) -> sno);//fgets((p + i) -> sno, SNO_LENGTH, stdin);fflush(stdin); //输入姓名//printf(“name:\t”);scanf(“%s”, (p + i) -> name);//gets((p + i) -> name);//fgets((p + i) -> name, NAME_LENGTH, stdin);fflush(stdin); //输入三门课程成绩,并求和float sum = 0;for(j = 0; j < COURSE_NUMBER; j++){//printf(“score%d:\t”, j + 1);scanf(“%d”, &((p + i) -> score[j]));fflush(stdin);sum += (p + i) -> score[j];}//计算平均成绩(p + i) -> average = sum / COURSE_NUMBER;}} /* * 函数名称:output * 函数功能:将形参 p 所指向的结构体数组输出到屏幕 * 输出格式:所有同学的信息均需分行输出,即:每行只输出一个同学的所有数据, *           从左至右分别为学号、姓名、三门课程成绩和平均成绩, *           其中,平均成绩保留小数点后两位 * 形式参数:struct student型指针,p 指向结构体数组首地址 * 形式参数:int型,rows 为结构体数组元素个数 * 返 回 值:无 */void output(STU *p, int rows){int i,j;//printf(“\nThe students’information is as follows:”);for(i = 0; i < rows; i++){printf(“%s,”, (p + i) -> sno);//puts((p + i) -> sno);fflush(stdout); printf(“%s,”, (p + i) -> name);//puts((p + i) -> name);fflush(stdout); for(j = 0; j < COURSE_NUMBER; j++){printf(“%d,”, (p + i) -> score[j]);fflush(stdout);}printf(“%.2f\n”, (p + i) -> average);}} /* * 函数名称:writeFile * 函数功能:将指针 p 所指向的数组的所有元素值写入到二进制文件中 * 形式参数:struct student型指针,p 指向结构体数组的首地址 * 形式参数:int型,rows 为结构体数组长度 * 形式参数:一维字符数组,filename 为二进制文件路径及名称 * 形式参数:一维字符数组,mode 为文件打开模式 * 返 回 值:int型,若打开文件失败,返回 -1;否则,返回成功写入到文件的数据块个数 */int writeFile(STU *p, int rows, char filename[], char mode[]){// 请编程实现本函数 } /* * 函数名称:readFile * 函数功能:读取二进制文件并存储到指针p所指向的数组 * 形式参数:struct student型指针,p 指向结构体数组的首地址 * 形式参数:int型,rows 为结构体数组长度 * 形式参数:一维字符数组,filename 为二进制文件路径及名称 * 形式参数:一维字符数组,mode 为文件打开模式 * 返 回 值:int型,若打开文件失败,返回 -1;否则,返回从文件成功读取的数据块个数 */int readFile(STU *p, int rows, char filename[], char mode[]){// 请编程实现本函数 } 

【输入形式】

从键盘输入3个学生信息,且每个学生的每个数据均分行输入。共有15行输入。

第1~5行:第1个学生的学号、姓名、成绩1、成绩2、成绩3

第6~10行:第2个学生的学号、姓名、成绩1、成绩2、成绩3

第11~15行:第3个学生的学号、姓名、成绩1、成绩2、成绩3

其中,学生的学号和姓名不能包含空格。

【输出形式】

标准输出。共有5行输出。

第1行:成功写入二进制文件的数据块个数

第2行:成功读取二进制文件的数据块个数

第3行:第1个学生的学号、姓名、成绩1、成绩2、成绩3、平均成绩,以逗号分隔

第4行:第2个学生的学号、姓名、成绩1、成绩2、成绩3、平均成绩,以逗号分隔

第5行:第3个学生的学号、姓名、成绩1、成绩2、成绩3、平均成绩,以逗号分隔

【样例输入】

1001

LiuBeibei

100

100

71

1002

GuanYuyu

90

90

80

1003

ZhangFeifei

80

80

90

【样例输出】

3

3

1001,LiuBeibei,100,100,71,90.33

1002,GuanYuyu,90,90,80,86.67

1003,ZhangFeifei,80,80,90,83.33

【样例说明】

【评分标准】

正确性

设计思想:文件操作

实验代码及注释:

/*

@Filename: ex805.c

@Author: Ju Chengdong

@Version: 1.0

@Date: 2021-03-18

@Description: Data File Processing

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define SNO_LENGTH 10

#define NAME_LENGTH 20

#define COURSE_NUMBER 3

#define STU_NUMBER 3

/*

 * 定义结构体类型student

 */

typedef struct student{

    char sno[SNO_LENGTH]; //学号

    char name[NAME_LENGTH]; //姓名

    int score[COURSE_NUMBER]; //课程成绩数组

    float average; //所有课程的平均成绩

}STU;

int main(){

    /*声明函数*/

    void input(struct student *p, int rows);

    void output(STU *p, int rows);

    int writeFile(STU *p, int rows, char filename[], char mode[]);

    int readFile(STU *p, int rows, char filename[], char mode[]);

    /*定义student型结构体数组*/

    STU stu[STU_NUMBER], stu2[STU_NUMBER];

    /*从标准输入为stu数组元素赋值*/

    input(stu,STU_NUMBER);

    /*将stu数组元素值写入二进制文件,并输出成功写入的数据块个数*/

    printf(“%d\n”, writeFile(stu, STU_NUMBER, “ex805.dat”, “wb”));

    //writeFile(stu, STU_NUMBER, “ex805.dat”, “wb”);

    /*读取二进制文件并填充stu2数组中,并输出成功读取的数据块个数*/

    printf(“%d\n”, readFile(stu2, STU_NUMBER, “ex805.dat”, “rb”));

    /*输出显示stu2数组元素*/

    output(stu2, STU_NUMBER);

    return 0;

}

/*

 * 函数名称:input

 * 函数功能:为形参 p 所指向的结构体数组元素以键盘输入方式进行赋值

 * 输入格式:所有学生的所有数据均需分行输入,即:

 *           每个学生均有 5 行输入,自上而下分别为学号、姓名、三门课程成绩,

 *           其中,学号和姓名不能包含空格

 * 形式参数:struct student型指针,p 指向结构体数组首地址

 * 形式参数:int型,rows 为结构体数组元素个数

 * 返 回 值:无

 */

void input(struct student *p, int rows){

    int i, j;

    for(i = 0; i < rows; i++){

        //printf(“\nInput the information of student %d:\n”, (i + 1));

        //输入学号

        //printf(“sno:\t”);

        scanf(“%s”, (p + i) -> sno);

        //gets((p + i) -> sno);

        //fgets((p + i) -> sno, SNO_LENGTH, stdin);

        fflush(stdin);

        //输入姓名

        //printf(“name:\t”);

        scanf(“%s”, (p + i) -> name);

        //gets((p + i) -> name);

        //fgets((p + i) -> name, NAME_LENGTH, stdin);

        fflush(stdin);

        //输入三门课程成绩,并求和

        float sum = 0;

        for(j = 0; j < COURSE_NUMBER; j++){

            //printf(“score%d:\t”, j + 1);

            scanf(“%d”, &((p + i) -> score[j]));

            fflush(stdin);

            sum += (p + i) -> score[j];

        }

        //计算平均成绩

        (p + i) -> average = sum / COURSE_NUMBER;

    }

}

/*

 * 函数名称:output

 * 函数功能:将形参 p 所指向的结构体数组输出到屏幕

 * 输出格式:所有同学的信息均需分行输出,即:每行只输出一个同学的所有数据,

 *           从左至右分别为学号、姓名、三门课程成绩和平均成绩,

 *           其中,平均成绩保留小数点后两位

 * 形式参数:struct student型指针,p 指向结构体数组首地址

 * 形式参数:int型,rows 为结构体数组元素个数

 * 返 回 值:无

 */

void output(STU *p, int rows){

    int i,j;

    //printf(“\nThe students’information is as follows:”);

    for(i = 0; i < rows; i++){

        printf(“%s,”, (p + i) -> sno);

        //puts((p + i) -> sno);

        fflush(stdout);

        printf(“%s,”, (p + i) -> name);

        //puts((p + i) -> name);

        fflush(stdout);

        for(j = 0; j < COURSE_NUMBER; j++){

            printf(“%d,”, (p + i) -> score[j]);

            fflush(stdout);

        }

        printf(“%.2f\n”, (p + i) -> average);

    }

}

/*

 * 函数名称:writeFile

 * 函数功能:将指针 p 所指向的数组的所有元素值写入到二进制文件中

 * 形式参数:struct student型指针,p 指向结构体数组的首地址

 * 形式参数:int型,rows 为结构体数组长度

 * 形式参数:一维字符数组,filename 为二进制文件路径及名称

 * 形式参数:一维字符数组,mode 为文件打开模式

 * 返 回 值:int型,若打开文件失败,返回 -1;否则,返回成功写入到文件的数据块个数

 */

int writeFile(STU *p, int rows, char filename[], char mode[]){

    // 请编程实现本函数

        FILE*fp;

        int sum=0;

        int i;

        fp=fopen(filename,mode);

        for(i=0;i<rows;i++)

        {

        sum++;

                        fprintf(fp,”%s “,  (p  +  i)  ->  sno);

                        fprintf(fp,”%s “,  (p  +  i)  ->  name);

                          int j;

                        for(j=  0; j<3;  j++)

                                fprintf(fp,”%d “,  (p  +  i)  ->  score[j]);

                        fprintf(fp,”%f “,  (p  +  i)  ->  average);

        }

        fclose(fp);

        return sum;

}

/*

 * 函数名称:readFile

 * 函数功能:读取二进制文件并存储到指针p所指向的数组

 * 形式参数:struct student型指针,p 指向结构体数组的首地址

 * 形式参数:int型,rows 为结构体数组长度

 * 形式参数:一维字符数组,filename 为二进制文件路径及名称

 * 形式参数:一维字符数组,mode 为文件打开模式

 * 返 回 值:int型,若打开文件失败,返回 -1;否则,返回从文件成功读取的数据块个数

 */

int readFile(STU *p, int rows, char filename[], char mode[]){

    // 请编程实现本函数

            FILE*fp;

        int i;

        int sum=0;

        fp=fopen(filename,mode);

        if(fp==NULL)

        return -1;

        for(i=0;i<rows;i++)

        {

                        sum++;

                        fscanf(fp,”%s”,  (p  +  i)  ->  sno);

                        fscanf(fp,”%s”,  (p  +  i)  ->  name);

                        int j;

                        for(j=  0; j<3;  j++)

                        fscanf(fp,”%d”,  &(p  +  i)  ->  score[j]);

                        fscanf(fp,”%f” , &(p  +  i)  ->  average);

        }

        fclose(fp);

        return sum;

}

验证与结论:完全正确

总结与心得体会:学会了读写二进制文件