檔案是由分開的不同文字塊組成的。這些文字可用作命令、屬性名稱、字串、數字等。所使用的這些內容有乙個共同點,即它們是用分隔符分開的。分開的每一組文字稱為乙個令牌。檔案可以由許多令牌組成,每個令牌都有自己的用途和含義。在不考慮出現令牌原因的情況下,令牌只是一些文字。如果願意的話,有時可以將檔案分隔成一系列令牌——令牌流——這是一種很好的做法。如果讀者曾經研究過更高階型別的指令碼,實際上就會發現這只是為了將指令碼編譯成一種更低階形式而要做的一些工作。也許在建立命令和屬性指令碼系統時,已經使用過令牌流。雖然有一種獲取資訊的方法,但如果本該使用令牌流而沒有使用,那麼這個方法就不是很清晰。例如,對屬性指令碼而言,使用令牌流,所要做的全部工作就是呼叫某類函式,如getnexttoken(),將其賦給屬性名稱,然後再次呼叫getnexttoken()函式獲取屬性值。對命令指令碼,可以使用getnexttoken()函式獲取命令名,再次呼叫該函式可以獲取跟在命令後的單個值或一組值,所有工作只需乙個函式即可完成。
雖然本章並未對開發的指令碼演示程式使用令牌流,但稍後在模型載入一章將使用它。在此,對它做個介紹,因為即使本書已經介紹了書中使用的兩個系統,但令牌流確實與指令碼緊密相關。將要建立的類似檔案作為引數,並在每次呼叫乙個名為getnexttoken()函式時返回該檔案中的下乙個令牌。對該令牌所做的處理取決於正在使用它的程式。
演示程式將載入檔案,顯示檔案中的令牌流數目,檔案的位元組數以及整個檔案的令牌流。這裡將使用std::cout向螢幕上顯示內容。控制台程式也會讓人生厭,但它對驗證這個主題卻非常合適。
演示程式中要介紹的第乙個檔案是main.cpp原始檔。該演示程式由4個檔案構成:main.cpp、tokensfile.txt、token.h和token.cpp。在演示程式的main函式中,將整個檔案載入到記憶體中,將其設定為令牌流,並輸出一些與令牌流相關的資訊。該資訊是指明檔案大小的位元組數、令牌數目以及檔名。完成該工作後,用空格分開顯示每個令牌。如果檢視將要載入的tokensfile.txt檔案,會發現它包含了隨機單詞和一些用空格分開的無規則的數。由於空格是分隔符,因此可以忽律令牌之間的其他行和空格。空格和新行只是為了讓人看著方便,對機器卻沒有任何意義。一旦顯示完令牌,就可以關閉程式。
main.cpp
#include<
iostream
>
#include
"token.h
"using
namespace
std;
intmain(
intarg,
char
**argc)
//get the length of the file.
fseek(file,
0, seek_end);
intlength
=ftell(file);
fseek(file,
0, seek_set);
//read in all data from the file.
char
*data
=new
char
[(length +1
) *sizeof
(char
)];if(!
data)
return
null;
fread(data, length,
1, file);
data[length] ='
\0';//
close the file when we are done.
fclose(file);
//set our file to our lexer.
ctoken token;
token.settokenstream(data);
//no longer need.
delete data;
data
=null;
//get total tokens.
inttotaltokens =0
;char
buff[
256] =;
while
(token.getnexttoken(buff))
if(buff[0]
!='\0'
) totaltokens++;
//print statistics.
cout
<<
"file name:
"<<
"tokens.txt.
"<<
endl;
cout
<<
"file size in bytes:
"<<
length
<<".
"<<
endl;
cout
<<
"total number of tokens:
"<<
totaltokens
<<".
"<<
endl;
cout
<<
endl
<<
endl;
cout
<<
"token stream:
"<<
endl
<<
endl;
//reset.
token.reset();
//print all tokens.
while
(token.getnexttoken(buff))
if(buff[0]
!='\0'
) cout
<<
buff
<<""
;//release all memory.
token.shutdown();
cout
<<
endl
<<
endl
<<
endl;
return0;
}
token.h
#ifndef _ugp_token_h_#define
_ugp_token_h_
class
ctoken
~ctoken()
//返回到檔案的頭部
void
reset()
void
settokenstream(
char
*data);
//@buffer 儲存令牌的快取
bool
getnexttoken(
char
*buffer);
//@token 令牌
//@buffer 儲存令牌的快取
bool
getnexttoken(
char
*token,
char
*buffer);
//移動到檔案的下一行
bool
movetonextline(
char
*buffer);
void
shutdown();
private://
檔案長度
intm_length;
//跟蹤檔案的起始索引和終止索引
intm_startindex, m_endindex;
//檔案資料流
char
*m_data;
};#endif
token.cpp
#include<
string
.h>
#include
"token.h
"bool
isvalididentifier(
char
c)void
ctoken::settokenstream(
char
*data)
bool
ctoken::getnexttoken(
char
*buffer)
//將終止索引賦值為起始索引+1
m_endindex
=m_startindex +1
;if(m_startindex
<
m_length)
else
buffer[0]
='\0'
;}return
true;}
return
false;}
bool
ctoken::getnexttoken(
char
*token,
char
*buffer)
bool
ctoken::movetonextline(
char
*buffer)
}else
return
false
;return
true;}
void
ctoken::shutdown()
Nebula3指令碼系統
nebula2的指令碼系統實現了乙個面向c 的指令碼介面,它把指令碼命令直接對映到了c 方法.從技術角度來說,這是乙個簡捷的思路,但是對於需要把遊戲邏輯和行為指令碼化的關卡設計師來說,nebula2的指令碼系統太底層和透明了.關卡邏輯指令碼一般來說構架於比c 介面更高階的層次上,直接把指令碼命令對映...
shell 指令碼 系統檢測
bin bash 介面輸出區 optimize 函式命令區 order ip get sed s space g grep v lo echo read ep 請選擇您想要獲取ip的網絡卡名稱 wangka zw ifconfig grep n1 wangka grep inet awk ip if...
手機遊戲指令碼系統設計
因為要為公司開發乙個遊戲引擎的緣故,接觸到公司原來使用的指令碼系統。哇,不看不知道,發現原來指令碼系統可以這樣設計,呵呵,我的意思是貶義的,因為檢視源 之後,發現這個指令碼系統使用起來不僅速度慢,而且占用記憶體大。因為它是在執行態進行解釋操作,存在大量的字串操作,而且還了解到這個指令碼系統原來是乙個...