程序语言原理复习家庭作业.docx
《程序语言原理复习家庭作业.docx》由会员分享,可在线阅读,更多相关《程序语言原理复习家庭作业.docx(29页珍藏版)》请在冰豆网上搜索。
![程序语言原理复习家庭作业.docx](https://file1.bdocx.com/fileroot1/2023-1/31/eb1cc26c-08e4-489e-8fde-9b3b5544743d/eb1cc26c-08e4-489e-8fde-9b3b5544743d1.gif)
程序语言原理复习家庭作业
1.3BASIC能不能编人工智能程序?
为什么?
答:
一般不能。
首先,人工智能应用,这类程序是对人们的智力行为仿真,包括自然语言理解、定理证明、模式识别、机器人、各种专家系统。
这类语言要能描述知识,并根据推理规则推断合理的结论。
在符号运算上作谓词演算或λ演算是其推理运算的基本方式。
因此此语言最好是非过程的,以直接反映客观事物之间的关系。
BASIC是过程性语言、是交互性、解释型语言,这是由于它的全程量数据、无模块,决定了它只能编制小程序,它不能定义数据类型,没有递归,这对匹配回溯是致命的。
因此一般情况下,不能满足人工智能的要求。
但它有判断,转移和条件,可以在相对窄小范围内模拟实现专家系统程序。
所以不能绝对。
1.8程序设计语言的成功有以下因素:
成功=设计好坏+实现难易+权势支持+社会需要,试比较FORTRON-Alogol60;Modula2-Ada;BASIC-Pascal;Pascal-C;PL/1-Alogol68(任选一组)。
答:
Pascal-C
Pascal的研究者一开始就本着“简单、有效、可靠”的原则设计,因此一问世,就取得了巨大的成功。
在人们为摆脱软件危机而对结构化程序设计寄于极大希望的时代,Pascal得到很快普及,以上说明设计好坏和社会需要使Pascal取得成功,但随着社会发展,硬件继续降价,功能和可靠性进一步提高,人们对软件的要求,无论是规模、功能、还是开发效率都大为提高。
因此只能编顺序小程序的Pascal已不能满足需求了,也就慢慢只在教学示范中使用。
C是一个表达能力强、顺序的、结构化程序设计语言,它给程序员较大的自由度。
下层数据转换灵活。
上层是结构化的控制结构,它的分别编译机制使它可以构成大程序。
输入/输出依赖UNIX,使语言简短。
C得益于灵活的指针,函数副作用和数据类型的灵活。
它设计上虽不完美,但它简洁、近于硬件、代码高效、并有大量环境工具支持,以及实现上的优势,使它成为系统软件的主导。
FORTRAN与ALGOL
FORTRAN语言的出现使当时科技计算为主的软件生产提高了一个数量级,奠定了高级语言的地位,1960年的“算法语言ALGOL的修订的报告”对ALGOL的定义采用相对严格的形式语法。
ALGOL语言为广大计算机工作者接受,当时IBM公司当时经营世界计算机总额75%的销售量,一心要推行FORTRAN,不支持ALGOL,以致ALGOL60始终没有大发展起来。
以上说明了“权势支持”是影响程序设计语言成功的因素之一。
Moduld-2和Ada语言。
Moduld-2和Ada在设计上是相似的,二者皆是强类型语言,封装的程序包是程序资源构件。
从实现上来看,Mudula-2语言9000句编译器就具有了Ada20万句编译器80%的功能,明显优于Ada。
但是,Ada有美国国防部的支持,故modula在与Ada的竞争中处于不利地位,最终也没有取得很大成就,不及PASCAL语言的。
而Ada在美国国防部的支持下,发展迅速。
该语言的开发完全按软件工程方式进行,但是Ada过多强调安全性和易读性,因而编译程序要做许多静态检查,故体积庞大。
且由于Ada的环境工具发展缓慢,故自其第一个版本以来,并未取得投资者预想成就。
并且,随着软件工程本身向集成化、可重用、面向对象方向发展,Ada已有些不适应,然而美国军方仍然支持,故95年,Ada完成面向对象的改造,但这种改造使其成为最庞大臃肿的语言,可是它却被ANSI和ISO接受,成国世界上第一个有法定标准的面向对象语言。
由此可见,程序设计语言的成功不仅在于其设计的好坏和实现的难易,权势支持和社会需要也是重要因素。
2.2计算机解题涉及四个世界的对象及其相互作用(运动)。
程序设计语言要涉及几个世界对象?
为什么?
答:
程序设计语言的设计要受到问题世界和模型世界的影响,一旦它定型,它只涉及程序、机器两个世界对象,这是因为程序设计语言的只是实现软件的描述工具并自动转到机器中运行。
2.4指出以下说法的正误。
(a)程序设计语言越简短越好。
错,有时十分方便的使用未必简便。
(b)复杂的语言可读性都差。
错,例如Ada虽复杂,但可读性也很好。
(C)已有程序设计语言(Pascal、C、Ada、Lisp、Prolog)早已实用不存在二义性。
错,Pascal还存在。
(d)高级语言由于硬件速度提高快不用追求效率。
错,效率是高级程序语言必须考虑的一个问题。
(e)当今语言没有一个在语言的层次上能保证可移植。
错,很多语言都有力图脱离机器。
Ada、C等。
(f)有副作用的函数百害无一利。
错,C正是得益于这种副作用。
3.3标识符、符号名、变量、常量、字面量、参数名这些术语相互什么关系,为什么不能去掉一些?
答:
计算机之中只能用名字操纵值。
变量、常量、字面量都是标识符,符号名是标识符的名字。
变量是代表多值的标识符,仅是一个名字,它的值在程序中可以改变;常量的值在程序中不能改变,成为某个具体值的代名词;字面量也是常量,只是不能再给他取名字。
参数是只用于调用的变量。
这些术语相互区别,相互联系,不能去掉。
3.7略
3.10描述屏幕窗口可以用以下的数组类型:
typewindow=array[0..511,0..255]of0..1;
w:
window;
如果有一记录:
typepoint=record
x:
0..511;
y:
0..255
end;
能否写出typeScreen=array[point]of0..1;
s:
Screen;
如果行,对记录有什么限制?
他们的值集有没有区别?
写出w(35,22)的相当的元素的引用。
答:
对记录有限制。
不能通过,如果行只能限定为两整形记录成分。
Point相当于一个{(x,y)|x(0,511),y(0,25)}的集合,与window定义的范围相同;
它们的值有差别。
Screen类型的值集是Point(0,1)全集。
即对应每一个象素点坐标
(x,y)Screen的值都有两个,即0或1。
与W(35,52)相当的S元素引用为S({35,22})
iffs({35,22})=W(35,22).
3.11C语言的++X,X++是左值还是右值?
为什么?
答:
++X先作左值后作右值,是因为X=X+1,在把X赋值给它的左值;
X++先作右值后作左值,因为先赋值给它的左值,再X=X+1。
3.13用运算符,操作数术语说明以下每个表达式,它们表达的是什么?
答:
b[3][5]:
二维数组的一个操作数,表达的是二维数组b的一个存储操作数。
*(b[i]+j):
一维数组b的第i个操作数b[i]的地址与j相加的和作为*运算符的操作数,即指向b[i][j]操作数的指针值。
(*(b+i))[j]:
操作数b和操作数i相加的和作为*运算符的操作数,*运算求得的结果作为起始地址指针操作数,与操作数j相结合决定了以*运算结果为指向b[i][j]操作数的指针值。
*((*(b+i))+j):
操作数b和操作数i相加的结果作为*运算的操作数,*运算求得的结果作为操作数和操作数j通过+运算符求得结果有作为*运算符的操作数得到最终结果指向b[i][j]操作数的指针值。
*(&b[0][0]+5*i+j):
&b[0][0]是二维数组b的起始操作数的地址指针,5*i+j是操作数5和操作数j,通过运算后得到的结果,通过‘+’运算符运算后,其结果作为‘*’的操作数,意即从起始地址增加的位移,最终结果为指向b[i][j]操作数的指针值。
3.17变量是抽象的值,类型是抽象的变量,也是抽象的值,按类型层次可以不定义类型的类型?
他们的值集,操作集又是什么?
解:
变量是抽象的值,类型是抽象的变量,也是抽象的值,按类型层次可以定义类型的类型,它们的值集应是所有类型组成的集合。
也可以由某种具体的语言限制其值集,只允许几种特定的类型值。
它的操作集可以包括组装(几种不同的类型组成一种复杂类型),比较相等(两种类型是否是同一类型)、赋值由已定义的类型产生新的类型拷贝)等等。
4.1一般变量和指针变量有何不同?
引用类型变量与它们又有何不同?
答:
在寻址对照表中,一般变量对应的地址码即为该变量值的存储单元,而指针变量对应的地址码则为该指针所指向的存储单元的地址。
引用型变量与指针变量的区别在于它是常指针,一旦对照表建立,也就创建了引用,不可改变。
引用是变量的别名,但它必须赋初值。
4.2C语言中的数组名的含义是什么?
当把数组的地址赋给某指针时是否要用运算符?
为什么?
答:
C语言中的数组名可以看作是一个指针变量名,它代表数组元素的首地址。
但其值不可改变,这一点与引用型变量有些类似。
当把数组的地址赋给某指针时不用运算符,因为数组名本身就是指向数组首地址的指针。
4.6何谓运行时堆栈?
堆栈帧?
堆?
答:
运行时堆栈是在内存开辟一个空间,如同堆栈。
首先将程序代码和全局静态变量装入。
在执行控制开始时首先执行这一块;当执行调用时,按编译时生成的嵌套关系,结合动态链和静态链来增、减堆栈帧。
堆栈帧是指在运行时把每次调用所需的数据作为一帧,并包括返回地址、动态链、静态链、返回值和局部变量,压入运行堆栈栈顶。
当对应的子程序执行完毕,该帧失去定义(可为新调用覆盖)。
堆是内存中预留的一片自由空间,当程序在运行过程中需要动态分配空间时,由操作系统从堆中按照一定的算法分配所需的变量的存储空间。
4.8设计一个程序输入随机的一千个职工记录。
用重排指针的方法,按姓名的字典序;按年龄(由小到大),按小单位名的字典序,按工资多少(由大到小)各打印一个报告,即重排的原记录。
#include"stdafx.h"
#include"stdio.h"
#include"string.h"
structcrew
{
charname[20];
charunit[50];
intage;
floatincome;
crew*next;
}*head;
voidsortbyname();
voidsortbyunitname();
voidsortbyincome();
voidsortbyage();
voidprint();
voidmain()
{
intI;
structcrew*p,*sav;
head=newcrew[101];
for(I=0;I<100;I++)
head[I].next=&head[I+1];
p=head;
for(I=0;I<100;I++)
{
scanf("%s%s%d%f",p->name,p->unit,&p->age,&p->income);
if(I)
{
p=sav->next;
}
sav=p;
}
sortbyname();
sortbyunitname();
sortbyincome();
sortbyage();
}
voidsortbyname()
{
intI=0,j=0;
crew*tmp1,*tmp2;
while(I<100)
{
for(j=I+1;j<100;j++)
{
if(strcmp(head[I].name,head[j].name)>0)
{
tmp1=&head[I];
tmp2=&head[j];
head[j-1].next=&head[j+1];
head[I-1].next=tmp2;
tmp2->next=tmp1;
}
}
I++;
}
print();
}
voidsortbyage()
{
intI=0,j=0;
structcrew*tmp1,*tmp2;
while(I<100)
{
for(j=j+1;j<100;j++)
{
if(head[I].age>head[j].age)
{
tmp1=&head[I];
tmp2=&head[j];
head[j-1].next=tmp2;
tmp2->next=tmp1;
}
}
I++;
}
print();
}
voidsortbyunitname()
{
intI=0,j=0;
structcrew*tmp1,*tmp2;
for(I=0;I<100;I++)
for(j=I+1;j<100;j++)
{
if(strcmp(head[I].name,head[j].name)>0)
{
tmp1=&head[I];
tmp2=&head[j];
head[j-1].next=&head[j+1];
head[I-1].next=tmp2;
tmp2->next=tmp1;
}
}
for(I=99;I>=0;I--)
for(j=I-1;j>=0;j--)
{
if(!
(strcmp(head[j].name,head[I].name)>0))
{
tmp1=&head[I];
tmp2=&head[j];
head[j-1].next=&head[j+1];
head[I-1].next=tmp2;
tmp2->next=tmp1;
}
}
print();
}
voidsortbyincome()
{
intI=0,j=0;
crew*tmp1,*tmp2;
while(I<100)
{
for(j=j+1;j<100;j++)
{
if(head[I].income
{
tmp1=&head[I];
tmp2=&head[j];
head[j-1].next=&head[j+1];
head[I-1].next=tmp2;
tmp2->next=tmp1;
}
I++;
}
}
print();
}
voidprint()
{
intI=0;
for(I=0;I<=100;I++)
{
printf("%10s%10s%10d%10d",head[I].name,head[I].unit,head[I].age,head[I].income);
printf("\n");
}
}
4.10见例4-4
4.15指针变量如同语句中的goto,愿意指谁就指谁,没有章法,goto的问题已用结构化解决了,你能想出有效管理指针的方案吗,至少要谈出途径。
解:
悬挂引用主要是指指针指向一个已死的或无定义的对象。
主要出错情况有两种:
1.未给一个指针变量分配空间就给它赋值;
2.函数返回局部变量指针。
解决方案
①在对指针实施运算的地方,检查指针变量是否已赋初值,即指针变量是否已指向合法位置。
②在对指针变量赋值的地方,检查指针变量是否先前已指向其他合法位置,避免悬挂引用。
③在对指针变量赋值(特别是数组)时,记录其“元素”的个数,以便能在其后的操作中检查是否越界。
④在对指针变量赋值的地方,记录引用对象已被哪些指针指向,为此引用对象被除时,提出编译警告,告许程序员哪些指针已悬挂。
5.1程序对象、标识符、名字、存储对象它们各自的含义并有什么关系?
答:
程序对象是名字和存储对象的结合体;
标识符和名字都是用以代表程序对象的,标识符是一字符串用于命名程序中某个(语法)元
素。
名字也是字符串用以表示程序中的实体。
以使人们从语义角度使用它。
一般情况下,名字对应一简单标识符。
有时代表多个构件的组合。
存储对象是机器内部程序对象的具体实现。
关系:
一个名字可对应几个程序对象,一个程序对象也可对应多个名字,这些是由不同的束定机制来决定的。
5.5何谓束定?
束定和指针,引用有何不同?
答:
束定是将名字(标识符)和可束定体联系起来,所谓可束定体是能反映出语义的存储块。
如常量、变量的存储体、函数体、过程体、类型和异常。
或者束定是将程序中代表对象的标识符和实现程序对象的存储对象联系起来的动作。
指针是程序可以令其指向任何程序实体,引用是常指针。
不同:
①束定是编译(或解释器)做的。
,为每一个名字分配其语法要求的存储,也以跨越时间,编译时占个位置,运行时再分配(实现束定)。
②翻译器可以自动递引用束定而不能自动递引用指针。
5.11指出以下Pascal程序各标号处的束定环境。
PROGRAMA;
CONSTx=999;
TYPENat=0..maxint;
VARm,n:
Nat;
(1)
FUNCTIONf(n:
Nat):
Nat;
BEGIN
(2)
END;
PROCEDUREw(j:
Nat);
(3)CONSTn=6;
BEGIN
(4)
END
BEGIN
(5)
END
(1)处环境x整常量999
Nat类型0…maxint
m,nnat类型变量
(2)处环境为x→整常量(3)处环境x整常量999
m,n→nat类型变量m,nnat类型变量
jnat类型变量
(4)处环境:
jNat类型变量的参数(5)处环境:
x→整常量
n常量6Nat→类型变量
x→整常量999m,n→nat类型变量
mnat类型变量度f→函数抽象
w→过程抽象(如有递归)w→过程抽象
f→函数抽象(如有调用)
5.14为什么递归定义只能用动态作用域?
答:
动态作用域是指新的存储块(堆栈帧)一直保留对参数和局部量的束定,直至该程序块出口才释放的堆栈帧,递归定义的函数在每次递归调用本函数时都要作新的存储分配形成新一层堆栈帧,所以只能用动态作用域。
6.2试述以下函数调用的优缺点:
(a)利用缺省参数形实参数个数可不匹配(Ada,C++)
答:
优点:
调用灵活、简洁,使用方便;效率高;
缺点:
易带来副作用,引起参数丢失、误用。
(b)Ada指明参数调用次序随意。
优点:
灵活、安全、不需要记住参数名。
缺点:
要求程序员记住所有的参数名。
(C)C语言某些函数参数个数随意。
优点:
灵活、可通过参数个数,类型的多样化实现过程函数,高阶函数等。
缺点:
不安全、易引起函数功能误用。
(d)ANSIC的参数原型
优点:
安全、有利于进行强类型检查,易于区分参数与局部变量。
缺点:
不够灵活方便,在函数调用时参数个数、类型、位置对应关系限制较严。
(e)Ada有参数模式,C++为什么没有。
答:
开发并发进程、多进程时易只读,只写。
Ada的参数模式中的Out模式保证了在多进程、并发程序中的安全性,所以多用于开发多进程,而C++一般不用于开发多进程。
6.11按以下表格回答问题
变量类型
创建时间
死亡时间
何处访问
全局变量
1
2
3
静态局部变量
4
5
6
一般局部变量
7
8
9
动态堆变量
10
11
12
答:
1:
装入时2:
程序终止时3:
整个程序4:
装入时5:
程序结束6:
声明所在块
7:
声明处8:
块出口9:
声明所在块10:
声明处11:
块出口12:
声明所在块
6.13何谓高阶函数,它有什么用?
编制一个仿真高阶函数的应用。
答:
以函数或过程作为实参变元或返回值的函数或过程,我们统称为高阶函数。
作用:
①函数作为变元的需求主要是为通用化程序单元而提出的。
②作映射函数。
把单目、双目运算扩充到多个数据对象的数组或表上。
见书“凯人勒函数求根”
7.6有以下类pascal程序片断
k:
=3
FORi=1TOkDO
BEGIN
Writeln(i,k);
k:
=k+1;
END;
Writeln(i);
这个程序终止吗?
为什么?
最后一句写出什么?
答:
这个程序终止,因为循环中递归变量值改变,并最终达到终值,而pascal程序中又不能改变循环终值最后一句写出4。
7.8设计一个for循环要考虑哪些问题?
试写一设计需求规格说明。
答:
考虑的问题。
\
1循环控制变量(初值)、终值、增量表达式、条件表达式、循环体;
2循环控制变量类型:
整型、离散、实型;循环控制变量:
全局静态、局部静态、局部变量;
3终值和增量表达式在循环中允许改变否?
4条件表达式EXP2在顶部求值还是在底部求值。
7.12C语言中有一顺序控制器continue它的作用是什么?
写出continue出现在for循环时等价语义的while_do形式:
for(Exp1,Exp2,Exp3){
.
.
(1)
.
if(Exp4)
continue
.
.
(2)
.
}
答:
作用:
结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。
等价语义的while_do形式:
Exp1;
while(Exp2)do
{
Exp3;
(1);
if(!
Exp4)
{
(2);
}
}
7.15有以下Ada程序片断
typeMONTHis(JAN,FEB,MAR,…,NOV,DEC_);
RAINFALL:
array(MONTH)ofFloat;
procedureGET_VEATHER_DATAis
begin
forAMONTHinMONTHLOOP
begin
GET(RAINFALL(AMONTH));
exception
whenDATA_ERROR=>
PUT(“Invaliddatafor“);PUT(AMONTH);
SKIP_DATA_ITEM;
RAINFALL(AMONTH):
=0.0;
end
endloop;
endGET_WEATHER_DATA;
该程序读取每月雨量数据以判断天气。
若雨量RAINFALL数据格式不对,引发异常,处理时RAINFALL数组中该项为零,并读下一项。
异常DATA_ERROR是系统定义的异常还是用户定义的?
它在哪儿引发?
不用异常能否处理?
若能改写之。
答:
异常DATA_ERROR是系统定义的
它在语句GET(REINFALL(AMONTH))处引发。
不用异常可以处理,改写如下:
begin
forAMONTHinMONTHloop
begin
GET(RAINFALL(AMONTH));
if(RAINFALL(AMONTH)/=float)then
PUT(“Invaliddatafor“);PUT(AM