Icon編程語言手冊(cè) 簡略翻譯版 第二章

第二章 基礎(chǔ)知識(shí)

2.1 編譯和運(yùn)行Icon程序

作者假設(shè)你的系統(tǒng)上安裝了Icon 9版本。

假設(shè)你把Icon程序命名為“test”。你把你的Icon程序放在一個(gè)文件“test.icn”中。然后用icont命令編譯它

? ? icont test

如果編譯沒有出現(xiàn)錯(cuò)誤,則使用命令運(yùn)行它

? ? test

如果有錯(cuò)誤,Icon編譯器會(huì)告訴你它在哪里遇到了錯(cuò)誤以及錯(cuò)誤是什么。我們將在稍后的第14章中進(jìn)行更全面的討論。

2.2 Hello, world

習(xí)慣上,寫一個(gè)“hello, world”程序作為開始,正常的話它會(huì)輸出“hello, world”來。

例1 Hello world

? ? procedure main()

? ? ? ? write("hello, world")

? ? end

您可以看到編寫過程的方法:以procedure開始,以end結(jié)束。過程后面是過程名稱和參數(shù)列表,可以為空。

write函數(shù)將其參數(shù)寫入輸出,然后終止該行(再用一條write會(huì)從下一行開始寫)。

字符串是用雙引號(hào)括起來。

當(dāng)程序開始運(yùn)行時(shí),它執(zhí)行名為main的過程,就像在C中一樣。

在下面的例2中,我們展示了在Icon中,用新行或分號(hào)(如果您愿意,也可以兩者都用)分隔序列中的表達(dá)式。Icon按順序執(zhí)行表達(dá)式。該writes函數(shù)(注意相比上例中函數(shù)多個(gè)s)將其參數(shù)寫入輸出,但不終止該行。接下來寫的內(nèi)容將在同一行。

例2 表達(dá)式序列

? ? procedure main()

? ? ? ? writes(”hello,”)

? ? ? ? write(” world”)

? ? end

? ? procedure main()

? ? ? ? writes(”hello,”);

? ? ? ? write(” world”)

? ? end

? ? procedure main()

? ? ? ? writes(”hello,”); write(” world”)

? ? end

Icon是一種弱類型語言。這意味著變量沒有被聲明為具有特定的數(shù)據(jù)類型。只有值才有數(shù)據(jù)類型,任何類型的值都可以賦值給任何變量。就此而言,變量根本不需要聲明。下面例3說明了這一點(diǎn)。

賦值操作符是“:=”。

變量x被分配了兩個(gè)不同類型的值,第一個(gè)是字符串,然后是整數(shù)。

過程write可以像輸出字符串一樣輸出整數(shù)。事實(shí)上,它會(huì)輸出任何它知道如何轉(zhuǎn)換為字符串的東西。

例3 弱類型

? ? procedure main()

? ? ? ? x := "Example "

? ? ? ? writes(x)

? ? ? ? x := 1

? ? ? ? write(x)

? ? end

例4顯示了局部聲明和交換操作符。

過程中的局部變量在進(jìn)入過程時(shí)分配內(nèi)存,在過程返回時(shí)消失。如果沒有對(duì)變量的聲明,如例3中的x,則編譯器將其變?yōu)榫植孔兞俊?/p>

“:=:”是交換操作符;它將交換兩個(gè)變量的值。

例4 局部聲明

? ? procedure main()

? ? ? ? local x,y

? ? ? ? x := " Example "

? ? ? ? y := 2

? ? ? ? write(x,y)

? ? ? ? x :=: y

? ? ? ? write(x,y)

? ? end

當(dāng)創(chuàng)建變量時(shí),它們被賦予初始值null,這導(dǎo)致大多數(shù)操作在運(yùn)行時(shí)報(bào)告錯(cuò)誤。您將經(jīng)常遇到這種運(yùn)行時(shí)錯(cuò)誤。

例5 未初始化變量

? ? procedure main()

? ? ? ? local x

? ? ? ? write(x+1)#this will cause an error at run time

? ? ? ? ? ? ? ? ? # (and notice: comments begin with

? ? ? ? ? ? ? ? ? # and run to the end of the line)

? ? end

2.3 聲明

我們已經(jīng)看到了局部聲明。Icon實(shí)際上提供了以下所有種類的聲明:

