新疆昌吉学院
《C语言程序设计》
教学实习报告
部门:信息技术分院
专业:计算机应用技术
班级:2010高职应用
姓名:
指导教师:
《C语言程序设计》教学实习报告
2010高职应用班
一、实习时间: 2011 年 6 月 13 日至 2011 年 6 月 17 日
二、实习地点:第一微机室
三、实习目的:(小4宋体,约150字)
(1)能进一步熟悉C程序的编辑、编译、连接和运行的过程;
(2)通过C语言环境下的应用实例,能有编写程序的能力,掌握编程的思路和方法,掌握C语言程序设计的基本概念和基本技能;
(3)在程序调试过程中,能根据运行结果,运用相应的手段,正确地找出并解决程序中的逻辑错误;
(4)可以掌握不同类型数据之间赋值的规律;
(5)通过解题、程序设计和上机实践,能加深对所学概念的理解,使得理论与实践相结合的学习方法;
(6)通过C语言程序设计的课程实习,我们能具有使用计算机解决相关问题的能力,为今后学习其他计算机应用课程打下较好的程序设计基础。
四、实习内容及方法:
实训一 C语言的编程环境:
1、Turbo C运行环境。
了解TC的基本环境,熟悉常用菜单项和快捷键。
2、C程序的编辑、编译、连接和运行过程。
掌握C程序的运行步骤,初步了解C程序的特点。
3、VC6.0环境的熟悉,能按照软件并在软件中能够调试简单的C语言程序。
实训二 C语言数据类型、运算符及表达式:
案例3:字母转换问题。本案例在执行时,将提示输入一个字母,如果输入的是小写字母,程序将输入的小写字母转换为大写字母并输出,否则按原样输出。 步骤:
1、定义变量,和变量类型;
2、寻找大小写字母的 ASC||码值得关系;
3、输入输出变量。
代码:
结果:
实训三 C程序的三种基本结构的应用
案例1:输入某年某月某日,判断这一天是这一年的第几天?
解题步骤:
1、定义变量年year月month、日day、和第几个月的天数总和sum;
2、定义month变量作为switch语句的测试条件;
3、从键盘上输入年、月、日的值;
4、输出这一年的第几天sum。
程序分析:
输入某年某月某日,判断这一天是这一年的第几天?那么需要考虑三个变量,年,月,日。
首先,年主要要考虑的因素是否是闰年的问题。月要考虑的是那一个月的问题。因为不同月的天数不一样。日嘛,就不用说了。
还有就是,月份是一月或者二月,那么就不需要考虑是否闰年的问题,因为不需要计算二月总共多少天。
上述程序,首先是在默认闰年的情况下计算某月前面所有月的天数和,然后加上当月的零头天数,最后才是判断当月是否大于二月,如果大于二月,那么必须考虑闰年的问题,再接着判断是否闰年,如果非闰年总天数减一,是闰年不变,因为在开始计算的过程中时默认闰年的。
代码:
main()
{
int day,month,year,sum,leap;
clrscr();
printf("\nplease input year,month,day\n");
scanf("%d%d%d",&year,&month,&day);
switch(month)
{
case1:sum=0;break;
case2:sum=31;break;
case3:sum=59;break;
case4:sum=90;break;
case5:sum=120;break;
case6:sum=151;break;
case7:sum=181;break;
case8:sum=212;break;
case9:sum=243;break;
case10:sum=273;break;
case11:sum=304;break;
case12:sum=334;break;
default:printf("data error");break;
}
sum=sum+day;
if(year%400==0||(year%4==0&&year%100!=0))
leap=1;
else
leap=0;
if(leap==1&&month>2)
sum++;
printf("it is the %dth day.",sum);
getch();
}_
案例4:求200-300之间所有素数,每5个换行。
程序分析:先将1挖掉(为什么?因为1不是素数)
用2去除它后面的各个数,把能被2整除的数挖掉,
用3去除它后面各数,把3的倍数挖掉,用循环体分别将4、5…各数作为除数去除这些数以后的各数。直到除数后面的数已全部挖掉为止
代码:
main()
{
int i,j,n=0;
clrscr();
for(i=200;i<=300;i++)
{
for(j=2;j<=i;j++)
if(i%j==0)
break;
if(j>=i)
{
printf("%4d",i);
n++;
}
if(n%5==0)
printf("\n");
}
getch();
}_
案例8:打印输出九九乘法表。
解题步骤:
1、定义行变量、列变量。
2、循环输出行乘列的值。
3、每行最后输出一个换行符。
程序分析:
两个循环嵌套时,第一个循环语句为外循环,第二个循环语句为内循环,外循环执行一次,内循环从头到尾执行一遍(可能执行多次循环体),因此本题的执行次数为:1+2+3+4+5+6+7+8+9=45次。
代码:
结果:
实训四 数组的定义和使用:
案例3、打印杨辉三角,输出前10行数据。
解题步骤:
(1) 定义变量;
(2) 确定数组的行与列;
(3) FOR循环给数组赋值。
(4) 输出这个数组。
程序分析:
杨辉三角是(a+b)的n次幂的展开式系数,如:
(a+b) 系统数是1 1
(a+b)2展开后的系数是 1 2 1
(a+b)3展开后的系数是 1 3 3 1
从而得到杨辉三解的系数规律(指数为n):
1、共有n+1组系数,且第K组(从0)开始有K+1个数。
2、每组最后一位与第一位均为1
3、若用二维数组存放系数,每行存放一组,则从第二行开始除最后一个数与第一个数外,每个数都是其所在行的前一行同一列与前一列之各。
代码:
#include "stdio.h"
main()
{
int i,j,a[10][10];
for(i=0;i<10;i++)
for(j=0;j<10;j++)
a[i][j]=0;
for(i=0;i<10;i++)
{
a[i][0]=1;
a[i][i]=1;
}
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
printf("%d ",a[i][j]);
printf("\n");
}
结果:
实训五 函数的应用:
案例3:用函数和递归实现求n!
程序分析:
(1)首先在有限递归中,必须有一个测试避免递归调用的条件,即当满足该条件时,不再递归。而在递归函数中,应该是先测试,后进行递归调用。在本例中,if语句就是这种测试条件,当n等于0时,则不再递归,即退出该递归函数。
(2)在递归函数中,至少要有一个递归调用的语句,并且该语句的参数应该逐渐逼近递归结束的条件。其中,该语句参数n-1是逐次减1,当n为0时,则不再调用递归函数。
(3)完成该递归函数。
代码:
结果:
实训六 指针的应用
案例1:分析并对比如下2个程序,写出运行结果,并上机验证。
1.1 main()
{int *p1,*p2,*p,a,b;
a=5;b=9;
p1=&a;p2=&b;
if(a<b){p=p1;p1=p2;p2=p;}
printf(“a=%d,b=%d\n”,a,b);
printf(“max=%d,min=%d”,*p1,*p2);}
1.2 main()
{int *p1,*p2,p,a,b;
a=5;b=9;=
p1=&a;p2=&b;
if(a<b){p=*p1;*p1=*p2;*p2=p;}
printf(“a=%d,b=%d\n”,a,b);
printf(“max=%d,min=%d”,*p1,*p2);}
结果:
a=5 , b=9
Max=9 , min=5
五、结论(小4宋体,约1500字)
1、收获:
(1)通过C语言实训,让我加深了对C语言的了解,而不只是单单的在课本中学到的那些理论,平时乏味的课程,通过自己动手亲自编写,变的生动有趣,而在自己动手的过程中,出现的问题很多,当一个程序写完以后,经常会有很多错误。不过,通过这几天的实训和小组讨论,逐渐让自己积攒了一些经验,有些错误可以很快就看出来。
(2)这次实训让我对C语言有了更深的认识,平时在课堂上学到的东西可以自己动手编写,将其转化成一些实用的技能。如果是一个程序写完一处错误也没有,会有种成就感,于是兴趣就来了,兴趣来了,自然学的东西也就多了,能把理论变成实际的技能,让我对C语言有了较多的兴趣和更深层的认识。
(3)C语言是一个有序的学习,学了最基本的替换,然后扩展到循环,嵌套,条理很清楚,不是一个零散的知识,而是一门较有逻辑思维能力培养的学科。
2、不足:
(1)通过实训我也知道了自己的不足,存在的很多问题。比如自己写的写的小程序出了问题,不会解决了就叫同组的帮忙,虽然说一定意义上增加了同学之间的感情,但是会养成一种依赖的心理,碰到问题了个想到的是求助而不是自己独立解决,所以以后要多多锻炼自己的信心和增加自己的能力,争取做到没有别人帮助的时候也可以完成一些简单的程序编写与错误排除。
(2)还有自己的基础知识不扎实,遇到的问题,没有很好的逻辑思维,亲自编写一个陌生的程序的时候会有种无法下手的感觉,找不到突破口。通过实训,逐渐理清了顺序,对于简单的程序和一些相对比较繁琐的嵌套,循环,不在是看着一头雾水。其实只要理清了思路,把基础知识掌握了,然后有条不紊的分析,一步一步理解,感觉C语言还是很有意思的课程。
(3)自己亲自动手编写程序让我增加了对C语言程序开发环境的了解,在上课的时候老师就讲,学习C语言最重要的是学习C语言的逻辑思维,不管以后从事什么行业,学习C语言都对自己的职业很有帮助,如果是从事编程工程工作的话,就更有帮助了,即使以后的编程工作可能不用C语言,但是拥有扎实的C语言基础是对工作很有用的。当初在初步接触C语言的时候,看着一堆“奇形怪状”的符号,觉得甚是无聊,通过这次实训,摆脱了那种似懂非懂的状态!
六、致谢
感谢学校安排这次实训和老师的耐心讲解,让我学到了很多知识,在实训过程中,同学之间的相互探讨,老师的循循善诱,最终让我们达到了举一反三的效果,在学知识的同时,也增加了同学老师之间的感情。希望以后还会有更多类似的实训课程,在有限的大学时间内学到更多的实用技能,为以后的工作打下一个良好的基础。
第二篇:C语言实习指导题解
C语言程序设计实习指导及报告
C语言课组编写
学院 :
专业班级 :
学
姓号 : 名 :
任课教师 :
西北农林科技大学信息工程学院
20xx年10月
西北农林科技大学信息工程学院实习报告
前 言
程序设计是实践性很强的过程,实习的目的是为了巩固所学知识,培养、提高实际上机动手能力和严肃认真的科学工作态度,而程序设计是创造性的劳动,因此需要编程人员全身心地投入,充分发挥主观能动性,认真做好每一次实习。
每道题没有唯一解,只要掌握了基本的方法和技巧,加上自己创造性的工作,就一定能够编写出各种各样的好程序。任何程序最终都必须在计算机上运行,以检验程序的正确与否。因此在学习程序设计中,一定要重视上机实践环节,通过上机可以加深理解C语言的有关概念,巩固理论知识,另一方面也可以培养调试程序的能力与技巧。为了加强基础知识和语言主干结构的学习,深刻理解和掌握教材内容,减少实习时的盲目性,特编写本实习指导书。
为方便内容组织,每个实习由实习目的、实习内容和注意事项三部分组成。下面对每次实习提几点具体要求:
(1) 实习前应进行充分的准备,做到心中有数。要弄懂教材中的相关知识和例题,深刻理解教材中涉及到的知识点及程序设计方法,根据实习要求,对题目进行分析,选择适当的算法、事先编写好程序。上机前一定要仔细检查程序(称为静态调试),直到找不出错误(包括语法错误和逻辑错误)为止。分析可能遇到的问题及解决的办法。准备几组测试程序的数据、写出预期的结果,以便发现程序中可能存在的错误。
(2) 在实习中,应该对编写好的程序使用预先准备好的测试数据运行程序,观察是否能得到预期的结果(称为动态调试)。对于实习中出现的问题进行仔细的分析,找出解决办法,调试程序排除各种错误,直到得到正确结果。对运行结果要做好记录,为写实习报告做好准备。调试过程中,要充分利用系统提供的各种调试手段和工具,例如:单步跟踪、设置断点、观察变量值等。对出现的错误要善于思考,勤于分析,尽量自己动手解决问题,逐渐提高自主分析问题和解决问题的能力。
(3) 实习结束后,要整理实习结果,并应根据问题、解决办法和运行结果,对本次实习及时进行认真分析和总结,撰写出实习报告。
以这种方式提交实习报告书还处于尝试阶段,限于作者水平,其中疏漏在所难免,敬请各位老师和同学批评指正。联系地址:Email:hl@或Email:cy@ 。
作者
20xx年10月
西北农林科技大学信息工程学院实习报告
目 录
实习一 C语言概述 .................................................................................................................................... - 1 - 实习二 顺序结构 ......................................................................................................................................... - 4 - 实习三 选择结构 ......................................................................................................................................... - 6 - 实习四 循环结构程序设计 ....................................................................................................................... - 9 - 实习五 数 组 ........................................................................................................................................... - 14 - 实习六 函数调用 ..................................................................................................................................... - 21 - 实习七 指 针 ......................................................................................................................................... - 24 - 实习八 用户建立的数据类型 ................................................................................................................. - 31 - 实习九 文件操作 ..................................................................................................................................... - 36 -
西北农林科技大学信息工程学院实习报告
实习名称:实习一 C语言概述
实习时间:第 周 成绩:
一、实习目的
1.熟悉C语言集成开发环境的使用方法,学会独立使用该系统;
2.掌握C语言源程序的编辑、编译、连接、调试和运行过程;
3.通过运行、编写简单的C语言源程序,学习程序编写方法,了解C源程序的特点;
4.理解C语言的数据类型、运算符及表达式等基本概念。
二、实习要求
⒈ 实习前认真学习第1、2章内容;
⒉ 对实习内容中给定的题目上机前先进行程序的编写和数据的准备;
⒊ 上机编辑、调试、运行程序,并保存最终程序,然后认真撰写实习报告;
三、实习内容
1.在实习的机器C上盘以自己姓名的拼音创建一个文件夹,以便将所有实习内容保存在
自己的文件夹中,你建立的文件名为: c:\huanglin 。
2.认真阅读教材P10-15内容,学习VC++6.0集成开发环境的使用方法,掌握建立、打开、保存、运行一个C源程序的操作方法,注意完成以下内容的填写。
(1)输入完教材图1-5中所示的源代码后保存,你保存的文件名为: c1-1.c
(2)通过资源管理器查看你自己的文件夹,此时其中有 1 个文件。
(3)编译源代码(快捷键为CTRL+F7),结束后再通过资源管理器查看你的文件夹,发现
除源程序文件外,多了 3 个文件和 1 个文件夹,多出的文件夹名为: Debug 。
(4)连接程序(快捷键为F7),结束后查看新增加的文件夹中又多在第(3)步的基础上
多出了 3 个文件。其中最重要的是程序编译结果文件,其扩展名为EXE。
3.利用File菜单中的“Close Workspace”命令结束前一个程序的调试,再新建一个C++
源程序,文件名规定为c1-2.c,验证我们学习所使用的C编译系统VC++6.0对不同类型变量所分配的存储空间。程序代码如下:
#include <stdio.h> void main()
- 1 -
西北农林科技大学信息工程学院实习报告
{ printf("%d,%d,%d\n",sizeof(int),sizeof(short),sizeof(long)); }
运行后程序结果为: 4,2,4
在资源管理器中查看文件c1-2.c、c1-2.obj、c1-2.exe分别被保存的路径为:
c:\huanglin\c1-2.c、c:\huanglin\Debug\c1-2.obj 、c:\huanglin\Debug\c1-2.exe
4.验证整型数据的溢出。在VC中运行教材例2.3代码后,并没有出现教材所说的溢出情
况,要想看到VC中的溢出,可将变量a的值改为 2147483647 。
5.P39习题5程序运行后的结果为:
aa bb cc abc
AN
如果删除某一语句行末尾的“;”后再编译,出现的错误提示为:
error C2146: syntax error : missing ';' before identifier 'printf'
6.P39习题6程序部分代码如下,请填空完成程序:
#include <stdio.h>
void main() {
char c1=?C?,c2=?h?,c3=?i??n??a? //给变量赋值
c1=c1+4; c2= ;c3= //计算变量的新值
printf(“%c%c%c%c%c\n”,c1,c2,c3,c4,c5); } //设置输出结果的类型
7.编程求P39习题8表达式结果,程序部分代码如下,请填空完成程序:
(1) #include <stdio.h>
void main() {
float x=2.5,y=4.7;
int a=7;
printf(“% \n”,x+a%3*(int)(x+y)%2/4); } //设置输出结果的类型
(2) #include <stdio.h>
void main() {
x=3.5,y=2.5; //给变量填类型
a=2,b=3; //给变量填类型
printf(“% \n”,x+a%3*(int)(x+y)%2/4); }//设置输出结果的类型
8.P39习题9程序运行结果为:
9,11,9,10\n
- 2 -
西北农林科技大学信息工程学院实习报告
四、实习总结
五、注意事项
1. 上机实习前一定要认真阅读教材相关内容,结合实习步骤整理出实习涉及的内容。从本次实习开始大家应该明白,上机实习的目的有两个,其一是加深对知识点的理解;其二是验证自己学习过程中的一些疑问。对于教材中的内容,如果已经理解的可以跳过,对于有疑问的内容才需要上机调试验证。
2. 对程序的可靠性要进行多方面的测试,有时要和别的程序对比运行结果,甚至要用手算。
3. C语言程序编写及上机调试步骤:
⑴ 先根据题意决定算法,并用笔在纸上画出程序流程图;
⑵ 根据流程图编写源程序代码,经人工检查无误后才能上机。对自己有疑问的地方,应事
先作好标记,以便上机时给予注意。初学时切忌不编程序或抄袭别人的程序,应养成良好的习惯和严谨的科学作风;
⑶ 准备好测试数据,写出预期结果(必要时应准备多组测试数据);
⑷ 将源程序代码输入计算机;
⑸ 再次检查程序有无错误(包括语法错误和逻辑错误);
⑹ 运行和调试。进行编译和连接,仔细分析编译信息,如有错误应找出原因并记录,然
后改正、再进行编译和连接??,直到输出结果正确为止。对出现的问题应仔细分析,一般应尽量独立处理,尤其是对“出错信息”,应学会自己分析判断,不要轻易问别人,这是学会调试程序的良方;
⑺ 程序调试过程中,应记录出现的各种状况、解决的方法,为撰写实习报告作好准备。
程序运行通过后,应将结果与事先的预期结果进行对比分析;
⑻ 对于教材上的例题输入运行后,自己可以再修改、调试,例如:故意改成错的,然后分
析其编译和运行情况;
⑼ 将每次实习的所有内容调试好后,可将自己文件夹中扩展名为“.c”的C语言源程序文
件保留,将其它文件全部删除,然后压缩保存在自己的邮箱中。
- 3 -
西北农林科技大学信息工程学院实习报告
实习名称:实习二 顺序结构
实习时间:第 周 成绩:
一、实习目的
1.掌握基本输入/输出函数和各种运算符、表达式的功能和使用方法;
2.掌握各种类型数据的输入/输出方法,能正确使用各种格式转换符和控制符;
3.准确理解各种运算符的优先级;对各种表达式及其运行结果必须有清晰的认识;
4.通过上机,了解程序中常见的语法,掌握基本的程序调试技术。
二、实习内容
1.新建源程序文件c2-1.c,录入以下程序,将编译过程中出现的warning信息及你自己理解的汉语意思写在对应程序行的右侧:
#include <stdio.h>
void main()
{ double d=123.456789e100;
float f=d; warning C4244: 'initializing' : conversion from 'double ' to 'float ', possible loss of data printf("%f\n",f); 从双精度转换为单精度,可能丢失数据 }
2.重新录入以下程序,将编译过程中出现的warning信息及你自己理解的汉语意思写在
对应程序行的右侧:
#include <stdio.h>
main()
{ char i=289; 'initializing' : truncation from 'const int ' to 'char ' 将整型常量截断赋给字符型变量 printf("%c\n",i);
}
3.调试教材例3.1及3.2,整理出以下内容:
(1)如果将有符号整数赋给无符号整型变量,要注意的是:
在vc中当有符号整数<0时,可造成数据的不正确。
(2)若将无符号整数赋给有符号整型变量,在VC中当数据超出 2147483647 范围时,数
据将会出现溢出。
4.调试例3.5,认真理解例题前面那一段话的含义。
5.调试例3.6和3.7,简要总结“%f”和“%e”的输出特点如下:
- 4 -
西北农林科技大学信息工程学院实习报告
6.认真阅读教材P55-P58内容,总结scanf函数中格式控制符对输入数据的控制作用。假设需要为三个整型变量a,b,c用scanf函数赋值,请写出你喜欢的正确输入格式: 控制符与数据类型必须相符,否则得不到正确的输入数据
scanf(“%d%d%d”,&a,&b,&c);
7.写出P67习题3程序的运行结果
8.P68习题7程序部分代码如下。不要改变与输入输出有关的语句,填空完善程序。 分析:输入华氏温度f,计算并输出相应的摄氏温度c(保留2 位小数)的公式为:
c = 5/9(f-32).
测试数据:当输入的数据为 17.2 (是华氏温度)
预测输出:运行结果应是 The temprature is -8.22
程序代码:#include <stdio.h>
int main( ) {
double f, c;
scanf("%lf", f);
// 计算c值
} // 按要求输出计算结果
三、实习总结
- 5 -
西北农林科技大学信息工程学院实习报告
实习名称:实习三 选择结构
实习时间:第 周 成绩:
一、实习目的
1.掌握C语言的六种关系运算符和三种逻辑运算符的使用方法;
2.了解C语言表示逻辑量的方法(以“0”代表“假”,以1或非“0”代表“真”);
3.深刻理解选择结构,熟练掌握和应用if语句的三种基本形式和嵌套形式;
4.掌握switch语句的规则、功能与特点,能准确构造表达式;
5.通过上机,理解选择结构程序中常见的语法及逻辑错误,掌握基本的程序调试技术。
二、实习内容
1.完善左侧为P95习题4画出的流程图,并在右侧写出程序的代码。
测试数据: -2 0 1 预期结果:1
100 -10 25 100
13 256 1
注:虚框中填写将找出的最大数存放在max中并输出的流程图。
2.输入一个学生的数学成绩,如果它低于60,输出“Fail”,否则,输出“Pass”。程序
填空,不要改变与输入输出有关的语句。
测试数据: 第一次输入第二次输入 59
预期结果: 第一次的结果是第二次的结果是 Fail
- 6 -
西北农林科技大学信息工程学院实习报告
程序代码:#include <stdio.h>
int main( )
{ int mark;
scanf("%d",&mark); // 输入成绩,以下进行判断并输出结果
if (mark>=60) printf("Pass\n");
else printf("Fail\n"); }
3.为P95习题6写出程序、测试数据(5种不同情况)、预测结果及上机实习后的验证结果。
程序 #include "stdio.h"
void main()
{ float grade;
printf("输入成绩:");
scanf("%f",&grade);
switch ((int)(grade/10))
{ case 10:
case 9: printf("A\n");break;
case 8: printf("B\n");break;
case 7: printf("C\n");break;
case 6: printf("D\n");break;
default: printf("E\n");
}
}
测试数据 100 98 88 71 66 45
预测结果 A A B C D E
上机结果:同预测结果。
4.为P95习题10,写出代码、4组测试数据、预测结果及上机实习后的验证结果。 提示:判断输入点(x,y)的数据是否在圆内,即为求两点间的距离是否小于等于1,
程序 #include "stdio.h"
#include "math.h"
void main()
{ float x,y,s;
printf("输入圆心值:");
scanf("%f%f",&x,&y);
s=sqrt((fabs(x)-2)*(fabs(x)-2)+(fabs(y)-2)*(fabs(y)-2));
if (s<=1) printf("该点的建筑高度为10m\n");
}
测试数据 0 0 2 -2 2 3 3 3
预测结果 × √ √ ×
- 7 - (|x
|?2)2?(|y|?2)2?1
西北农林科技大学信息工程学院实习报告
上机结果:同预测结果。
5. 输入一个字符,如果它是大写字母,输出相应的小写字母;如果它是小写字母,输出相应的
大写字母;否则,原样输出。程序填空,不要改变与输入输出有关的语句。 测试数据:3F=y (输入的3 个字符是'F', '=', 'y') 预测输出:f=Y
程序代码:#include <stdio.h> void main( ) { char ch; int i,n;
scanf(“%d”,&n); for (i=1;i<=n;i++) {ch=getchar();
/*以下填写判断和输出程序*/
if (ch>=?A? && ch<=?Z?) printf(“%c”,ch+32); else if (ch>=?a? && ch<=?z?) printf(“%c”,ch-32); else printf(“%c”,ch); }
}
6.以下程序是利用海伦公式求三角形面积,请在有问题语句行的左侧简要写出程序存在的问题,并在后面写出你认为完美的程序。
#include <stdio.h> main() { int a,b,c,p,s; p=(a+b+c)/2;
s=sqrt(p*(p-a)*(p-b)*(p-c)); printf("please input a,b,c:"); scanf("%d%d%d",a,b,c); printf("s=%d",s); }
自己认为完美的程序 #include <stdio.h>
main() { int a,b,c,p,s;
printf("please input a,b,c:"); scanf("%d%d%d",&a,&b,&c); p=(a+b+c)/2;
if (a+b>c && a+c>b && c+b>a) {s=sqrt(p*(p-a)*(p-b)*(p-c)); printf("Area =%d",s); } elseprintf("No area."); }
三、实习总结
- 8 -
西北农林科技大学信息工程学院实习报告
实习名称:实习四 循环结构程序设计
实习时间:第 周 成绩:
一、实习目的
1.熟练掌握C语言的三种循环语句:for循环、while循环、do-while循环;
2.对以上三种循环结构形式进行分析比较,掌握各自的特点及异同之处,通过程序设计的训练,深刻理解循环结构的思想;
3.掌握运用循环结构、循环嵌套,结合分支结构编程,解决求和、穷举、递推等问题;
4.熟悉循环执行的过程,掌握优化程序、提高程序运行效率的基本思想和方法;
5.通过上机,了解循环结构程序中常见的语法及逻辑错误,掌握基本的程序调试技术。
二、实习内容
1.认真阅读教材第5章有关内容,验证其中自己难以理解的例题程序段。
2. P113习题2程序部分代码如下,填空完善程序,不要改变有关的语句。
输入一个正整数repeat (0<repeat<10),做repeat 次下列运算。
测试输入:2 (repeat=2) //对两个字符串进行统计
Old building room 123. //第一个字符串
Programming is fun //第二个字符串
预期结果:letter=15, blank=3, digit=3, other=1
letter=16, blank=2, digit=0, other=0
程序代码:#include <stdio.h>
int main( )
{ int ri, repeat; //repeat代表欲测试字符串的个数
int blank, digit, letter, other; //分别存放空格、数字、字母及其它符号的个数
char c;
scanf("%d", &repeat);
getchar();
for(ri=1; ri<=repeat; ri++)
while((c=getchar())!= ) //逐个字符输入,接收并判断和统计 { if (c==? ?) blank++; else if (c>=?A? && c<=?Z? ||c>=?a? && c<=?z?) letter++; else if (c>=?0? && c<=?9?) digit++; else other++; }
- 9 -
西北农林科技大学信息工程学院实习报告
}
}
3.为P113习题3填空程序程序,不要改变有关的语句。
分析:求a+aa+aaa+aa?a(n 个a)之和,实际为重复执行tn=tn*10+a表达式n次,特别注意
tn的初始值为a。而将保存在变量tn中的每次的计算结果加起来便是所求的和。 测试数据: 2 3 (a=2, n=3)
8 5 (a=8, n=5)
预测结果: 246 (2+22+222)
98760 (8+88+888+8888+88888)
程序代码:#include <stdio.h>
void main()
{ int ri, repeat; // repeat为欲测试数据的组数
int i, n;
long int a, sn, tn; //tn存i个a组成的值、sn是多项式前i项之和
scanf("%d", &repeat);
for(ri=1; ri<=repeat; ri++) //为两组a、n求和
{ scanf("%ld%d", &a, &n); //
tn=a; sn=0; for (i=1;i<=n;i++) { sn=sn+tn; tn=tn*10+a; } printf("%ld\n",sn); } }
4.为P113习题6程序填空,不要改变有关的语句。写出上机实习结果。
#include "stdio.h" 程序运行结果:
int main( ) 153 370 371 407
{ int ri,repeat; //此说明在程序中没有用到,无妨
int i, digit, g, b, q, sum;
for(i=100;i<=999;i++)
{ digit=i; //要判断的数
/*以下填空将从digit中分离出来的个、十、百各位数字分别存放在g, b, q三个变量中,其立方和存放在变量sum中,并判断是否与digit相等,若相等则输出*/
g=digit%10; q=digit/100; b=digit/10%10; //或 b=(digit-q*100-g)/10;
sum=g*g*g+b*b*b+q*q*q; //或 sum=pow(g,3)+ pow(b,3)+ pow(q,3); 此时要用math.h 头文件 if (sum==digit) printf(“%5d”,digit);
}
}
5.为P113习题8程序填空,不要改变有关的语句,输出保留2 位小数。
分析:输入一个正整数repeat (0<repeat<10),做repeat 次运算;
分析2/1+3/2+5/3+8/5 +...可知,该序列从第2 项起,每一项的分子是前一项分子与分
- 10 -
西北农林科技大学信息工程学院实习报告
母的和,分母是前一项的分子。
测试输入:3 (repeat=3)
1 5 20 (3个n值)
预测结果:2.00 (第1 项是2.00)
8.39 (前5 项的和是8.39)
32.66 (前20 项的和是32.66)
程序代码:#include <stdio.h>
int main( )
{ int ri, repeat;
int i,n;
float a,b,s,t;
scanf("%d", &repeat);
for(ri=1; ri<=repeat; ri++)
{ scanf("%d", &n);
for(a=2,b=1,s=0,i=1;i<=n;i++)
{s=s+a/b;t=a;a=a+b;b=t;} // 求前n项的和
printf("%.2f\n",s);
}
}
6.写出P113习题10程序代码及上机实习结果。
#include <stdio.h> 实习结果
int main( )
{ int i, x;
x=1;
for (i=10;i>=1;i--)
x=2*(x+1);
printf(“total=%-5d\n”,x);
}
之间的偶数符合此规律。
提示:先找出其中的一个素数,然后判断另一半(=偶数-此素数)是否素数。是,输出;
否则,重新进行判断。
要求:一个偶数可能有多对素数和,如:20=3+17=7+13=13+7=17+3,仅输出一对即可。
#include <stdio.h>
int main( )
{ int i,j,n,m;
for(i=6; i<=106; i+=2)
{ for(m=3;m<=i/2;m++) //因为仅求一对素数,所以在前二分之一范围内查找即可 { for (j=2;j<=m-1;j++) //找第一个素数
if (m%j==0)break;
- 11 - 7.选做题 歌德巴赫猜想:
}
}
三、实习总结 - 12 -
西北农林科技大学信息工程学院实习报告
四、注意事项
⒈ 循环前有时需要为某些变量赋初值,一般情况下:
① 求和需要令累加器变量初值为0;
② 求阶乘需要令累积器变量初值为1;
③ 计数器变量的初值应为0;
否则会因变量初值的不确定,导致运行结果出现错误。
⒉ 要防止发生死循环,写程序时必须保证控制循环的表达式的值是不断改变的,并最终会
变到能使循环条件为假而结束循环。其中:
① for循环一般通过修改表达式3,使表达式2为假来结束循环;
② 对于while循环、do while循环,是在循环体内加入使控制循环进行的表达式能发
生变化的语句,使循环趋于结束。
⒊ 正确理解循环嵌套:外层循环变量每取一次值,内层循环变量从头到尾取一遍值。 ⒋ 一般来说,循环结束后循环变量的值并不等于终值,而是沿变化方向超过终值的。 ⒌ 对for和while循环,若循环体一次也不执行,肯定是一开始循环条件就不成立。如:
⑴ ?? ;i=101;for (;i<=100;i++) {?},虽然循环没有为i赋值,但实际i>100; ⑵ for (i=100;i<10;i- -) {?},从表达式2可见条件一开始就不成立;
⑶ ?i=101;?.;while (i<=100) {??.};原因同⑴;
⒍ 对于do-while循环,无论如何循环体最少也要执行一次,因为它是先执行后判断的。 ⒎ 如果循环控制变量在循环执行过程中永不发生变化或条件表达式恒为真,则循环就会
变成死循环。遇到这种情况,可用
可能造成死循环:
⑴ 漏掉循环控制变量值的修改语句。如:
for(i=1;i<=100;) {?}; /*缺少表达式3*/
如果循环体中也没有i的增值语句,则i的值永远不会超过终值100。
⑵ 循环体中对循环控制变量重新赋值。如:
for(i=1;i<=100;i++) {?;i=4; ?};
由于循环体中i的值被改为4,所以其值永远不会大于终值100,程序无法终止。 ⑶ 表达式2设置错误。如:想循环10次,写成了;
for(i=1;i=10;i++) {?};
表达式2是赋值表达式,每次判断时i的值赋为10,条件恒为真,程序陷入死循环; ⑷ 循环变量的终值达到变量类型所允许的边界值,经表达式3运算又回到了域内。如
计算:
若将循环控制变量设为int型,并作为分母来使用,在TC中则可能出现这种情况。
- 13 -
西北农林科技大学信息工程学院实习报告
实习名称:实习五 数 组
实习时间:第 周 成绩:
一、实习目的
⒈ 熟练掌握一维、二维数组的定义、数组元素的赋值、引用和输入输出方法;
⒉ 理解数组的作用及下标的表示方法,学会灵活运用数组元素下标,能用数组优化程序; ⒊ 能正确使用字符数组存储字符串,掌握字符串函数的使用方法及字串的输入输出方法; ⒋ 熟练掌握选择、循环结构和数组的综合应用;
⒌ 熟悉与数组有关的算法,如排序、查找等。
二、实习内容
1.认真阅读教材第6章内容,并对其中理解有困难的程序段上机进行调试。
2.完善P138习题2程序代码,不要改变与输入输出有关的语句。
测试数据:第一组 第二组 第三组
4 5 1 7 6 3 1 2 3 5 4 3 2 1 0 //每组第一个数为本组数的个数
预期结果:第一组 第二组 第三组
7 6 5 1 3 2 1 4 3 2 1 0
程序代码:#include <stdio.h>
int main( )
{ int i, index, k, n, temp;
int a[10];
scanf("%d", &n); //输入数据的个数
for(i=0; i<n; i++)
scanf("%d", &a[i]);
/*以下填写排序程序*/
for(i=0; i<n-1; i++)
{k=i;a[k]=a[i];
for(index=i+1; index<=n-1; index ++)
if (a[k]<a[index]) k=index;
if (k!=i){ temp=a[k];a[k]=a[i];a[i]=temp;}
for(i=0; i<n; i++)
printf("%d ", a[i]);
printf("\n");
}
3.完善P138习题3程序代码,不要改变有关的语句。
- 14 -
西北农林科技大学信息工程学院实习报告
分析:主对角线为从矩阵的左上角至右下角的连线,在数组中即指行列下标相同的元素。 测试数据: 第一组 第二组
1 2 3 0 4 5 0 0 6 2 1 0 0 -8 2 10 5 9
预测结果: 第一个第二个
11 3
程序代码:#include "stdio.h"
#include "math.h"
#define N 3
int main( )
{ int a[N][N], i,j,n,sum=0;
scanf("%d",&n);
for (i=0;i<n;i++)
for (j=0;j<n;j++)
scanf("%d",&a[i][j]);
/*以下填写求对角线元素和的程序段*/
for (i=0;i<n;i++)
sum+=a[i][i]; //对角线元素的行列下标相同
printf("Sum=%d\n",sum);
}
4.以下为 P138习题5程序部分代码,完善程序,不要改变有关的语句。
分析:欲实现逆序,只需将前二分之一个数据与从最后往前的数据逐个交换即可。
测试输入:8 6 5 4 1
预测输出:1 4 5 6 8
程序代码1:程序代码2:
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> int main( )
int main( ) { int i, n, temp, a[10]; { int i, n, temp, a[10]; scanf("%d", &n); //欲输入数据的个数 scanf("%d", &n); //欲输入数据的个数 for(i=0; i<n; i++) for(i=0; i<n; i++) scanf("%d", &a[i]); printf("%5d", a[i]= rand()%50+10); /*以下为实现逆序的代码*/ printf("\n");
for (i=0;i<n/2;i++) /*以下为实现逆序的代码*/
{temp=a[i]; a[i]=a[n-i-1]; a[n-i-1]=temp;} for (i=0;i<n-i-1;i++)
{temp=a[i];a[i]=a[n-i-1];a[n-i-1]=temp;} for(i=0; i<n; i++)
for(i=0; i<n; i++) printf("%d ", a[i]); printf("%5d", a[i]); printf("\n"); } printf("\n"); } 5.为P138习题6编写程序代码。 } 分析:杨辉三角形第一列和对角线上的数据都为1,即a[i][0]=a[i][i]=1;其余位置数据
的计算公式为a[i][j]=a[i-1][j-1]+ a[i-1][j],即上一行前一列和当前列的和。
程序代码:#include <stdio.h>
- 15 -
西北农林科技大学信息工程学院实习报告
void main ()
{ int i,j,a[11][11],n;
scanf("%d",&n);
for (i=0;i<n;i++)
{a[i][0]=1;a[i][i]=1;}
for (i=2;i<n;i++)
for (j=1;j<i;j++) //即仅给三角形的一半元素赋值
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(i=0;i<n;i++)
{ for (j=0;j<=i;j++)
printf("%-5d ",a[i][j]); //输出成直角三角形
printf("\n");
}
}
或 #include <stdio.h>
void main ()
{ int i,j,a[11][11],n,k;
scanf("%d",&n);
for (i=0;i<n;i++)
{a[i][0]=1;a[i][i]=1;}
for (i=2;i<n;i++)
for (j=1;j<i;j++) /*即三角形仅一半元素有值*/
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(i=0;i<n;i++)
{k=(n/2-i)*3+30; //为使输出成等腰三角形
for (j=0;j<k;j++) //输出三角形每行左端的空格
printf(" "); //输出空格
for (j=0;j<=i;j++)
printf("%-5d ", a[i][j]);
printf("\n");
}printf("\n"); printf("\n");
}
6.判断a 是否上三角矩阵,若是,输出"YES", 否则, 输出"NO"。完善程序,不要改变有关语句。
分析:上三角矩阵即主对角线以下的元素都为0。主对角线为从矩阵的左上角至右下角的连线。 测试数据: 第一组 3 1 2 3 0 4 5 0 0 6 (第一个数据3赋给n,表示是3行3列的矩阵)
第二组 2 1 0 -8 2 (n=2)
预测结果: 第一组 YES
第二组 NO
程序代码:#include "stdio.h"
#include "math.h"
- 16 -
西北农林科技大学信息工程学院实习报告
int main( )
{ int a[6][6],flag=1,i,j,n; //flag=1即先假设是上三角矩阵
scanf("%d",&n);
for (i=0;i<n;i++)
for (j=0;j<n;j++)
scanf("%d",&a[i][j]);
/*以下填写判断是否上三角矩阵*/
for(i=0;i<n;i++)
{ for (j=0;j<i;j++)
if (a[i][j]!=0) {flag=0;break;} //当主对角线以下元素有不为0时
if (flag==0) break;}
if (flag) printf("YES\n"); //如果条件成立即flag≠0
else printf("NO\n");
}
7.完善P139习题12程序代码,不得改变有关的语句。
说明:连续输入一批以 # 结束的字符串(字符串的长度不超过80),遇 ## 则结束全部输入。
将每个字符串中的字母用下面列出的对应字母替换, 其余字符不变, 输出替换后的字符串。
原字母 → 对应字母
A → Z B → Y C → X D → W …… X → C Y → B Z → A
a → z b → y c → x d → w …… x → c y → b z → a
测试数据:A flag of USA#IT12#oueiaba## (连续输入3 个字符串)
预计输出:Z uozt lu FHZ
RG12
lfvrzyz
程序代码:#include "stdio.h"
#include "string.h"
#define MAXLEN 80
int main( )
{ int i,k;
char ch,oldch,str[MAXLEN];
oldch=' ';
while((ch=getchar())!='#' || oldch!='#') //
{ k=0;
while(ch!='#'&& k< MAXLEN-1)
{ str[k++]=ch;
ch=getchar();
}
oldch='#'; //当一个串结束后,让oldch='#',为外循环判断两个#做准备
str[k]='\0'; //一个串结束
/*以下填入转换程序*/
- 17 -
西北农林科技大学信息工程学院实习报告
k=0;
while (str[k]!='\0')
{ if ((str[k]>='A') && (str[k]<='Z'))
str[k]=155-str[k];
//(26-i+1),其中26即为第26个字母,ASCII码值为90、i即str[k]为第i个字符,i=str[k]-65+1,
则(26-i+1)=90-(str[k]-65+1)+1=155-str[k]
else if ((str[k]>='a') && (str[k]<='z'))
str[k]=219-str[k]; //对小写字母(26-i+1),第26个字母的ASCII码值为122,其余解释同上 else
str[k]=str[k];
k++;
}
puts(str); //逐个串输出
}
}
8.写出P139习题13程序代码、测试字符串、预测结果及上机实习结果。
#include <stdio.h>
void main()
{ char s1[80],s2[40];
int i=0,j=0;
printf("input string1:");
scanf("%s",s1); //输入的串中不得有空格
printf("input string2:");
scanf("%s",s2); //输入的串中不得有空格
while (s1[i]!='\0')
i++; //计算出s1串中字符的个数
while(s2[j]!='\0')
s1[i++]=s2[j++]; //将s2串中的字符逐个存入s1串
s1[i]='\0'; //加上串结尾符
printf("\nThe new string is:%s\n",s1);
}
9.写出P139习题14程序代码、测试字符串、预测结果及上机实习结果。
#include <stdio.h>
void main()
{ int i,resu;
char s1[100],s2[100];
printf("input string1:");
gets(s1); //串中可以包含空格
printf("\ninput string2:");
gets(s2);
i=0;
- 18 -
西北农林科技大学信息工程学院实习报告
while ((s1[i]==s2[i]) && (s1[i]!='\0'))i++; //对应位置的字符逐个进行比较
if (s1[i]=='\0' && s2[i]=='\0')
resu=0; //若相同,返回0
else
resu=s1[i]-s2[i]; //若不相同,返回两个字符ASCII码的差值
printf("\nresult:%d.\n",resu);
}
三、实习总结
四、注意事项
1.数组是用一个统一的名字和有序下标来标识的一组类型相同的数据的集合;
2.数组元素下标从0开始,在内存占据一片连续的存储区域,每个元素等价于一个普通
变量;
3.运用数组可使程序精练。数组的奥妙和编程的灵活性全都体现在下标的灵活使用上。
下标可以是常量、变量、表达式,也可以是数组元素,甚至是函数;
4.使用数组时要注意:
⑴ 要先定义后引用,并且不能用变量定义数组的个数,即定义数组之前必须确定数组大小; ⑵ 要注意数组元素的初值。若数组元素定义后没赋值,其值可能是任意的;
⑶ 要记住数组的下标边界,下标越界后系统不会报错,虽然越界读是没有意义的,但越
界写可能引起数据、应用程序或操作系统的错误,使系统出现故障,甚至瘫痪。
5.C语言中没有字符串类型的变量,所以对于字符串只能用字符数组进行处理。
对于字符数组,赋值时,可以用赋值语句、键盘输入语句或初始化方式;
输出时,可用%c格式按元素输出字符,也可用%s格式整体输出字符串。
6.处理字符串最容易犯的三个错误是:
⑴ 不可用赋值语句为字符数组赋值,例如s="abcde"错,要用strcpy函数; ⑵ 不能用“= =”判断两个字符串是否相等,要用strcmp函数;
⑶ 不能用“+”连接两个字符串,如s=s1+s2,要用strcat函数。
7.内存中用空字符?\0?作为字符串结束标志,注意:
⑴ ?\0?是输出格式%s及字符串函数操作的需要。处理字符串时,第一个?\0?前面的所有字
符被视为一个字符串,不管其后面有多少个字符;
⑵ 系统在字符串常量(而不是字符数组)末尾自动加?\0?,用户不必另加。用strlen函数
测字符串长度时,?\0?不计算在内;
⑶ 对字符数组,?\0?有时是系统自动加的,有时必须由用户添加(见教材P153)。
8.使用字符串处理函数要注意参数的选取。参数允许是字符数组,有的还允许是字符串常
量,编程时要考虑是否加入结束标志?\0?或覆盖结束标志?\0?。
- 19 -
西北农林科技大学信息工程学院实习报告
9.定义字符数组时要留有余地,即留一个位置放?\0?。否则,处理时可能会产生错误。
10.使用字符串函数要在程序前面用命令行指定包含标准头文件string.h。
- 20 -
西北农林科技大学信息工程学院实习报告
实习名称:实习六 函数调用
实习时间:第 周 成绩:
一、实习目的
⒈ 掌握C语言库函数的调用方法、自定义函数的定义和使用方法;
⒉ 掌握函数实参与形参的对应关系、“值传递”和“地址传递”的意义、区别及使用方法; ⒊ 掌握函数的嵌套调用方法,了解递归调用的思想方法;
⒋ 理解变量的作用域概念,学会在程序中正确的定义和引用变量;
⒌ 掌握全局变量和局部变量、动态变量和静态变量的概念、区别和使用方法。
二、实习内容
1.认真阅读教材第7章内容,并对其中理解有困难的程序段上机进行调试。
2.以下程序可以完成P184习题1程序代码,请补充函数。
分析:设m和n的最大公约数为gys,最小公倍数为gbs=m×n/gys;
求最大公约数可用辗转相除法:①rem=m%n;②m=n;n=rem;③若rem=0,m是最大公
约数,程序结束;否则从①重复做起。
测试数据:9 6
预测结果:9和6的最大公约数为3
9和6的最小公倍数为 18
程序代码: #include <stdio.h>
int gys(int x,int y) /*求最大公约数函数*/
{int rem; while ((rem=x%y)!=0) {x=y; y=rem;} return y; }
int gbs(int x,int y)/*求最小公倍数函数,其中可以调用最大公约数函数*/
{
return
(x*y/gys(x,y));
}
main()
{ int m,n;
printf("please input m,n:");
scanf("%d%d",&m,&n);
printf("%d和%d的最大公约数为%d\n",m,n,gys(m,n));
- 21 -
西北农林科技大学信息工程学院实习报告
printf("%d和%d的最小公倍数为%d\n",m,n,gbs(m,n));
}
3.写一个判断素数的函数,在主函数中调用验证歌德巴赫猜想:任意一个充分大的偶数都
可以分解成两个素数之和。验证6~106之间的偶数符合此规律。
4.完成P185页习题9。提示:可以将一个整型数组作为函数参数,在函数中将统计结果可以放在这个数组中,并回传给主函数输出。
#include <stdio.h>
void main()
{void count(char str[ ],int t[ ]);//函数原型声明
char text[80]; //存放字符串的数组
int a[4]={0}; //保存统计结果的数组
printf("input string:\n");
gets(text); //输入字符串
count(text,a); //调用函数,实参为数组名
printf("\nletter:%d\ndigit:%d\nspace:%d\nothers:%d\n",a[0],a[1],a[2],a[3]);
}
void count(char str[ ],int t[ ])//函数,形参t数组与实参a数组占相同的存储单元
{int i;
for (i=0;str[i]!='\0';i++)
if ((str[i]>='a'&& str[i]<='z')||(str[i]>='A' && str[i]<='Z'))
- 22 -
西北农林科技大学信息工程学院实习报告
t[0]++;
else if (str[i]>='0' && str [i]<='9')
t[1]++;
else if (str[i]==32)
t[2]++;
else
t[3]++;
}
5.完善函数sort和parray。其中:parray用于输出一组整型数。sort用于实现对一组整
数按由小到大排序。函数头已经给出,请补充完整。
#include <stdio.h> #define SWAP(x,y) {t=x;x=y;y=t;}
void parray(int x[ ],int n) /*以上是宏定义,编译时引用进行对应参数的替换*/ { int i; void sort(int x[],int n)
for(i=0;i<n;i++) { int i,j,k,t;
printf("%-5d",x[i]); for(i=0;i<n-1;i++) //使用选择法排序
printf("\n"); { k=i;
} for(j=i+1;j<n;j++)
if (x[k]>x[j]) k=j;
} }
main()
{ int a[10]={23,43,54,56,75,27,12,28,34,24};
printf("before:");
parray(a,10);
sort(a,10);
printf(" after:");
parray(a,10);
} 三、实习总结
四、注意事项
⒈ 一个函数最好只有一个return语句,以保持程序的高清晰度;
⒉ 被调函数中的形参及说明部分的变量,所占存储单元动态分配与回收;
⒊ 函数参数的值传递适宜每次传递数据较少的场合,而地址传递则特别适合处理大批量的
数据,从而提高系统效率;
⒋ 变量的数据类型、作用域和存储类别会相互联系,相互制约,相互影响;
⒌ 主函数内定义的变量,也只在主函数内有效。不同函数中变量可以同名,互不干扰,因
为它们占用不同的内存区域,所以不会混淆;
⒍ 尽量少用全局变量。因为全局变量会增加模块间的耦合、限制函数的通用性、损害程序
的清晰度、降低内存的利用率。
- 23 -
西北农林科技大学信息工程学院实习报告
实习名称:实习七 指 针
实习时间:第 周 成绩:
一、实习目的
⒈ 深刻理解指针的含义,熟练掌握指针变量的定义和使用方法;
⒉ 明白指针与数组的关系,能正确使用数组的指针和指向数组的指针变量;
⒊ 能正确使用字符串的指针和指向字符串的指针变量;
⒋ 在函数的调用中,能正确利用数组和指针进行参数的传递;
⒌ 能正确理解函数指针的概念、熟练使用函数指针代替函数名调用函数、了解指向函数的
指针变量做另一函数的参数的实际意义;
⒍ 了解多级指针的概念及其使用方法。
二、实习内容
1.认真阅读教材第8章的内容,并对其中理解有困难的例题上机进行调试。
2.按要求完成P247习题6。
程序:#include <stdio.h>
void main()
{ int length(char *p); //函数原型声明,函数返回值为整型
int len;
char str[20]; //假设串长不超过20个字符
printf("input string: ");
scanf("%s",str);
len=length(str); //调用函数,返回整型值即为字符串的长度
printf("The length of string is %d.\n",len);
}
int length(char *p)
{ int n;
n=0; //其中存放统计结果
while (*p!='\0') //当前字符不是串的结束符时
{n++; //统计字符个数
p++; //指向下一个字符
}
return (n);
}
- 24 -
西北农林科技大学信息工程学院实习报告
3.按要求完成P247习题7。
方法1:#include <stdio.h>
#include <string.h>
void main()
{ void fuzhi(char *,char *,int);
int m;
char str1[80],str2[80]; //将str1中第m个字符开始的全部字符复制到str2中 printf("input string:");
gets(str1);
printf("which character that begin to copy?");
scanf("%d",&m);
if (strlen(str1)<m) //当str1中字符的个数小于m时,不能复制 printf("input error!\n");
else
{ fuzhi(str1,str2,m);//函数调用,str1,str2传递地址,使形参p1,p2分别指向他们所占用的存储单元的首地址
printf("result:%s\n",str2);
}
}
void fuzhi(char *p1,char *p2,int m)
{int n;
n=0;m--;
while (p1[m]!='\0')
p2[n++]=p1[m++]; //p1和str1,p2和str2占用相同的存储单元,p2[i]的改变即是对应str2[i]的改变
p2[n]='\0'; //给复制的串加上结尾符
}
方法2:#include <stdio.h>
#include <string.h>
void main()
{void fuzhi(char *,char *,int);
int m;
char str1[80],str2[80]; //将str1中第m个字符开始的全部字符复制到str2中 printf("input string:");
gets(str1);
printf("which character that begin to copy?");
scanf("%d",&m);
if (strlen(str1)<m) //当str1中字符的个数小于m时,不能复制 printf("input error!");
else
- 25 -
西北农林科技大学信息工程学院实习报告
{ fuzhi(str1,str2,m);
printf("result:%s\n",str2);
}
}
void fuzhi(char *p1,char *p2,int m)
{int n;
n=0;
while (n<m-1) //先使p1指向第m个字符
{n++;
p1++;
}
while (*p1!='\0')
{*p2=*p1; //然后从第m个字符开始复制,*p2的改变即是对应str2的改变 p1++;
p2++;
}
*p2='\0'; //给复制的串加上结尾符
}
4.按要求完成P247习题11、12。
习题11的源程序:
#include <stdio.h>
#include <string.h>
void main()
{void sort(char (*p)[60]);
int i;
char str[10][60]; //二维字符数组用于处理多个字符串,每个串长不超过60个字符 char (*p)[60]; //指向一维数组的指针变量
printf("input 10 strings:\n");
for (i=0;i<10;i++)
scanf("%s",str[i]); //输入字符串
p=str; //p指向二维数组的0行的指针,p+1指向下一行而不是下一个元素 sort(p); //实参p传递地址
printf("Now,the sequence is:\n");
for (i=0;i<10;i++)
printf("%s\n",str[i]);
}
void sort(char (*s)[60]) //s与p相同也是指向行的指针,s+1指向下一行而不是下一个元素 {int i,j;
char temp[60],*t=temp;
- 26 -
西北农林科技大学信息工程学院实习报告
for (i=0;i<9;i++) //用冒泡法从大到小排序 for (j=0;j<9-i;j++)
if (strcmp(s[j],s[j+1])>0)
{strcpy(t,s[j]);
strcpy(s[j],s[+j+1]);
strcpy(s[j+1],t);
}
}
习题12的源程序1:
#include <stdio.h>
#include <string.h>
void main()
{void sort(char *[ ]);
int i;
char *p[10],str[10][60]; //p是字符型指针数组 for (i=0;i<10;i++)
p[i]=str[i]; //p数组元素存放str二维字符数组每行(即每个串)的首地址 printf("input 10 strings:\n");
for (i=0;i<10;i++)
scanf("%s",p[i]); //输入字符串
sort(p);
printf("Now,the sequence is:\n");
for (i=0;i<10;i++)
printf("%s\n",p[i]);
}
void sort(char *s[ ]) //s数组与主函数中的p数组占用相同的存储单元 {int i,j,k;
char *temp;
for (i=0;i<9;i++) //用选择法从大到小排序
{k=i;
for ( j=i+1; j<10; j++)
if (strcmp(*(s+k),*(s+j))>0) k=j;
if (k!=i)
{temp=*(s+i);
*(s+i)=*(s+k);
*(s+k)=temp;
}
}
}
习题12的源程序2:
#include <stdio.h>
- 27 -
西北农林科技大学信息工程学院实习报告
#include <string.h>
void main()
{ void sort(char *[ ]);
int i;
char *p[10],str[10][60]; //p是字符型指针数组
for (i=0;i<10;i++)
p[i]=str[i]; //p数组元素存放str二维字符数组每行(即每个串)的首地址 printf("input 10 strings:\n");
for (i=0;i<10;i++)
scanf("%s",p[i]); //输入字符串,p[i]是第i个串的首地址
sort(p); //调用函数,传递数组的首地址
printf("Now,the sequence is:\n");
for (i=0;i<10;i++)
printf("%s\n",p[i]);
}
void sort(char *s[ ])
{int i,j;
char *temp;
for (i=0;i<9;i++) //用冒泡法从大到小排序
for (j=0;j<9-i;j++)
if (strcmp(*(s+j),*(s+j+1))>0) //以下这些交换的是指向,即地址
{temp=*(s+j);
*(s+j)=*(s+j+1);
*(s+j+1)=temp;
}
}
5.按要求完成P247习题16。
#include <stdio.h>
void main()
{char *month_name[13]={"illegal month","January","February","March","April",
"May","June","july","August","September","October",
"November","December"};//字符指针数组元素存放字符串的首地址
int n;
printf("input month:\n");
scanf("%d",&n);
if ((n<=12) && (n>=1))
printf("It is %s.\n",*(month_name+n));
else
printf("It is wrong.\n");
}
- 28 -
西北农林科技大学信息工程学院实习报告
*6.按要求完成P247习题15(选做)。
#include <stdio.h>
void main()
{
char str[50],*pstr;
int i,j,k,m,e10,digit,ndigit,a[10],*pa;
printf("input a string:\n");
gets(str); //输入字符串,其中可以包含空格
pstr=&str[0]; //字符指针pstr存放字符数组str 的首地址,pstr是指向元素的指针 pa=&a[0]; //指针pa存放整型a数组首地址
ndigit=0; //ndigit代表有多少个整数
i=0; //代表字符串中的第几个字符
j=0;
while(*(pstr+i)!='\0')
{if((*(pstr+i)>='0') && (*(pstr+i)<='9'))//逐个字符查看是否阿拉伯数字,pstr+i指向第i个字符 j++;
else
{if (j>0)
{digit=*(pstr+i-1)-48; //将个数位赋予digit k=1;
while (k<j) //将含有两位以上数的其它位的数值累计于digit {e10=1;
for (m=1;m<=k;m++)
e10=e10*10; //e10代表该位数所应乘的因子 digit=digit+(*(pstr+i-1-k)-48)*e10; //将该位数的数值累加于digit k++; //位数k自增
}
*pa=digit; //将数值赋予数组a ndigit++;
pa++; //指针pa指向a数组下一元素 j=0;
}
}
i++;
}
if (j>0) //以数字结尾字符串的最后一个数据 {digit=*(pstr+i-1)-48; //将个数位赋予digit k=1;
while (k<j) // 将含有两位以上数的其它位的数值累加于digit {e10=1;
for (m=1;m<=k;m++)
- 29 -
西北农林科技大学信息工程学院实习报告
e10=e10*10; //e10代表位数所应乘的因子
digit=digit+(*(pstr+i-1-k)-48)*e10; //将该位数的数值累加于digit
k++; //位数K自增
}
*pa=digit; //将数值赋予数组a
ndigit++;
j=0;
}
printf("There are %d numbers in this line, they are:\n",ndigit);
j=0;
pa=&a[0];
for ( j=0;j<ndigit;j++) //打印数据
printf("%d ",*(pa+j));
printf("\n");
}
三、实习总结
四、注意事项
⒈ 指针里存放的是地址,是程序运行时由系统分配的,用户程序中不应为指针变量赋常
量为值,但必须为指针变量赋地址值后才能引用,否则可能引起严重后果。
⒉ 使用指针常见的错误如下:
⑴ 引用没有赋值的指针变量;
⑵ 未分清变量的指针和变量的指针表示。如:int a,*p=&a; 和 *p=10;
⑶ 混淆给指针变量赋值和给指针变量指向的变量赋值的区别。如:p=q; 与 *p=*q; ⑷ 指针移动后未复位便使用,认为是从头开始;地址越界问题;
⑸ 指针与输入输出格式不匹配;
⑹ 对指针所指数据放置顺序的假定错误;
⑺ 指针运算符的结合性和优先级的理解不正确。
- 30 -
西北农林科技大学信息工程学院实习报告
实习名称:实习八 用户建立的数据类型
实习时间:第 周 成绩:
一、实习目的
1.掌握结构体类型、结构体变量及结构体数组的定义和使用方法; ...............
2.掌握结构体类型与指针的联合使用方法;
3.了解联合体的概念、结构特征、定义与使用方法;
4.了解枚举类型的概念和使用方法;
5.掌握用typedef自定义类型的方法。 .....
二、实习内容
1.认真阅读教材第9章的内容,并对其中理解有困难的例题上机进行调试。
2.定义一个结构体变量(包括年、月、日三个成员),计算给定的日期是该年的第几天。
方法1:#include <stdio.h>
struct d //定义包含三个成员的结构体类型
{ int year;
int month;
int day;
}date; //声明date为此结构体类型的变量
void main()
{int i,days=0,m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
printf("input year,month,day:");
scanf("%d,%d,%d",&date.year,&date.month,&date.day);//为结构体变量date
的成员赋值
for(i=1;i<date.month;i++) //统计整月份的天数
days+=m[i];
days+=date.day; //加上不满一个月的天数
if ((date.year %4== 0 && date.year % 100 != 0
||date.year % 400 == 0) && date.month >=3) days+=1;//闰年加1天
printf("%d-%d-%d is the %dth day in %d.\n",date.year,date.month,date.day,
days,date.year);
}
方法2:#include <stdio.h>
struct //定义无名结构体类型,包含三个成员
{ int year;
int month;
- 31 -
西北农林科技大学信息工程学院实习报告
int day;
}date; //声明date为此结构体类型的变量
void main()
{int days;
printf("input year,month,day:");
scanf("%d,%d,%d",&date.year,&date.month,&date.day);//为结构体变量date的
成员赋值
switch(date.month) //根据月份加天数
{ case 1: days=date.day; break;
case 2: days=date.day+31; break;
case 3: days=date.day+59; break;
case 4: days=date.day+90; break;
case 5: days=date.day+120; break;
case 6: days=date.day+151; break;
case 7: days=date.day+181; break;
case 8: days=date.day+212; break;
case 9: days=date.day+243; break;
case 10: days=date.day+273; break;
case 11: days=date.day+304; break;
case 12: days=date.day+334; break;
}
if ((date.year %4== 0 && date.year % 100 != 0
||date.year % 400 == 0) && date.month >=3) days+=1;//闰年加1天
printf("%d/%d is the %dth day in %d.\n",date.month,date.day,days,
date.year);
}
3.建立一个学生通讯录(最少有三条学生的信息),包括学号、姓名、性别、电话、邮编、
通讯地址及Email等。要求按姓名排序,并输出排序后的通讯录。
#include <stdio.h>
#include <string.h>
struct student //定义结构体类型
{ int xh;
char xm[20];
char xb;
int dh;
int yb;
char dz[30];
char Email[25];
};
void main()
- 32 -
西北农林科技大学信息工程学院实习报告
{struct student s[3] ,temp; //声明结构体类型的变量s
int i, j,k;
for(i=0;i<3;i++)//为结构体变量s的成员赋值
{ printf("\n输入第 %d 个学生的信息:",i+1);
printf("\n\t学号:"); scanf("%d",&s[i]. xh);
printf("\n\t姓名:"); scanf("%s",s[i]. xm);
getchar( );
printf("\n\t性别:"); scanf("%c",&s[i]. xb);
printf("\n\t电话:"); scanf("%d",&s[i]. dh);
printf("\n\t邮编:"); scanf("%d",&s[i]. yb);
printf("\n\t通讯地址:"); scanf("%s",s[i]. dz);
printf("\n\t Email:"); scanf("%s",s[i]. Email);
}
printf("\n");
for(i=0;i<2;i++) //用选择法排序
{k=i;
for( j=i+1; j<3; j++) //
if ((strcmp(s[j].xm,s[k].xm))> 0) k=j;
if (k!=i)
{temp=s[i];s[i]=s[k];s[k]=temp;} //同类的结构体变量可以相互赋值,见p251
}
printf("\n排序后:\n");
for(i=0;i<3;i++)
printf("%d, %s, %c, %d, %d, %s, %s\n",s[i]. xh,s[i]. xm,s[i].xb,s[i].dh,s[i].yb, s[i].dz, s[i].Email);
}
4.按要求完成P282习题5。
#include <stdio.h>
#define N 10
struct student
{ char num[6];
char name[8];
float score[3];
float avr;
} stu[N];
void main()
{ int i,j,maxi;
float sum,max,average;
for (i=0;i<N;i++)
{printf("input scores of student %d:\n",i+1);
- 33 -
西北农林科技大学信息工程学院实习报告
printf("NO.:");
scanf("%s",stu[i].num);
printf("name:");
scanf("%s",stu[i].name);
for (j=0;j<3;j++)
{printf("score %d:",j+1);
scanf("%f",&stu[i].score[j]);
}
}
printf("\n");
average=0;
max=0;
maxi=0; //存放最高分学生的位置号
for (i=0;i<N;i++)
{sum=0;
for (j=0;j<3;j++)
sum+=stu[i].score[j]; //求每个人的和
stu[i].avr=sum/3.0; //求每个人的平均
average+=stu[i].avr; //求总的和
if (sum>max) //找出最高分的学生的位置
{max=sum;
maxi=i; //找出最高分的学生的位置
}
}
average/=3;//求总的平均
printf(" NO. name score1 score2 score3 average\n"); for (i=0;i<N;i++)
{printf("%5s%10s",stu[i].num,stu[i].name);
for (j=0;j<3;j++)
printf("%9.2f",stu[i].score[j]);
printf(" %8.2f\n",stu[i].avr);
}
printf("average=%5.2f\n",average);
//根据位置输出最高分学生的数据
printf("The highest score is : student %s,%s\n",stu[maxi].num,stu[maxi].name); printf("his scores are:%6.2f,%6.2f,%6.2f,average:%5.2f.\n",
stu[maxi].score[0],stu[maxi].score[1],stu[maxi].score[2],stu[maxi].avr); }
*5.按要求完成P282习题7。
- 34 -
西北农林科技大学信息工程学院实习报告
三、实习总结
四、注意事项
⒈ 定义结构体类型,系统并不为其分配内存空间,当使用这种类型的变量或数组时才分
配。如同int i; int不分配内存,i才分配内存。理解结构体是一种类型,本质上和int等类型并没有任何区别,这样结构体变量、结构体数组等就和前面学习过的知识是一回事了,只要注意其新内容(成员)就可以了。
⒉ 结构体变量及其指针变量与引用成员,如:struct student a,*p=&a;
a是结构体类型的变量,p是指向变量a的指针,p不直接指向a的任何一个成员,是通过成员运算符“.”来指向某一个成员的,即:(*p)·成员。
⒊ 结构体数组名、结构体数组元素、结构体数组元素成员名等都可以作函数的参数,与数
组及结构体变量作函数参数没有本质区别。
⒋ 联合体的所有成员共享同一段内存空间,系统按占内存最多的成员开辟内存空间。一般
来说,联合体变量在任一时刻只有一个成员的值是有效的,总是“后入有效,冲掉前者”。
- 35 -
西北农林科技大学信息工程学院实习报告
实习名称:实习九 文件操作
实习时间:第 周 成绩:
一、实习目的
⒈ 理解文件以及文件缓冲区、文件指针的概念;
⒉ 掌握文件的打开、关闭、读取、写入等操作方法;
⒊ 掌握建立文件的方法,能按要求对文件选择适当的方式进行读写等操作;
⒋ 学会使用文件定位函数,能正确移动文件指针到恰当位置,对文件进行简单的操作。
二、实习内容
1.认真阅读教材第9章的内容,并对其中理解有困难的例题上机进行调试。
2.编程完成P305习题4,并查看磁盘文件内容是否符合要求。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main ()
{ FILE *fp; //定义文件指针变量
char str[100];
int i=0;
if ((fp=fopen("c:\\a1","w"))==NULL) //以写方式打开文件
{ printf("can not open file\n");
exit(0);
}
printf("input a string:\n");
gets(str); //从键盘输入字符串,以“!”结尾
while (str[i]!='!') //判断是否字符串的结尾
{if (str[i]>='a' && str[i]<='z') //找出小写字母
str[i]=str[i]-32; //将小写字母转换为大写字母
fputc(str[i],fp); //逐个字符写入文件
i++;
}
fclose(fp); //关闭文件
fp=fopen("a1","r"); //以读方式打开文件。注:一个文件若要多次打开,必须先关闭,才能再次打开
fgets(str,strlen(str)+1,fp); //读出所有字符及串结尾符
- 36 -
西北农林科技大学信息工程学院实习报告
printf("%s\n",str); //显示到屏幕上 fclose(fp); //关闭文件 }
3.按要求将P305习题6-8编写成一个程序(或项目),并给定测试数据如下: ① 5个学生的学号、姓名、3门课的成绩如下:
05101 05103 05106 05123 05108 05113 P305习题6
#include <stdio.h> #define N 5 struct student {char xh[10]; char xm[8]; int cj[3]; float pj; } stu[N];
void main() { int i,j,sum; FILE *fp; for(i=0;i<N;i++)
{ printf("\ninput data of student %d:\n",i+1); printf("xh:"); scanf("%s",stu[i].xh); printf("xm:"); scanf("%s",stu[i].xm); sum=0; //存放个人和 for (j=0;j<3;j++) // 输入成绩
{ printf("cj %d:",j+1); scanf("%d",&stu[i].cj[j]); sum+=stu[i].cj[j]; //求个人和 }
stu[i].pj=sum/3.0; //求平均 }
/*将数据写入文件*/
fp=fopen("stud","w"); //以写方式打开文件,建立一个新文件 for (i=0;i<N;i++)
if (fwrite(&stu[i],sizeof(struct student),1,fp)!=1)//一次写入一个数组元素的所有成员
- 37 -
Wang Li Fun Ling Xin Yuan
89 60 75.5 100 90 58
98 80 91.5 50 95 68
67.5 90 99 62.5 60 71
② 要插入的学生数据为:
西北农林科技大学信息工程学院实习报告
printf("file write error\n");
fclose(fp); //关闭文件
fp=fopen("stud","r"); //再次打开文件,进行读取
for (i=0;i<N;i++)
{fread(&stu[i],sizeof(struct student),1,fp); //读出文件中的内容,一次读一个元素 printf("\n%s,%s,%d,%d,%d,%6.2f\n",stu[i].xh,stu[i].xm,stu[i].cj[0],
}
P305习题6-8合写为一个文件:
#include <stdio.h>
#define SIZE 6
struct student
{unsigned int xh;
char xm[20];
float cj[3];
float pj;
}stud[SIZE],st;
void save( )
{ FILE *fp;
int i;
char filename[25];
printf("input filename:");
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{printf("cannot open file\n");
return;
}
for(i=0;i<SIZE;i++)
fprintf(fp,"%u,%s,%5.1f,%5.1f,%5.1f,%6.2f\n",stud[i].xh,stud[i].xm,
stud[i].cj[0],stud[i].cj[1], stud[i].cj[2],stud[i].pj);//用格式写语句,也可用fwrite()函数 stu[i].cj[1],stu[i].cj[2],stu[i].pj);} //显示在屏幕上
fclose(fp);
}
void paixu(struct student t[],int n)//排序函数
{int i,j,k;
struct student temp;
for(i=0;i<SIZE-2;i++)
{k=i;
- 38 -
西北农林科技大学信息工程学院实习报告
for(j=i+1; j<SIZE-1; j++)
if (stud[k].pj<stud[j].pj) k=j;
if (k!=i)
{temp=stud[k];stud[k]=stud[i];stud[i]=temp;}
}
printf("sort result:\n");
for(i=0;i<SIZE-1;i++)
printf("%u, %s, %5.1f, %5.1f, %5.1f, %6.2f\n",stud[i].xh,stud[i].xm, stud[i].cj[0], stud[i].cj[1],stud[i].cj[2],stud[i].pj);//将排序结果显示在屏幕上
}
void insert( ) //插入函数
{int i, j,k;
for(i=0;i<SIZE-1;i++)
if (stud[i].pj<st.pj) { break;}
if (i<SIZE-1)
for( j=SIZE-1; j>i; j--)
stud[j]=stud[ j-1];
stud[i]=st; //插入st
printf("Insert result:\n");
for(i=0;i<SIZE;i++)
printf("%u, %s, %5.1f, %5.1f, %5.1f, %6.2f\n",stud[i].xh,stud[i].xm, stud[i].cj[0], stud[i].cj[1],stud[i].cj[2],stud[i].pj);//将排序结果显示在屏幕上
}
void main()
{ int i;
for(i=0;i<SIZE-1;i++)
{ printf("Please enter %d data of student:\n",i);
printf("xh,xm: "); scanf("%u%s",&stud[i].xh,stud[i].xm); //用格式输入函数输入 printf("三个成绩: ");
scanf("%f%f%f",&stud[i].cj[0],&stud[i].cj[1], &stud[i].cj[2]); //用格式输入函数输入 stud[i].pj=(stud[i].cj[0]+stud[i].cj[1]+stud[i].cj[2])/3; //求平均
printf("\n ");
}
save( ); //调用写文件函数,将输入的数据存入指定文件
paixu(stud,SIZE-1); //调用排序函数,此函数可以没有参数,因为stud,SIZE都定义为全局的
save( ); //再次调用写文件函数,将排好序的数据存入指定文件
printf("Please enter data of Insert student:\n");
- 39 -
西北农林科技大学信息工程学院实习报告
scanf("%u%s%f%f%f",&st.xh,st.xm,&st.cj[0],&st.cj[1], &st.cj[2] ); //用格式输入
函数输入
st.pj=(st.cj[0]+st.cj[1]+st.cj[2])/3; //求平均
insert( ); //调用插入函数
save( ); //再次调用写文件函数,将插入好的数据存入指定文件
}
三、实习总结
四、注意事项
⒈ 本章讲的是C语言中由文字和数据组成的数据文件,其中的数据是由程序写入的,并
可由程序读出到程序中使用,它不同于C语言中的.c源程序文件;
⒉ 文件读写方式“w”具有“破坏性”,如文件名用重复了,已经存在的文件将会被覆盖; ⒊ 一定要分清选取的读写函数与文件打开方式是否相适应:
⑴ 打开文件的目的是读是写还是追加,全由打开方式字符中第1个字符r、w、a决定; ⑵ 若打开的是二进制文件,则打开方式中第2个字符一定是b;
⑶ 如果对文件是读/写或写/读两种功能,打开方式中最后一个字符一定是+。
- 40 -