第一部分 C实验上机指导
实验1 C程序运行环境及基本操作
一、实验目的及要求
(1)熟悉并掌握在Visual C++ 6.0环境中编辑、编译、连接、运行C语言程序的一般步骤。重点掌握C程序源文件、目标文件、可执行文件的建立和保存。
(2)进一步熟悉和掌握C语言源程序的基本结构及书写规则。
(3)初步熟悉各运算符的运算规则及使用。
二、实验内容及指导
【实验1-1】在Visual C++ 6.0(后文在不引起歧义的情况下简称VC++)环境中编辑并运行以下程序lab1-1.C。
#include <stdio.h> void main() { printf("Hello C!\n"); }
本题指导
(1)本实验目的是练习并熟悉在VC++环境中新建、保存源程序及进行编译、连接、运行的一般步骤。这里以英文版Visual C++ 6.0软件为例来说明。
(2)本实验操作步骤如下:
①在Windows中运行VC++,进入集成开发环境。
②新建源程序。在 VC++主窗口中运行“File”(“文件”)菜单上的“New”(“新建”)命令,如图1-1所示。
图1-1 VC++窗口中的“File”菜单
屏幕上弹出“New”对话框,单击此对话框上方的“Files”选项卡,选择“C++ Source File”项(即“C++源程序”),然后在“File”下的文本框中输入要新建的源程序文件名lab1-1.C,如图1-2所示,单击“OK”按钮。
图1-2 VC++窗口中的“New”对话框
单击“OK”按钮后回到Visual C++主窗口,可以看到VC++主窗口的标题栏显示出了源程序的文件名。
在主窗口的程序编辑窗口中输入源程序lab1-1.C的代码,如图1-3所示。
图1-3 “lab1-1.C”程序编辑窗口
③保存源程序。输入完源程序之后,应执行“File”菜单中的“Save”(“保存”)或“Save as”(“另存为”)命令,保存程序(如果没有执行这一步操作,则执行下一步编译操作时,系统会自动提示是否保存源程序)。
④编译源程序。执行“Build”(“创建”)菜单的“Compile”(“编译”)命令,如图1-4所示。
图1-4 VC++窗口中的“Build”菜单
此时弹出如图1-5所示的对话框,询问是否要建立一个默认的工程工作区。单击“是”按钮,开始编译该文件。
图1-5 VC++对话框
编译过程中,如果源程序有错,则在 VC++主窗口下方的编译输出窗口的“Build”选项卡中显示出错误,程序员须改正错误,编译改正才能完成。如果没有错,编译输出窗口就会显示生成的.OBJ文件名,并显示如下信息:
lab1-1.OBJ - 0 error(s), 0 warning(s)
⑤连接。编译无误生成OBJ文件后,就可执行“Build”菜单下的“Build lab1-1.exe”(“创建lab1-1.exe”)命令或按“F7”键,对被编译后的目标文件进行连接,如图1-6所示。
图1-6 VC++“Build”菜单下的连接(创建)命令
如果连接过程中发现错误,则会在编译输出窗口的“Build”选项卡中显示出连接错误的信息,出现错误时,修改源程序后再编译、连接,直到连接没有错误为止。
编译连接成功时,在编译输出窗口中就会显示如下信息:
lab1-1.exe - 0 error(s), 0 warning(s)
表明没有错误和警告信息,创建了可执行文件lab1-1.exe。
⑥运行程序。连接生成EXE文件后,就可执行“Build”菜单下的“Execute”(“执行”)命令或按“Ctrl”+“F5”键(如图1-7所示),来运行程序lab1-1.exe。程序执行时将弹出一个DOS窗口并输出以下内容:
Hello C! Press any key to continue(按任意键继续)
图1-7 VC++“Build”菜单下的Execute命令
按任意键后,输出结果窗口将关闭,回到源程序编辑窗口。
【实验1-2】分析以下程序的运行结果,并上机验证。
#define M 6 #include "stdio.h" void main() { char c='k'; int a,b; int i=1,j=2,k=3; a=b=8; printf("%d,%d\n ",++a,b--); printf("%d,%d\n",'a'+5<c,1<M<j); printf("%d,%d\n",i+j+k==-2*j,k==j==i+5); }
本题指导
本题虽只有短短几行,却涵盖了宏定义、头文件包含、变量定义及初始化、赋值运算、自增/减运算、算术运算、关系运算及不同类型数据间的混合运算等多个内容,值得仔细分析和体会。
(1)注意自增运算符“++”和自减运算符“- -”放在变量前面与后面时运算顺序的区别(放在前面是先自增/自减,然后取变量的值;放在后面则是先取变量的值,后进行自增/自减运算)。
(2)程序第一行是一个无参数的宏定义,在较早的C软件版本中称为符号常量定义。
(3)注意语句“a=b=8;”的执行过程。该语句相当于“a=(b=8);”,先执行右边括号内的赋值操作,括号内表达式的值为8,再给变量a赋值。
(4)注意表达式1<M<j 的运算过程。不能理解为数学上的两个不等式,而是相当于(1<M)<j,整个是一个关系不等式,括号内也是一个关系表达式。求值时先求括号内表达式的值,由于1<M为真,因此整个表达式相当于1<j,该关系表达式也为真,因此整个表达式的值为1。
(5)根据算术运算符和关系运算符的优先级,最后一行中的两个表达式分别相当于(i+j+k)==(-2*j)和(k==j)==(i+5),读者不难求出其值。
【实验1-3】分析以下程序的运行结果,并上机验证。
#include <stdio.h> void main() { int x, y, z; x=y=z=0; ++x||++y&&++z; printf("x=%d,y=%d,z=%d\n",x,y,z); x=y=z=0; ++x&&++y||++z; printf("x=%d,y=%d,z=%d\n",x,y,z); x=y=z=-1; ++x&&++y||++z; x=y=z=2; printf("%d,%d,%d\n",!x*!y, !!!x, x==5&&y&&(z=8)); }
本题指导
本题主要让读者加深对逻辑运算符及逻辑表达式求解过程的理解。
(1)“||”运算符左边表达式的值为真(非0)时,不再计算右边的表达式。
(2)“&&”运算符左边表达式的值为假(0)时,不再计算右边的表达式。
【实验1-4】运行以下程序,分析各表达式输出的结果。
#include<stdio.h> void main() {int a,b,c,i,j; printf("%d\n",5%3*2/6-!5); printf("%d\n",5>=2+1-(3<5)); i=2; j=4; printf("%d\n",++i-j--); printf("%d\n",i+=i*=j); printf("%d\n",i=3/2*(j=3-2)); a=1; b=2; c=3; printf("%d\n",!a&&b++); printf("%d\n",a||b+2&&a*b); printf("%d\n",++a,b=10,a+5); printf("%d\n",a+=b%=a+b); printf("a=%d,b=%d,c=%d\n",a,b,c); printf("%d\n",a>b?a:c>b?c:b); }
本题指导
本题涉及算术、逻辑、符合赋值、条件运算、逗号等多重运算符和表达式。
(1)在分析表达式的运算过程及结果时,需注意掌握并分析以下几个方面:
①表达式中各种运算符的功能和对操作数类型的要求;
②根据各运算符的优先级和结合性,正确分析运算的先后次序;
③根据各运算符的功能、操作数类型、运算过程中的类型转换,确定运算结果的值及类型。
(2)逗号表达式求解时,会顺序执行每一个表达式,整个表达式的值为最后一个表达式的值。
(3)对于赋值和复合赋值运算,需注意以下两点:
①复合赋值运算的过程是,首先根据赋值运算符前的运算符,复合赋值运算符左边的变量和复合赋值运算符右边的表达式进行相应的运算,然后将该运算结果赋值给复合赋值运算符左边的变量。例如,表达式“x+=y+1”等于“x=x+(y+1)”。
②对于赋值和复合赋值表达式,其结果类型为赋值和复合赋值运算符左边变量的类型。
【实验1-5】按下面要求运行程序 lab1-5.C,分析并观察运行结果。理解字符的输入与输出,对结果进行合理的解释。
#include <stdio.h> void main() {int a,b,c; char x,y,z; scanf(“a=%d,b=%d”,&a,&b); scanf(“%c%c%c”,&x,&y,&z); c=a+b; printf(“%d+%d=%d”,a,b,c); printf(“%c%c%c”,x,y,z); }
本题指导
本题主要是练习字符数据的输入输出,并通过练习了解getchar、putchar、scanf和prtinf等函数在处理字符数据时的用法。
(1)利用scanf和prtinf函数实现外设和内存的数据交互,实现数据的标准输入输出。
(2)利用getchar和putchar函数可以实现一个字符数据的输入输出。调用putchar函数的时候,直接把待输出的字符常量或者字符变量放到参数的圆括号内,例如输出字符'a';那么可以写成putchar('a');,每调用一次该函数,可以输出一个字符。调用getchar函数的时候,直接从键盘输入一个字符赋值给该函数左侧的变量。输入输出一个字符时,可以用 scanf 和prtinf函数,也可以用getchar和putchar函数。
【实验1-6】分析以下程序的输出结果并上机验证。
#include<stdio.h> void main() {short int a=32767,b=a+1; char c1=97,c2='b'; unsigned int d=54321; unsigned long e=1234567; float f=1.56789,g=-345.48; double m=12.67323,n=123.456789; printf("%d,%d\n",a,b); printf("%#o,%#lx\n",d,e); putchar(c1); printf("%c %c\n",c1,c2); printf("%+6f,%+5.4f\n",f,g); printf("m=%lf,n=%e\n",m,n); }
本题指导
本题主要是练习调用库函数prtinf来输出各种类型的数据。
(1)关于printf函数的几点说明:
①printf函数的一般格式为:
printf(格式控制串,输出列表);
其中,格式控制串是用双引号引起来的字符串,也称转换控制字符串;输出列表是需要输出的一些数据项列表,数据项可以是变量或任何表达式。
②格式控制串中的字符分为两类,一类是普通的ASCII码字符(包括转义字符),这些字符在输出时将原样输出到屏幕;另一类是以百分号(%)和其他字符组成的格式控制符,如果输出正常的话,在输出时格式控制符将被输出列表中相应位置上数据项的值替代。例如,在
printf("x=%d,y=%d,x+y=%d\n",x,y,x+y);
中,格式控制串中的字符'x'、'y'、'+'、'='、'\n'等都是普通ASCII码字符,而%d是格式控制符。
③在printf函数中,格式说明符与输出项从左到右在类型上必须一一对应匹配。如不匹配,将导致数据不能正确输出,但此时C系统不报错。另外,格式说明符与输出项的个数一般应该相同,如果格式说明的个数少于输出项的个数,多余的输出项不予输出;如果格式说明的个数多于输出项的个数,则对于多余的格式将输出不定的值。
有关printf函数更详细的用法,请参考理论教材或其他资料。
(2)在给变量进行初始化或赋值时,一定要注意变量所表示的数的范围。如本例中整数32767加1后输出为-32768。
【实验1-7】输入并运行下面的程序。为使变量 a、b、x、y、c1、c2的值分别为3、7、3.2、2.4、'a'、'b',运行程序时正确的数据输入形式是什么?
#include<stdio.h> void main() { int a,b; float x,y; char c1,c2; scanf("a=%d b=%d",&a,&b); scanf("x=%f y=%f",&x,&y); scanf("c1=%c c2=%c",&c1,&c2); printf("a=%d,b=%d,x=%f,y=%f,c1=%c,c2=%c\n",a,b,x,y,c1,c2); }
本题指导
(1)本题进一步练习scanf函数及其对应的键盘输入格式。
scanf函数的一般形式可写为:
scanf(格式控制串,输入项地址列表);
其中格式控制串中的字符分为两类,一类是普通的ASCII码字符(包括部分转义字符如'\n'、'\t'等),这些字符在程序运行时必须从键盘原样输入;另一类是以百分号(%)和其他字符组成的格式控制符,输入时格式控制符位置上应输入对应类型的数据值常量。输入项地址列表是变量或数组元素的地址。
(2)说明:如果要获得以上的数据,正确的输入应该是(“└┘”表示空格符):
a=3└┘b=7x=3.2└┘y=2.4c1=a└┘c2=b↙
由于输入时scanf函数若遇到回车键将视为输入结束,因此,如果在输入完“a=3└┘b=7”后直接回车,则后面的几个变量则无法正确接收数据。
(3)由于scanf函数的格式控制串中,普通ASCII码字符(包括部分转义字符如'\n'、'\t'等)应原样输入,为了避免输入时出错或过于烦琐,在格式控制串中应尽量少使用不必要的普通字符。
三、思考与练习
(1)C语言程序的书写需要注意哪些方面?
提示:最基本的方面包括两方面。一是保证程序书写的正确性;二是要有良好的书写风格(如格式清晰、添加必要的注释等),以便自己和他人容易阅读。
(2)通过查阅本书附录Ⅱ或其他资料,熟悉编译、连接过程中常用提示信息的含义。
提示:正确理解这些提示信息,便于查找及改正源程序中的错误和其他错误。有经验的程序员会非常注意这些提示信息。
(3)分析下面程序的运行结果,并上机验证。
#include<stdio.h> void main() { int a,b,i,j; a=b=i=j=10; a+=i++; b-=++j; printf("a=%d,b=%d,i=%d,j=%d\n",a,b,i,j); }
(4)在printf函数中,如果输出项列表与格式符的数目不匹配,会有怎样的输出结果?同样地,如果是在 scanf 函数中出现了输入项地址列表与格式符不相匹配的情况,又会对输入造成怎样的影响?试编写程序验证。