local x,y,z? #定義在過程內(nèi)。每當(dāng)進(jìn)入過程時(shí),創(chuàng)建變量的新副本。在過程返回時(shí)刪除它們。這些名稱僅在過程中是已知的。對(duì)于未聲明的變量,假設(shè)是局部的,但不要使用此特性:稍后引入全局聲明可能會(huì)導(dǎo)致過程停止工作。

static x,y,z? #定義在過程內(nèi)。在程序開始執(zhí)行時(shí)創(chuàng)建變量的副本。這些名稱僅在過程中是已知的。靜態(tài)變量只有一個(gè)副本。它在過程調(diào)用之間保持其值。

global x,y,z? #定義在過程外。在程序開始執(zhí)行時(shí)創(chuàng)建變量的副本。只有在沒有為局部變量或靜態(tài)變量聲明相同名稱的所有過程中才知道這些名稱。全局變量只有一個(gè)副本。

procedure? #定義在過程外,不能嵌套。參見第5章“過程”

name(x,y,z)

? ? ...

end

record name(x,y,z)? #定義在過程外。參加第2.10節(jié)和第12章

link name? #定義在過程外。告訴鏈接器該程序使用文件名中聲明的過程、記錄或全局變量。名稱可以是Icon標(biāo)識(shí)符,但如果包含Icon標(biāo)識(shí)符中不允許的字符,則必須是帶引號(hào)的字符串。

2.4 退出程序

有幾種方法可以退出Icon程序。您已經(jīng)看到的方法是從過程main返回。還有兩個(gè)函數(shù)也被使用,exit和stop。

exit()? #以正常退出狀態(tài)退出程序(即,告訴操作系統(tǒng)一切正常)。

exit(n)? #退出程序并返回整數(shù)n作為退出狀態(tài)。這是告訴操作系統(tǒng)事情不正常的方法,但是您必須知道操作系統(tǒng)如何解釋這些退出狀態(tài)值才能使用它。

stop(s1,s2,...,sn)? #輸出字符串s1 s2…Sn,退出時(shí)顯示錯(cuò)誤狀態(tài)。進(jìn)一步請(qǐng)看第8章I/O部分。

2.5? 數(shù)字

2.5.1 整數(shù)字面值

您可以將整數(shù)字面值(常量)寫成十進(jìn)制數(shù),例如25。

2.5.2 整數(shù)運(yùn)算符

+? 加號(hào)? 優(yōu)先級(jí)8

-? 減號(hào)? 優(yōu)先級(jí)8

*? 乘號(hào)? 優(yōu)先級(jí)9

/? 除號(hào)? 優(yōu)先級(jí)9

%? 余號(hào)? 優(yōu)先級(jí)9

^? 乘方? 優(yōu)先級(jí)10

除冪運(yùn)算符首先在最右邊執(zhí)行外,其他運(yùn)算符從左到右執(zhí)行。運(yùn)算符*、/和%在+和-之前完成。^運(yùn)算符在其他運(yùn)算符之前執(zhí)行。也就是說,優(yōu)先級(jí)數(shù)大的操作符在優(yōu)先級(jí)小的運(yùn)算符之前執(zhí)行。

2.6 字符串

2.6.1 字符串字面值

你寫一個(gè)用引號(hào)括起來的字符串字面值(常量):

"Like this"

如果您需要在字符串中包含引號(hào),請(qǐng)?jiān)谄淝懊婕由戏葱备?,例?\""。如果你需要包含一個(gè)反斜杠,在它前面放一個(gè)反斜杠,"\\"。有一些特殊的方法可以包含其他字符,見后面的章節(jié)。

2.6.2 字符串操作符

您可以使用“||”運(yùn)算符連接兩個(gè)字符串,例如:

? ? s:="ab"

? ? s:=s||"cd"

? ? write(s)

會(huì)輸出“abcd”。

您可以使用一元“*”運(yùn)算符找出字符串的長度,例如:

? ? s:="abc"

? ? write(*s)

? ? s:="a"

? ? write(*s)

? ? s:=""

? ? write(*s)

會(huì)輸出

? ? 3

? ? 1

? ? 0

2.6.3 字符串下標(biāo)

字符串中的字符按照字符串長度從1開始編號(hào)。你可以給字符串下標(biāo),就像在大多數(shù)其他語言中給數(shù)組下標(biāo)一樣,把索引放在字符串后面的括號(hào)里:

? ? s:="find"

? ? write(s[3])

? ? s[4] := "e"

? ? write(s)

會(huì)輸出

? ? n

? ? fine

與C語言不同,它沒有單獨(dú)的字符類型。只有長度為1的字符串。上面的表達(dá)式[3]返回一個(gè)長度為1的字符串“n”。

當(dāng)用字符串下標(biāo)賦值,可以賦值多個(gè)字符的字符串或空字符串。例如:

? ? s:="fund"

? ? s[4] := ""

? ? write(s)

? ? s[3] := "nny"

? ? write(s)

會(huì)輸出

? ? fun

? ? funny

Icon還允許您使用位置范圍下標(biāo)字符串,選擇多于或少于一個(gè)字符。

s[i:j]

(其中i≤j),它從字符i到字符j之間選擇子字符串,但不包括字符j。

如果分配給子字符串,則替換所選字符。如果在賦值時(shí)i=j,則插入到字符i之前。如果i=j=*s+1,則追加到字符串s之后

? ? s:="12345"

? ? write(s)

? ? s[3:3]:="x"? #當(dāng)i=j時(shí),會(huì)把字符串插到原字串位置i字符之前

? ? write(s)

會(huì)輸出

? ? 12345

? ? 12x345

? ? s:="12345"

? ? write(s)

? ? s[3:4]:="x"? #當(dāng)i:i+1時(shí),會(huì)把字符串插到原字串位置i字符那

? ? write(s)

會(huì)輸出

? ? 12345

? ? 12x45

? ? s:="12345"

? ? write(s)

? ? s[3:5]:="x"? #當(dāng)i:i+n(2或更大)時(shí),會(huì)把原字串位置i到i+(n-1)的字符串變"",然后插入此位置

? ? write(s)

會(huì)輸出

? ? 12345

? ? 12x5

? ? s:="12345"

? ? write(s)

? ? s[3:5]:="xyz"? #當(dāng)i:i+n(2或更大)時(shí),會(huì)把原字串位置i到i+(n-1)的字符串變"",然后插入此位置

? ? write(s)

會(huì)輸出

? ? 12345

? ? 12xyz5

? ? s:="12345"

? ? write(s)

? ? s[*s+1:*s+1]:="yz"? #i=j=*s+1,則追加到字符串s之后

? ? write(s)

會(huì)輸出

? ? 12345

? ? 12345yz

? ? s := "12345"

? ? write(s[6])? #超出長度不會(huì)報(bào)錯(cuò),只會(huì)輸出空串

會(huì)輸出


s := "12345"

write(s[0])? #取下標(biāo)0會(huì)輸出空串

會(huì)輸出


? ? s := "12345"

? ? write(s[-1])? #當(dāng)負(fù)數(shù)下標(biāo)會(huì)從右側(cè)數(shù)取位置

會(huì)輸出

? ? 5

2.6.4 比較運(yùn)算符

下面是數(shù)字和字符串的基本比較運(yùn)算符:

i=j? s1==s2? 相等? 優(yōu)先級(jí)6

i~=j? s1~==s2? 不相等? 優(yōu)先級(jí)6

i<j? s1<<s2? 小于? 優(yōu)先級(jí)6

i<=j? s1<<=s2? 小于等于? 優(yōu)先級(jí)6

i>j? s1>>s2? 大于? 優(yōu)先級(jí)6

i>=j? s1>>=s2? 大于等于? 優(yōu)先級(jí)6

2.7 基本控制結(jié)構(gòu)

以下是Icon中使用的三種最常見的控件結(jié)構(gòu)。我們省略了大部分細(xì)節(jié),詳見第4章:

2.7.1 If表達(dá)式

你可以使用if表達(dá)式選擇要執(zhí)行的代碼:

? ? if expr1 then expr2 else expr3

目前,我們只在expr1中使用一個(gè)比較運(yùn)算符。如果expr1成功(在其他語言中我們會(huì)說,如果expr1為真,但在Icon中我們不會(huì)這么說,我們?cè)谶@兒說“成功”),那么Icon執(zhí)行expr2,否則,Icon執(zhí)行expr3。

第3章和第4章將更詳細(xì)地討論expr1的其他選項(xiàng)。

因?yàn)閕f表達(dá)式是一個(gè)表達(dá)式,所以它返回一個(gè)值,expr2或expr3的值。

2.7.2 While表達(dá)式

你可以使用while表達(dá)式來重復(fù)執(zhí)行一些代碼:

? ? while expr1 do expr2

同樣,目前我們將把自己限制在expr1中的單個(gè)關(guān)系操作符。只要expr1成功,Icon就執(zhí)行expr2。盡管while表達(dá)式是一個(gè)表達(dá)式,但它不返回值。

2.7.3 表達(dá)式序列

你可以使用大括號(hào){expr1;expr2;…;exprn},對(duì)表達(dá)式序列進(jìn)行分組,以便將它們包含在if表達(dá)式或while表達(dá)式中。大括號(hào)內(nèi)的表達(dá)式用分號(hào)分隔,或者用新行分隔,或者兩者同時(shí)分隔,就像過程體中的表達(dá)式序列一樣。

表達(dá)式序列是一個(gè)表達(dá)式。它返回序列中最后一個(gè)表達(dá)式的值。

2.8 基本生成器

生成器是傳遞一系列值的表達(dá)式,是Icon的核心。它們將在第3章中深入討論。這里我們只展示其中一個(gè)用途。

這循環(huán)

? ? every i := 1 to 10 do expr

是Icon中的for循環(huán)。表達(dá)式“1 to 10”是一個(gè)生成器,它生成整數(shù)1,2,…10。每個(gè)值被賦給變量i,表達(dá)式expr被求值。

幾個(gè)生成器可以與&操作符組合使用,以實(shí)現(xiàn)嵌套循環(huán)的效果:

? ? every i := 1 to 10 & j := 1 to 10 do expr

行為類似于兩個(gè)嵌套的for循環(huán)。當(dāng)i = 1時(shí),j將從1迭代到10,然后當(dāng)i = 2時(shí),j將從1迭代到10,以此類推。

您還可以添加測試以消除一些迭代:

? ? every i := 1 to 10 & j := 1 to 10 & i ~= j do expr

如果I和j的值相同就會(huì)忽略expr的取值。

2.9 基本列表

2.9.1 List創(chuàng)建:list (n)

列表類似于其他語言中的數(shù)組。您可以使用list函數(shù)創(chuàng)建一個(gè)元素編號(hào)為1、2、…n的列表

例如:

? ? L:=list(3)

將創(chuàng)建一個(gè)長度為3的列表,并將其賦值給變量L。列表中的所有元素將初始化為null。

2.9.2 列表下標(biāo)

長度為n的列表是一個(gè)包含n個(gè)元素的數(shù)組,元素的編號(hào)從1到n,就像數(shù)組一樣。列表下標(biāo)的方式與字符串相同:將下標(biāo)表達(dá)式放在列表后面的括號(hào)中,例如:

? ? L:=list(2)

? ? L[1]:=5

? ? L[2]:=10

? ? write(L[1])

會(huì)輸出

? ? 5

您可以創(chuàng)建長度為0的列表。只需list(0)

2.9.3 List創(chuàng)建:[...]

如果要?jiǎng)?chuàng)建一個(gè)包含特定值的短列表,你可以在括號(hào)中列出你想要的值:

? ? L:=[5,10]

? ? write(L[1])

會(huì)輸出

? ? 5

您可以通過寫[]來創(chuàng)建一個(gè)長度為0的列表。

2.9.4 List創(chuàng)建:list(n,x)

如果你想創(chuàng)建一個(gè)所有元素都相同的列表,但不是null,使用list(n,x),它將創(chuàng)建一個(gè)長度為n的列表,所有元素都是x。

2.9.5 列表操作符

你可以用操作符“|||”連接兩個(gè)列表,例如:

? ? s:=[5,6]

? ? s:=s|||[7,8]

? ? write(s[3])

會(huì)輸出

? ? 7

x|||y的結(jié)果是一個(gè)新的列表,其中包含x的元素和y的元素。列表x和y不會(huì)改變。

你可以使用一元*運(yùn)算符找出列表的長度,例如:

? ? s:=[1,2,3]

? ? write(*s)

? ? s:=[]

? ? write(*s)

會(huì)輸出

? ? 3

? ? 0

可以使用===或~===操作符比較兩個(gè)列表是否相同。(連續(xù)使用三個(gè)等號(hào)。)怎樣才能成為相同的列表呢?請(qǐng)看

? ? L:=[1,2]

? ? M:=L

在此代碼之后,L === M將成功,L ~=== M將失敗。賦值M:=L使L和M指向同一個(gè)列表。再看

? ? L:=[1,2]

? ? M:=[1,2]

在此代碼之后,L ~=== M將成功,L === M將失敗。賦值M:=[1,2]使得M指向一個(gè)不可能與L相同的新列表。即使L和M指向具有相同長度和相同內(nèi)容的列表,它們也不相同。

例子:

? ? x:=1

? ? y:=1

? ? write(if x === y then "equal" else "not equal")

會(huì)輸出

? ? equal

例子:

? ? x:=1

? ? y:="1"

? ? write(if x === y then "equal" else "not equal")

會(huì)輸出

? ? not equal

例子:

? ? L:=[[1],[1]]

? ? write(if L[1] === L[2] then "equal" else "not equal")

會(huì)輸出

? ? not equal

因?yàn)閮纱螁为?dú)出現(xiàn)的[1]創(chuàng)建了兩個(gè)不同的列表。

例子:

? ? L:=list(2,[1])

? ? write(if L[1] === L[2] then "equal" else "not equal")

會(huì)輸出

? ? equal

因?yàn)樵趌ist函數(shù)中出現(xiàn)[1]只計(jì)算一次,創(chuàng)建一個(gè)列表,它被分配給L的兩個(gè)元素。

2.9.6 列表與字符串的區(qū)別

下面是列表和字符串之間的一些區(qū)別:

字符串有字面值,列表沒有字面值。

列表是可變值;字符串是不可變的。這意味著您可以更改列表中的一個(gè)元素,并在與該元素相等(===)的所有列表中看到該更改。如果您更改字符串變量中的一個(gè)字符,Icon實(shí)際上會(huì)用所做的更改創(chuàng)建一個(gè)新字符串,并將該新字符串賦值給變量。

當(dāng)您將值賦給列表的元素時(shí),列表的長度不會(huì)改變。將字符串賦值給下標(biāo)字符串時(shí),字符串的長度可以更改。您分配的字符串在替換該位置的字符時(shí)被拼接。

過程write將輸出一個(gè)字符串。它不會(huì)寫出一個(gè)列表。

可以將一個(gè)列表賦值給另一個(gè)列表的元素。你可以將一個(gè)列表賦值給它自身的元素,得到一個(gè)循環(huán)結(jié)構(gòu)。

雖然Icon里皆是表達(dá)式,但不能對(duì)一個(gè)引號(hào)的字符串用下標(biāo)方式改變內(nèi)容,如:

? ? "abcd"[2]:="x"? #這是錯(cuò)的

但神奇的是,Icon列表這么寫卻是合法的,如:

? ? [1,2,3][2]:=5

2.9.7 main過程參數(shù)

過程main接受一個(gè)參數(shù),是個(gè)列表變量,所有命令行傳來的參數(shù)都放入這個(gè)字符串列表。如上所述,實(shí)際上不必用參數(shù)聲明過程main。下面是一個(gè)使用參數(shù)的例子,一個(gè)程序回顯命令行參數(shù):

? ? procedure main(args)

? ? ? ? i := 1

? ? ? ? while i <= *args do {

? ? ? ? write(args[i])

? ? ? ? i:=i+1

? ? ? ? }

? ? end

執(zhí)行test -a 123 -b xyz

會(huì)顯示

? ? -a

? ? 123

? ? -b

? ? xyz

2.10 記錄

您可以在Icon中創(chuàng)建新的記錄數(shù)據(jù)類型,就像在Pascal(記錄)、C(結(jié)構(gòu))和c++(類)中一樣。聲明一個(gè)記錄類型:

? ? record rname(f1,f2,...,fn)

? “rname”是給記錄類型的名稱。

? f1, f2, …, fn是給定給記錄的字段(成員)的名稱。

? 記錄聲明只允許在過程聲明之外使用。

例子

? ? record Point(x,y)

可用于在二維坐標(biāo)系中定義一個(gè)點(diǎn)。

一個(gè)點(diǎn)可以通過表達(dá)式創(chuàng)建:

? ? r := Point(1,2)

它將創(chuàng)建一個(gè)Point類型的新記錄,將其x字段初始化為1,y字段初始化為2,并將Point記錄賦值給變量r。

記錄的字段可以使用二進(jìn)制“?!保侄我?,操作符,例如。

記錄的字段可以使用“.”操作符來訪問,例如:

? ? r.x := r.y

與 Pascal、C 和 C++ 不同,Icon沒有顯式指針。

? ? p1 := Point(1,2)

? ? p2 := p1 #p2 points to p1

? ? p2.x := 2 #also changes p1.x

? ? write(if p1 === p2 then "equal" else "not equal")

? ? write(if p1.x === p2.x then "equal"

? ? else "not equal")

會(huì)輸出

? ? equal

? ? equal

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容