本文給出了一個(gè)對(duì)Microsoft
.NET
和Microsoft's
XML
Web服務(wù)平臺(tái)的總體介紹以及使用它們的好處。同時(shí)我們還將舉例說(shuō)明
.NET
是如何改變終端用戶和商業(yè)的計(jì)算模式。
??
?? 在本文中我們不想涉及到很精深的技術(shù),任何稍微懂一點(diǎn)電腦和Internet知識(shí)的人都可以理解本篇的內(nèi)容。Micorosoft還為那些希望掌握
.NET
的公司執(zhí)行官、IT領(lǐng)導(dǎo)和程序員們
??提供了更多的資源。
??
?? 什么是Microsoft
.NET
?
??
?? Microsoft
.NET
是Microsoft的
XML
Web服務(wù)平臺(tái)。
.NET
包含了建立和運(yùn)行基于
XML
的
軟件
所需要的全部部件。
??
?? Microsoft
.NET
解決了下面這些當(dāng)今
軟件
開(kāi)發(fā)中的一些核心問(wèn)題:
??
?? ●互操作性(Interoperability)、集成性(Integration)和應(yīng)用程序的可擴(kuò)展性(extensibility)太難實(shí)現(xiàn)而且代價(jià)很高。Microsoft
.NET
依靠
XML
(一個(gè)由World Wide Web Consortium(W3C)管理的開(kāi)放標(biāo)準(zhǔn))消除了數(shù)據(jù)共享和
軟件
集成的障礙。
??
?? ●無(wú)數(shù)具有相當(dāng)競(jìng)爭(zhēng)力的私有
軟件
技術(shù)使得
軟件
的集成變得非常復(fù)雜。而Microsoft
.NET
建立在一個(gè)開(kāi)放的標(biāo)準(zhǔn)上,它包含了所有
編程
語(yǔ)言。
??
?? ●當(dāng)終端用戶使用
軟件
時(shí),他們總覺(jué)得不夠簡(jiǎn)便。有時(shí)甚至感到很沮喪,因?yàn)樗麄儫o(wú)法在程序之間方便地共享數(shù)據(jù)或是無(wú)法對(duì)能訪問(wèn)的數(shù)據(jù)進(jìn)行操作。
XML
使數(shù)據(jù)交換變得容易了,并且
.NET
軟件
可以使得用戶只要一得到數(shù)據(jù)就能對(duì)它們進(jìn)行操作。
??
?? ●終端用戶們?cè)谑褂肳eb的時(shí)候,無(wú)法對(duì)自己的個(gè)人信息和數(shù)據(jù)進(jìn)行控制,這導(dǎo)致了個(gè)人隱私和安全泄漏問(wèn)題。而Microsoft
.NET
提供了一套服務(wù),使用戶可以管理他們的個(gè)人信息,并且控制對(duì)這些信息的訪問(wèn)。
??
?? ●.COM公司和Web站點(diǎn)開(kāi)發(fā)者們很難為用戶們提供足夠的有價(jià)值的數(shù)據(jù),至少有一部分原因是由于他們的應(yīng)用程序和服務(wù)無(wú)法很好地和其他程序和服務(wù)合作,只是一個(gè)不和外界連接的信息孤島。而Microsoft
.NET
的設(shè)計(jì)宗旨就是為了使來(lái)自于多個(gè)站點(diǎn)和公司的數(shù)據(jù)或服務(wù)能夠整合起來(lái)。
??
?? 如同MS-DOS和Windows一樣,
.NET
將大大改變我們的計(jì)算領(lǐng)域。MS-DOS使得個(gè)人電腦在商業(yè)和家庭中廣為接受;Windows增強(qiáng)了用戶的圖形界面,使其成為首選的與
軟件
交互方式,最終使得圖形界面成為個(gè)人電腦的主流。而
.NET
則要把
XML
Web服務(wù)變成日后的主流計(jì)算模式。
??
??
XML
Web服務(wù)是建立在
XML
數(shù)據(jù)交換基礎(chǔ)上的
軟件
模型,它幫助應(yīng)用程序、服務(wù)和設(shè)備一起工作。用
XML
進(jìn)行共享的數(shù)據(jù),彼此之間獨(dú)立,但同時(shí)又能夠松耦合地連接到一個(gè)執(zhí)行某特定任務(wù)的合作組。
??
?? 想了解
XML
Web服務(wù)如何工作,最方便的方法就是把它和拼裝
游戲
作比較。
XML
Web服務(wù)和拼裝
游戲
的拼塊一樣是一些獨(dú)立的單元。后者用一個(gè)標(biāo)準(zhǔn)的方法相互咬合在一起,
XML
Web服務(wù)與這類(lèi)似,但它是通過(guò)
XML
message實(shí)現(xiàn)相互交互的。當(dāng)你把拼塊拼在一起時(shí),你就得到了一個(gè)對(duì)象:一幢房子、一艘船或一架飛機(jī)。同樣,當(dāng)你把
XML
Web服務(wù)結(jié)合在一起時(shí),你就得到了一個(gè)完成某特定任務(wù)的
軟件
解決方案。同一拼塊可以用在很多不同對(duì)象中,而一個(gè)
XML
Web服務(wù)同樣也可以用在不同的方案組中,作為不同任務(wù)解決方案的一個(gè)組成部分。
??
??
XML
Web服務(wù)使開(kāi)發(fā)者能夠?qū)λ麄兯某绦虻膩?lái)源進(jìn)行選擇,可以自己創(chuàng)建或購(gòu)買(mǎi)程序的功能塊;同樣也可以選擇是讓自己的方案使用其他的
XML
Web服務(wù),還是讓其他的程序使用自己的服務(wù)。這意味著一個(gè)公司不必為了給客戶一個(gè)完整的解決方案而不得不提供方案的每一個(gè)組成部分。
??
??
XML
Web服務(wù)除了個(gè)服務(wù)相互之間獨(dú)立以外,對(duì)訪問(wèn)它們的設(shè)備而言也是獨(dú)立的。與獨(dú)立應(yīng)用程序不同的是,
XML
Web服務(wù)并沒(méi)有束縛于某一特定的
編程
語(yǔ)言或商業(yè)應(yīng)用程序或者是某一在線服務(wù)。這給了終端用戶足夠的自由,使其可以使用任何訪問(wèn)設(shè)備,從臺(tái)式電腦到移動(dòng)電話都可以。
??
??
.NET
戰(zhàn)略
??
?? Microsoft
.NET
程序員們?cè)O(shè)計(jì)編寫(xiě)的是
XML
Web服務(wù),而不是服務(wù)器或客戶端的獨(dú)立應(yīng)用程序。他們把這些服務(wù)組合成松耦合,相互協(xié)作的
軟件
群,
XML
Web服務(wù)之間使用
XML
messaging進(jìn)行通訊。為了做到這一點(diǎn),程序員需要:
??
?? 1.一個(gè)
軟件
平臺(tái),用于建立一種新的完整的個(gè)人用戶經(jīng)驗(yàn)。
??
?? 2.一個(gè)
編程
模型和工具,用以建立和整合
XML
Web服務(wù)。
??
?? 3.一套能為應(yīng)用程序和服務(wù)提供基礎(chǔ)的可
編程
的服務(wù)
??
?? Microsoft的
.NET
戰(zhàn)略就瞄準(zhǔn)了這三點(diǎn)。
??
??
.NET
包括:
??
?? ●
.NET
平臺(tái),這是一套
編程
工具和基本構(gòu)架,用來(lái)創(chuàng)建、發(fā)布、管理和整合
XML
Web服務(wù)
??
?? ●
.NET
體驗(yàn),這是終端用戶用以和
.NET
交互的手段
.NET
平臺(tái)
??
?? Microsoft的平臺(tái)是由用于創(chuàng)建和運(yùn)行
XML
Web服務(wù)組成的。它包含了下面四個(gè)組件:
??
??
.NET
框架和Visual Studio
.NET
:這些是開(kāi)發(fā)人員用來(lái)生成
XML
Web服務(wù)的工具。
.NET
框架是Microsoft
.NET
平臺(tái)核心中的一套
編程
接口;Visual Studio
.NET
是一套多語(yǔ)言系列的
??
編程
工具。
??
?? 服務(wù)器基本結(jié)構(gòu)(Server Infrastructure):
.NET
的服務(wù)器基本結(jié)構(gòu)是一系列用于生成、發(fā)布和操作
XML
Web服務(wù)的基礎(chǔ)程序,包括Windows和各種
.NET
企業(yè)服務(wù)器。主要的技術(shù)包括對(duì)
XML
、scale-out及跨程序和服務(wù)的商務(wù)流程(business process orchestration)的支持。這些服務(wù)器包括有:
??
?? ●Application Center 2000,用于scale-out solutions
??
?? ●BizTalk Server 2000,用于創(chuàng)建和管理基于
XML
的跨程序和服務(wù)的商務(wù)流程(business process orchestration across applications and services)
??
?? ●Host Integration Server 2000,用來(lái)訪問(wèn)主機(jī)上的數(shù)據(jù)和應(yīng)用程序
??
?? ●Mobile Information 2001 Server,使移動(dòng)設(shè)備,比如移動(dòng)電話,也能使用這些應(yīng)用程序
??
?? ●
SQL
Server
2000儲(chǔ)存和檢索結(jié)構(gòu)化的
XML數(shù)據(jù)
??
?? Building Block Services: Building Block Services是一套以用戶為中心的XML Web服務(wù),它把用戶數(shù)據(jù)的控制權(quán)從應(yīng)用程序移到了用戶手上,使Web有了一個(gè)翻天覆地的變化,做到了程序、服務(wù)和設(shè)備之間的簡(jiǎn)單性及一致性,這保證了所有的交易都必須得到用戶的同意。這些服務(wù)包含了Passport(用于用戶身份驗(yàn)證)、服務(wù)之間的消息傳遞、文件存儲(chǔ)、用戶個(gè)性設(shè)置的管理、日歷管理和其他一些功能。Microsoft將在那些對(duì).NET基本結(jié)構(gòu)起至關(guān)重要作用的領(lǐng)域內(nèi)提供一些塊構(gòu)建服務(wù)(building block services)。大量的合作伙伴和開(kāi)發(fā)商將對(duì)這些塊構(gòu)建服務(wù)作重要的擴(kuò)展。
??
?? 智能設(shè)備(smart device): .NET利用軟件使智能設(shè)備,諸如手提電腦、輕便電話、游戲操縱臺(tái)等都能夠在.NET世界中得以使用。
??
?? 一個(gè)智能設(shè)備應(yīng)該:
??
?? ●對(duì)用戶要智能:能根據(jù)用戶的.NET身份、檔案(profile)和有關(guān)數(shù)據(jù)簡(jiǎn)化用戶的工作;另外要對(duì)用戶的存在足夠的智能,能根據(jù)你的在與不在對(duì)通知(notification)作出調(diào)整。
??
?? ●對(duì)網(wǎng)絡(luò)要智能:負(fù)責(zé)帶寬的限制;支持應(yīng)用程序的在線和線下兩種使用模式;知道有哪些有效的服務(wù)。
??
?? ●對(duì)信息要智能:能在任何地方、任何時(shí)間訪問(wèn)、分析和操作數(shù)據(jù)。
??
?? ●對(duì)其他的設(shè)備要智能:能發(fā)現(xiàn)和報(bào)告其他智能設(shè)備、服務(wù)和Internet的存在;知道如何為其他設(shè)備提供服務(wù);能夠靈活方便地從PC上訪問(wèn)信息。
??
?? ●對(duì)軟件和服務(wù)要智能:能根據(jù)表單的情況,最恰當(dāng)?shù)乇憩F(xiàn)應(yīng)用和數(shù)據(jù);為終端用戶提供合適的輸入方法和連接;用XML、SOAP和UDDI來(lái)使用Web服務(wù);對(duì)開(kāi)發(fā)者來(lái)說(shuō),要具有可編程性和擴(kuò)展性
??
?? Microsoft的一些軟件使能夠在智能設(shè)備上運(yùn)行的,它們包括Windows XP、Windows Me、Windows CE、嵌入式Windows、.NET框架以及.NET Compact框架。
??
?? .NET體驗(yàn)(.NET experiences)
??
?? 終端用戶是通過(guò).NET體驗(yàn)訪問(wèn)XML Web服務(wù)的,這和現(xiàn)有的獨(dú)立應(yīng)用程序有點(diǎn)類(lèi)似,但在下列這些重要的方面是不同的:
??
?? ●.NET體驗(yàn)可使用于多種設(shè)備我們無(wú)需為可能使用的每一個(gè)設(shè)備編寫(xiě)一個(gè)不同XML Web服務(wù)和不同的.NET體驗(yàn),.NET體驗(yàn)?zāi)軌蜃x取用戶選取設(shè)備的特征,給出一個(gè)恰當(dāng)界面。
??
?? ●.NET體驗(yàn)使用XML Web服務(wù)當(dāng).NET體驗(yàn)連入網(wǎng)絡(luò)后就能有效地利用XML Web服務(wù)為用戶帶來(lái)額外的價(jià)值,以更好地解決問(wèn)題。
??
?? ●.NET體驗(yàn)是以用戶為中心的.NET體驗(yàn)的焦點(diǎn)在終端用戶,使用基于身份驗(yàn)證的塊構(gòu)建服務(wù)來(lái)為用戶驗(yàn)證、參數(shù)設(shè)定、通知機(jī)制和用戶數(shù)據(jù)提供服務(wù)。因?yàn)橛脩魯?shù)據(jù)是由塊構(gòu)建服務(wù)管理的,而不是應(yīng)用程序本身,所以用戶就能控制他們自己的數(shù)據(jù),能保障它的正確性,并且可以在不同的程序和服務(wù)之間協(xié)調(diào)數(shù)據(jù)。
??
?? Microsoft正在使最受歡迎的四個(gè)產(chǎn)品過(guò)渡到.NET體驗(yàn)。Microsoft Office XP為用戶提供.NET體驗(yàn)方面跨出了第一步。另外,MSN,包括MSN Explorer本地客戶端的使用,正在創(chuàng)建一個(gè)基于消費(fèi)者的.NET體驗(yàn)。Microsoft bCentral的小型商務(wù)入口(business portal)正努力為小型事務(wù)(比如商品目錄管理)提供必要的XML Web服務(wù),同時(shí)也使用一些重要的XML Web服務(wù)(比如eBay)。Visual Studio開(kāi)發(fā)系統(tǒng)將為開(kāi)發(fā)者們提供.NET體驗(yàn),可以在這些開(kāi)發(fā)工具中直接得到MSDN信息。
??
?? .NET的好處
??
?? Microsoft .NET為程序員、商業(yè)領(lǐng)導(dǎo)、IT部門(mén)以及消費(fèi)者帶來(lái)了很多好處。
??
?? ●相對(duì)來(lái)說(shuō),程序員是比較缺乏的,雇用的費(fèi)用也很高。然而Microsoft .NET使編程工作變得更加容易,開(kāi)發(fā)投資的回報(bào)率也趨最大化。開(kāi)發(fā)者們可以創(chuàng)建能重用的XML Web服務(wù),而不再是一個(gè)單一的程序;這些Web服務(wù)易于編程和調(diào)試,彼此之間相互獨(dú)立,通過(guò)XML message通訊及合作。所以對(duì)某一個(gè)服務(wù)的修改不會(huì)影響到其他的服務(wù)。
??
?? 由于XML Web服務(wù)可以被很多.NET體驗(yàn)共同使用,所以對(duì)一個(gè)服務(wù)模塊的有效更新,也即更新了所有使用這個(gè)模塊的.NET體驗(yàn)。任何編程語(yǔ)言都可以用來(lái)編寫(xiě)XML Web服務(wù)(如:C、C++、Visual Basic、COBOL、Perl、Python和Java等),所以你的程序員可以選擇他們最熟悉的語(yǔ)言來(lái)編程,這大大提高了開(kāi)發(fā)效率。更值得一體的是,他們并沒(méi)有因使用了不同的語(yǔ)言而失去跨服務(wù)或跨組件的調(diào)試能力。
??
?? ●Microsoft .NET減少了程序員要寫(xiě)的代碼量。一個(gè)XML Web服務(wù)能適用于所以的設(shè)備,不必再去為每一個(gè)設(shè)備編寫(xiě)一個(gè)不同的版本。另外,將顯示特性與.NET體驗(yàn)分開(kāi)以便以后加入新的接口技術(shù),比如語(yǔ)音或手寫(xiě)識(shí)別,而不必去重寫(xiě)程序。
??
?? ●Microsoft .NET開(kāi)創(chuàng)了全新的商業(yè)模型,它使得一個(gè)公司可以用多種方法來(lái)把自己的技術(shù)商品化。據(jù)個(gè)例子來(lái)說(shuō),一個(gè)通訊公司可以使用XML Web服務(wù)的方式提供語(yǔ)音信件和呼叫者ID的訪問(wèn),讓用戶從一個(gè)即時(shí)消息程序、電子郵件或用戶所選的其他信息編譯器中訪問(wèn)到上述信息。技術(shù)提供商可以把他們現(xiàn)有的軟件包轉(zhuǎn)變?yōu)?/font>XML Web服務(wù),并把這些服務(wù)出售給需要這些功能第三方,或是給.NET體驗(yàn)提供商,用以構(gòu)建新的軟件包。
●Microsoft .NET允許IT部門(mén)使用其他提供商的XML Web服務(wù),減少內(nèi)部研發(fā)的開(kāi)銷(xiāo),并能提高工作效率。
??
?? ●Microsoft .NET對(duì)"用戶界面友好"作了重新定義。終端用戶能夠徜徉于一個(gè)智能化的、個(gè)性化的Internet,它能記住用戶的個(gè)人設(shè)置,并在適當(dāng)?shù)臅r(shí)候,向用戶使用的智能設(shè)備上發(fā)送適當(dāng)?shù)臄?shù)據(jù)。
.NET如何改變計(jì)算 ?? ?? Microsoft .NET將從根本上改變我們的思考和使用電腦的方式。目前"服務(wù)器"和"桌面電腦"這兩種概念占據(jù)了計(jì)算領(lǐng)域的統(tǒng)治地位。然而Microsoft .NET是一種分布式計(jì)算范例,它沒(méi)有了傳統(tǒng)上的服務(wù)器和桌面電腦的區(qū)別,取而代之的是,計(jì)算的處理被放在最合適的地方進(jìn)行,可能是服務(wù) ??器,或是PC,也有可能是手提電腦以及其他智能設(shè)備。這就是智能計(jì)算。 ?? ?? .NET的計(jì)算模型對(duì)商務(wù)和終端用戶都產(chǎn)生了重要影響,但方法不同。對(duì)終端用戶來(lái)說(shuō),這個(gè)新計(jì)算模式更具個(gè)性化、綜合程度更高,會(huì)給他們帶來(lái)一種史無(wú)前例的新體驗(yàn)。對(duì)商務(wù)來(lái)說(shuō),這個(gè)模式改變了制造和銷(xiāo)售軟件的方法,使IT成為一個(gè)公司成功的重要貢獻(xiàn)者,并建立起新的商務(wù)模型。 ?? ?? 對(duì)終端用戶的改變 ?? ?? 這里有一個(gè)例子,說(shuō)明了.NET體驗(yàn)是如何對(duì)一個(gè)終端用戶產(chǎn)生影響的。 ?? ?? Bob,一個(gè)不安的商務(wù)旅行者,在芝加哥下了飛機(jī),突然想起他竟忘了帶上他的那部智能電話。這下完了,沒(méi)了這電話他無(wú)法知道晚宴在哪里進(jìn)行,無(wú)法知道原本打算在晚宴上見(jiàn)面的人的電話號(hào)碼,更慘的是,他無(wú)法在這個(gè)關(guān)鍵的會(huì)議之前再看一下重要的文件。但不用急,他從機(jī)場(chǎng)的租了一部智能電話,插入了自己的智能卡。很快通過(guò)內(nèi)置的Internet連接,各種相關(guān)的重要數(shù)據(jù)全部被下載了下來(lái),現(xiàn)在他能訪問(wèn)他的所有信息,不光是日程安排和電話簿,還有所有通常用他的PC機(jī)能訪問(wèn)到的所以文件。 ?? ?? 不幸的是,他在離開(kāi)機(jī)場(chǎng)時(shí)不小心在自動(dòng)扶梯上絆了一跤,腳踝嚴(yán)重扭傷,這個(gè)月這已經(jīng)是第二次了。無(wú)奈,他強(qiáng)忍疼痛要求電話接Roger醫(yī)生的辦公室,聽(tīng)電話的是接待員Mildred小姐。Bob通過(guò)電話確認(rèn)了自己的身份,他授權(quán)于Mildred小姐,讓她訪問(wèn)自己的所在位置和其他一些信息,以便使她可以在附近找一家整形外科診所。Mildred能夠知道哪家診所正在營(yíng)業(yè),有多遠(yuǎn),是否接受Bob的保險(xiǎn)。Bob所要做的就是輕按電話上的按鈕授權(quán)給她,Mildred在找到診所后便會(huì)和醫(yī)生約時(shí)間。 ?? ?? 與Mildred通話結(jié)束后,Bob用他的智能電話訪問(wèn)出租車(chē)服務(wù),查找離他最近的出租車(chē),并確認(rèn)目的地。接下來(lái)Bob只需爬進(jìn)車(chē)內(nèi),輕按電話的顯示屏確認(rèn)支付的費(fèi)用即可。 ?? ?? 從用戶角度來(lái)講,.NET提供的好處即超過(guò)了現(xiàn)在的獨(dú)立的程序,也勝過(guò)了純粹的Web站點(diǎn)。XML Web服務(wù)擁有傳統(tǒng)的軟件功能,如創(chuàng)建文檔、計(jì)算數(shù)字、存儲(chǔ)數(shù)據(jù)等。而且在下線后也能提供服務(wù),比如呼叫出租車(chē),這并不需要CPU的參與。 ?? ?? 從上面的例子我們可以看到,XML Web服務(wù)使終端用戶得到了更為個(gè)性化的、綜合性的體驗(yàn),同時(shí)便捷也是.NET給我們帶來(lái)的一大好處。 ?? ?? 對(duì)企業(yè)的改變 ?? ?? Bob那不走運(yùn)的商務(wù)旅行結(jié)束了,他蹣跚地回到了家(雖然那個(gè)晚宴非常成功,但現(xiàn)在他不得不面對(duì)六個(gè)星期的身體治療)。接下來(lái),Bob要提交費(fèi)用報(bào)告。他拿出了他的PDA,驗(yàn)明身份后,PDA列出了其信用卡上的支付紀(jì)錄。他標(biāo)出了與這次芝加哥之行有關(guān)的費(fèi)用,至于那些止痛藥和寄私人信件的費(fèi)用,他標(biāo)為個(gè)人開(kāi)銷(xiāo)。信用卡公司將為其生成必要的賬單。 ?? ?? 因?yàn)锽ob標(biāo)記了一些個(gè)人費(fèi)用,所以信用卡公司將根據(jù)他指定的方法為Bob生成一張個(gè)人帳單。在這個(gè)例子中,Bob使用的是直接從他銀行賬號(hào)中提錢(qián)的方法,但同時(shí)他也要一份藥費(fèi)開(kāi)支報(bào)告的硬拷貝。根據(jù)他的選擇,信用卡公司會(huì)Email發(fā)給他一個(gè)PDF文檔,Bob只需將它打印出來(lái)即可。 ?? ?? 對(duì)于那些業(yè)務(wù)上的開(kāi)支,信用卡公司會(huì)給Bob的公司發(fā)出一張電子帳單,它被送到公司的會(huì)計(jì)部門(mén),由公司會(huì)計(jì)Chris來(lái)處理。電子帳單到達(dá)時(shí),Chris會(huì)收到一封自動(dòng)生成的Email,隨后他登錄會(huì)計(jì)系統(tǒng)打開(kāi)這份帳單。他仔細(xì)檢查每一筆費(fèi)用,沒(méi)問(wèn)題后,他進(jìn)行支付,這也就是授權(quán)將一筆金從公司的賬戶轉(zhuǎn)移到信用卡公司的賬戶上。 ?? ?? 從企業(yè)角度講,.NET能夠自動(dòng)地處理很多任務(wù),節(jié)約了員工的大量時(shí)間。當(dāng)用XML將系統(tǒng)和XML Web服務(wù)連接起來(lái)后,數(shù)據(jù)交換變得非常方便,數(shù)據(jù)處理也變得輕而易舉。在這個(gè)例子中,員工Bob和Chris分別只要單擊一下"同意"和啟動(dòng)一個(gè)事務(wù)處理,無(wú)需花大量的時(shí)間去填寫(xiě)報(bào)銷(xiāo)單或是往會(huì)計(jì)系統(tǒng)中手工錄入數(shù)據(jù),一切都變得非常之簡(jiǎn)單。 ?? ?? 對(duì)企業(yè)和企業(yè)終端用戶來(lái)說(shuō),.NET預(yù)示這些從XML Web服務(wù)衍生出來(lái)的應(yīng)用程序有著很強(qiáng)的個(gè)性化和高度的整合性的特點(diǎn),同時(shí)它們適用于各種智能設(shè)備,具有相當(dāng)?shù)撵`活性。 ?? ?? 什么東西沒(méi)有變 ?? ?? 盡管Microsoft .NET給計(jì)算帶來(lái)了一些翻天覆地的變化,但還有很多東西依然沒(méi)有改變. ?? ?? ●終端用戶將依然使用熟悉的界面,就像.NET體驗(yàn)中的Microsoft Office一樣。這可以減少再培訓(xùn)的開(kāi)支,也意味著用戶可以馬上開(kāi)始使用.NET軟件。 ?? ?? ●硬件上運(yùn)行的還是象Windows、Unix、Windows CE和Palm OS一樣的操作系統(tǒng)。實(shí)際上,.NET增加了軟件的運(yùn)行場(chǎng)所,但同時(shí)減少了開(kāi)發(fā)的負(fù)擔(dān)。由于XML Web服務(wù)只使用XML與設(shè)備通信,所以任何智能設(shè)備都可以享用XML Web服務(wù)。 ?? ?? ●對(duì)程序員來(lái)說(shuō),他們依然可以使用他們?cè)仁煜さ?/font>編程語(yǔ)言。.NET平臺(tái)借助于.NET框架的公共語(yǔ)言運(yùn)行時(shí)間庫(kù)(CLR)使得用不同語(yǔ)言開(kāi)發(fā)的XML Web服務(wù)之間也可以相互操作。有沒(méi)有.NET體驗(yàn)問(wèn)題不大,你依舊可以用Visual Basic、Java、甚至是COBOL創(chuàng)建XML Web服務(wù)。這種對(duì)編程語(yǔ)言的中立性意味著不用為了進(jìn)入.NET世界而拋棄已有的投資。 ?? ?? ●原先系統(tǒng)無(wú)需被替換。一部分的Microsoft .NET產(chǎn)品就是為了能方便地將現(xiàn)有的系統(tǒng)整合到新,的XML Web服務(wù)和.NET體驗(yàn)中去而設(shè)計(jì)的。Host Integration Server就是個(gè)例子,它簡(jiǎn)化了對(duì)主機(jī)的訪問(wèn)。再比如就是BizTalk Server,它管理的商務(wù)流程(business process orchestration)包括了對(duì)現(xiàn)有系統(tǒng)和數(shù)據(jù)格式的支持,并會(huì)執(zhí)行一些必要的轉(zhuǎn)換,將數(shù)據(jù)轉(zhuǎn)成XML。 ?? ?? 所以這種下一代的分布式計(jì)算是建立在目前這一代基礎(chǔ)上的。Microsoft .NET不是我們所想象的那樣,對(duì)現(xiàn)在的應(yīng)用軟件作大規(guī)模的替換,而是一個(gè)自然的進(jìn)化過(guò)程,在原先的技術(shù)孤島之間建立了協(xié)作關(guān)系,協(xié)同工作能力逐漸加強(qiáng),我們也將從中受益無(wú)窮。 ?? ?? 總結(jié) ?? ?? Microsoft .NET是Microsoft的XML Web服務(wù)的平臺(tái)。這是下一代的Internet計(jì)算模型,各個(gè)XML Web服務(wù)之間彼此是松耦合的,通過(guò)XML進(jìn)行通訊,協(xié)同完成某一特定的任務(wù)。Microsoft .NET戰(zhàn)略提供了一個(gè)用以建立新.NET體驗(yàn)的軟件平臺(tái)、一個(gè)編程模型、用以建立和整合XML Web服務(wù)的工具以及一套可編程的Web接口。 ?? ?? 現(xiàn)在我們正處于向.NET轉(zhuǎn)變的過(guò)程中。Microsoft已經(jīng)宣布了.NET框架的第一個(gè)部分--.NET平臺(tái)、Visual Studio.NET和一些塊構(gòu)建服務(wù)以及最初的.NET體驗(yàn)。Microsoft在今年和明年中將會(huì)提供更多的工具和服務(wù)。 | [1]
|
|
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include <string.h>
功能:由src所指內(nèi)存區(qū)域復(fù)制count個(gè)字節(jié)到dest所指內(nèi)存區(qū)域。
說(shuō)明:src和dest所指內(nèi)存區(qū)域不能重疊,函數(shù)返回指向dest的指針。
舉例:
// memcpy.c
#include <syslib.h>
#include <string.h>
main()
{
char *s="Golden Global View";
char d[20];
clrscr();
memcpy(d,s,strlen(s));
d[strlen(s)]=0;
printf("%s",d);
getchar();
return 0;
}
原型:extern char *strchr(char *s,char c);
用法:#include <string.h>
功能:查找字符串s中首次出現(xiàn)字符c的位置
說(shuō)明:返回首次出現(xiàn)c的位置的指針,如果s中不存在c則返回NULL。
舉例:
// strchr.c
#include <syslib.h>
#include <string.h>
main()
{
char *s="Golden Global View";
char *p;
clrscr();
strchr(s,'V');
if(p)
printf("%s",p);
else
printf("Not Found!");
getchar();
return 0;
}
1 復(fù)制
?
char* strcpy (char *s1, const char *s2);
將字符串s2復(fù)制到s1指定的地址
?
char* strncpy (char *s1, const char *s2, size_t len);
void* ?memcpy (void *s1, const void *s2, size_t len);
將s2的前len個(gè)字符(字節(jié))復(fù)制到s1中指定的地址, 不加'\0'
?
void* memmove (void *s1, const void *s2, size_t len);
當(dāng)源單元和目的單元緩沖區(qū)交迭時(shí)使用
?
size_t strxfrm (char *s1, const char *s1, size_t len);
根據(jù)程序當(dāng)前的區(qū)域選項(xiàng), 將s2的前len個(gè)字符(字節(jié))復(fù)制到s1中指定的地址, 不加'\0'
?
2 連接
?
char* strcat (char *s1, const char *s2);
將字符串s2連接到s1尾部
?
char* strncat (char *s1, const char *s2, size_t len);
將字符串s2的前len個(gè)字符連接到s1尾部, 不加'\0'
?
3 比較
?
int strcmp (const char *s1, const char *s2);
比較字符串s1和s2
?
int strncmp (const char *s1, const char *s2, size_t len);
int ?memcmp (const void *s1, const void *s2, size_t len);
對(duì)s1和s2的前len個(gè)字符(字節(jié))作比較
?
int strcoll (const char *s1, const char *s2);
根據(jù)程序當(dāng)前的區(qū)域選項(xiàng)中的LC_COLLATE, 比較字符串s1和s2
?
4 查找
?
char* strchr (const char *s, int ch);
void* memchr (const void *s, int ch, size_t len);
在s中查找給定字符(字節(jié)值)ch第一次出現(xiàn)的位置
?
char* strrchr (const char *s, int ch);
在串s中查找給定字符ch最后一次出現(xiàn)的位置, r表示從串尾開(kāi)始
?
char* strstr (const char *s1, const char *s2);
在串s1中查找指定字符串s2第一次出現(xiàn)的位置
?
size_t strspn (const char *s1, const char *s2);
返回s1中第一個(gè)在s2中不存在的字符的索引(find_first_not_of)
?
size_t strcspn (const char *s1, const char *s2);
返回s1中第一個(gè)也在s2中存在的字符的索引(find_first_of)
?
char* strpbrk (const char *s1, const char *s2);
與strcspn類(lèi)似, 區(qū)別是返回指針而不是索引
?
char* strtok (char *s1, const char *s2);
從串s1中分離出由串s2中指定的分界符分隔開(kāi)的記號(hào)(token)
第一次調(diào)用時(shí)s1為需分割的字串, 此后每次調(diào)用都將s1置為NULL,
每次調(diào)用strtok返回一個(gè)記號(hào), 直到返回NULL為止
?
5 其他
?
size_t strlen (const char *s);
求字符串s的長(zhǎng)度
?
void* memset (void *s, int val, size_t len);
將從s開(kāi)始的len個(gè)字節(jié)置為val
?
char* strerror (int errno);
返回指向錯(cuò)誤信息字符串的指針
?
source: 《C & C++ Code Capsules》
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <string.h>
#i nclude <time.h>
//獲得prefix數(shù)組
int* GetPrefixValue(char* strPattern, int iPatternLen)
{
??? int i, j; /* i runs through the string, j counts the hits*/
??? int* prefix = (int*)malloc(iPatternLen*sizeof(int));
???
??? i = 1; j = 0;
??? prefix[0] = 0;
???
??? while(i<iPatternLen)
??? {
??????? if(strPattern[i] == strPattern[j])
??????? {
??????????? prefix[i] = ++j;
??????? }
??????? else
??????? {
??????????? j = 0;
??????????? prefix[i] = j;
??????? }
???????
??????? i++;
??? }
???
??? return prefix;??????????
}???
//返回target串在pattern串中第一次匹配的index
int KMPStringMatch(char* strPattern, int iPatternLen, char* strTarget, int iTargetLen, int* prefix)
{
??? int i = 0;
??? int j = 0;
???
??? while(i<iPatternLen && j<iTargetLen)
??? {
??????? if(j==0 || strPattern[i]==strTarget[j])
??????? {
??????????? i++;? j++;
??????? }
??????? else
??????? {
??????????? j = prefix[j];
??????? }
??? }????????????
???
??? free(prefix);
????
??? if(j==iTargetLen)
??? {
??????? return i-j;
??? }
??? else
??? {
??????? return -1;
??? }????????
}????????
int KMP(char* strPattern, char* strTarget)
{
??? int* prefix = GetPrefixValue(strPattern, strlen(strPattern));
??? int index = KMPStringMatch(strPattern, strlen(strPattern), strTarget, strlen(strTarget), prefix);
??? return index;
}
//在文本文件中查找target串出現(xiàn)的行數(shù)
int SearchInTxtFile(char* fileName, char* strTarget)
{
??? FILE* hFile = fopen(fileName, "r");
???
??? char str[1024];
??? int count = 0;
???
???
??? while(fgets(str, 1024, hFile))?
??? {
??????? if(KMP(str, strTarget)!=-1)
??????? {
??????????? count++;
??????? }???
??? }?????
???
??? fclose(hFile);
??? hFile=NULL;
???
??? return count;
}????
????????????
int main()
{
??? char ch;
??? char str1[] = "abcabcabctasksb,abTo";
??? char str2[] = "abc";
???
??? double t=clock();
??? printf("%d\n", KMP(str1,str2));
??? printf("耗時(shí):%f毫秒!\n", (clock()-t));
???
??? t=clock();
??? printf("find %d \n", SearchInTxtFile("c:\\txt.txt", "NULL"));
??? printf("耗時(shí):%f毫秒!\n", (clock()-t));
??? scanf("%c", &ch);
??? return 0;
}?
posted @
2006-07-05 23:48 Bourne 閱讀(4812) |
評(píng)論 (4) |
編輯 收藏
摘要:
本文從介紹基礎(chǔ)概念入手,探討了在C/C++中對(duì)日期和時(shí)間操作所用到的數(shù)據(jù)結(jié)構(gòu)和函數(shù),并對(duì)計(jì)時(shí)、時(shí)間的獲取、時(shí)間的計(jì)算和顯示格式等方面進(jìn)行了闡述。本文還通過(guò)大量的實(shí)例向你展示了time.h頭文件中聲明的各種函數(shù)和數(shù)據(jù)結(jié)構(gòu)的詳細(xì)使用方法。
關(guān)鍵字:UTC(世界標(biāo)準(zhǔn)時(shí)間),Calendar Time(日歷時(shí)間),epoch(時(shí)間點(diǎn)),clock tick(時(shí)鐘計(jì)時(shí)單元)
1.概念
在C/C++中,對(duì)字符串的操作有很多值得注意的問(wèn)題,同樣,C/C++對(duì)時(shí)間的操作也有許多值得大家注意的地方。最近,在技術(shù)群中有很多網(wǎng)友也多次問(wèn)到過(guò)C++語(yǔ)言中對(duì)時(shí)間的操作、獲取和顯示等等的問(wèn)題。下面,在這篇文章中,筆者將主要介紹在C/C++中時(shí)間和日期的使用方法.
通過(guò)學(xué)習(xí)許多C/C++庫(kù),你可以有很多操作、使用時(shí)間的方法。但在這之前你需要了解一些“時(shí)間”和“日期”的概念,主要有以下幾個(gè):
Coordinated Universal Time(UTC):協(xié)調(diào)世界時(shí),又稱為世界標(biāo)準(zhǔn)時(shí)間,也就是大家所熟知的格林威治標(biāo)準(zhǔn)時(shí)間(Greenwich Mean Time,GMT)。比如,中國(guó)內(nèi)地的時(shí)間與UTC的時(shí)差為+8,也就是UTC+8。美國(guó)是UTC-5。
Calendar Time:日歷時(shí)間,是用“從一個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)到此時(shí)的時(shí)間經(jīng)過(guò)的秒數(shù)”來(lái)表示的時(shí)間。這個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)對(duì)不同的編譯器來(lái)說(shuō)會(huì)有所不同,但對(duì)一個(gè)編譯系統(tǒng)來(lái)說(shuō),這個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)是不變的,該編譯系統(tǒng)中的時(shí)間對(duì)應(yīng)的日歷時(shí)間都通過(guò)該標(biāo)準(zhǔn)時(shí)間點(diǎn)來(lái)衡量,所以可以說(shuō)日歷時(shí)間是“相對(duì)時(shí)間”,但是無(wú)論你在哪一個(gè)時(shí)區(qū),在同一時(shí)刻對(duì)同一個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)來(lái)說(shuō),日歷時(shí)間都是一樣的。
epoch:時(shí)間點(diǎn)。時(shí)間點(diǎn)在標(biāo)準(zhǔn)C/C++中是一個(gè)整數(shù),它用此時(shí)的時(shí)間和標(biāo)準(zhǔn)時(shí)間點(diǎn)相差的秒數(shù)(即日歷時(shí)間)來(lái)表示。
clock tick:時(shí)鐘計(jì)時(shí)單元(而不把它叫做時(shí)鐘滴答次數(shù)),一個(gè)時(shí)鐘計(jì)時(shí)單元的時(shí)間長(zhǎng)短是由CPU控制的。一個(gè)clock tick不是CPU的一個(gè)時(shí)鐘周期,而是C/C++的一個(gè)基本計(jì)時(shí)單位。
我們可以使用ANSI標(biāo)準(zhǔn)庫(kù)中的time.h頭文件。這個(gè)頭文件中定義的時(shí)間和日期所使用的方法,無(wú)論是在結(jié)構(gòu)定義,還是命名,都具有明顯的C語(yǔ)言風(fēng)格。下面,我將說(shuō)明在C/C++中怎樣使用日期的時(shí)間功能。
2. 計(jì)時(shí)
C/C++中的計(jì)時(shí)函數(shù)是clock(),而與其相關(guān)的數(shù)據(jù)類(lèi)型是clock_t。在MSDN中,查得對(duì)clock函數(shù)定義如下:
clock_t clock( void );
這個(gè)函數(shù)返回從“開(kāi)啟這個(gè)程序進(jìn)程”到“程序中調(diào)用clock()函數(shù)”時(shí)之間的CPU時(shí)鐘計(jì)時(shí)單元(clock tick)數(shù),在MSDN中稱之為掛鐘時(shí)間(wal-clock)。其中clock_t是用來(lái)保存時(shí)間的數(shù)據(jù)類(lèi)型,在time.h文件中,我們可以找到對(duì)它的定義:
#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif
很明顯,clock_t是一個(gè)長(zhǎng)整形數(shù)。在time.h文件中,還定義了一個(gè)常量CLOCKS_PER_SEC,它用來(lái)表示一秒鐘會(huì)有多少個(gè)時(shí)鐘計(jì)時(shí)單元,其定義如下:
#define CLOCKS_PER_SEC ((clock_t)1000)
可以看到每過(guò)千分之一秒(1毫秒),調(diào)用clock()函數(shù)返回的值就加1。下面舉個(gè)例子,你可以使用公式clock()/CLOCKS_PER_SEC來(lái)計(jì)算一個(gè)進(jìn)程自身的運(yùn)行時(shí)間:
void elapsed_time()
{
printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);
}
當(dāng)然,你也可以用clock函數(shù)來(lái)計(jì)算你的機(jī)器運(yùn)行一個(gè)循環(huán)或者處理其它事件到底花了多少時(shí)間:
#include “stdio.h”
#include “stdlib.h”
#include “time.h”
int main( void )
{
???long????i = 10000000L;
???clock_t start, finish;
???double??duration;
???/* 測(cè)量一個(gè)事件持續(xù)的時(shí)間*/
???printf( "Time to do %ld empty loops is ", i );
???start = clock();
???while( i-- )??????;
???finish = clock();
???duration = (double)(finish - start) / CLOCKS_PER_SEC;
???printf( "%f seconds\n", duration );
???system("pause");
}
在筆者的機(jī)器上,運(yùn)行結(jié)果如下:
Time to do 10000000 empty loops is 0.03000 seconds
上面我們看到時(shí)鐘計(jì)時(shí)單元的長(zhǎng)度為1毫秒,那么計(jì)時(shí)的精度也為1毫秒,那么我們可不可以通過(guò)改變CLOCKS_PER_SEC的定義,通過(guò)把它定義的大一些,從而使計(jì)時(shí)精度更高呢?通過(guò)嘗試,你會(huì)發(fā)現(xiàn)這樣是不行的。在標(biāo)準(zhǔn)C/C++中,最小的計(jì)時(shí)單位是一毫秒。
3.與日期和時(shí)間相關(guān)的數(shù)據(jù)結(jié)構(gòu)
在標(biāo)準(zhǔn)C/C++中,我們可通過(guò)tm結(jié)構(gòu)來(lái)獲得日期和時(shí)間,tm結(jié)構(gòu)在time.h中的定義如下:
#ifndef _TM_DEFINED
struct tm {
????????int tm_sec;?????/* 秒 – 取值區(qū)間為[0,59] */
????????int tm_min;?????/* 分 - 取值區(qū)間為[0,59] */
????????int tm_hour;????/* 時(shí) - 取值區(qū)間為[0,23] */
????????int tm_mday;????/* 一個(gè)月中的日期 - 取值區(qū)間為[1,31] */
????????int tm_mon;?????/* 月份(從一月開(kāi)始,0代表一月) - 取值區(qū)間為[0,11] */
????????int tm_year;????/* 年份,其值等于實(shí)際年份減去1900 */
????????int tm_wday;????/* 星期 – 取值區(qū)間為[0,6],其中0代表星期天,1代表星期一,以此類(lèi)推 */
????????int tm_yday;????/* 從每年的1月1日開(kāi)始的天數(shù) – 取值區(qū)間為[0,365],其中0代表1月1日,1代表1月2日,以此類(lèi)推 */
????????int tm_isdst;???/* 夏令時(shí)標(biāo)識(shí)符,實(shí)行夏令時(shí)的時(shí)候,tm_isdst為正。不實(shí)行夏令時(shí)的進(jìn)候,tm_isdst為0;不了解情況時(shí),tm_isdst()為負(fù)。*/
????????};
#define _TM_DEFINED
#endif
ANSI C標(biāo)準(zhǔn)稱使用tm結(jié)構(gòu)的這種時(shí)間表示為分解時(shí)間(broken-down time)。
而日歷時(shí)間(Calendar Time)是通過(guò)time_t數(shù)據(jù)類(lèi)型來(lái)表示的,用time_t表示的時(shí)間(日歷時(shí)間)是從一個(gè)時(shí)間點(diǎn)(例如:1970年1月1日0時(shí)0分0秒)到此時(shí)的秒數(shù)。在time.h中,我們也可以看到time_t是一個(gè)長(zhǎng)整型數(shù):
#ifndef _TIME_T_DEFINED
typedef long time_t;?????????/* 時(shí)間值 */
#define _TIME_T_DEFINED??????/* 避免重復(fù)定義 time_t */
#endif
大家可能會(huì)產(chǎn)生疑問(wèn):既然time_t實(shí)際上是長(zhǎng)整型,到未來(lái)的某一天,從一個(gè)時(shí)間點(diǎn)(一般是1970年1月1日0時(shí)0分0秒)到那時(shí)的秒數(shù)(即日歷時(shí)間)超出了長(zhǎng)整形所能表示的數(shù)的范圍怎么辦?對(duì)time_t數(shù)據(jù)類(lèi)型的值來(lái)說(shuō),它所表示的時(shí)間不能晚于2038年1月18日19時(shí)14分07秒。為了能夠表示更久遠(yuǎn)的時(shí)間,一些編譯器廠商引入了64位甚至更長(zhǎng)的整形數(shù)來(lái)保存日歷時(shí)間。比如微軟在Visual C++中采用了__time64_t數(shù)據(jù)類(lèi)型來(lái)保存日歷時(shí)間,并通過(guò)_time64()函數(shù)來(lái)獲得日歷時(shí)間(而不是通過(guò)使用32位字的time()函數(shù)),這樣就可以通過(guò)該數(shù)據(jù)類(lèi)型保存3001年1月1日0時(shí)0分0秒(不包括該時(shí)間點(diǎn))之前的時(shí)間。
在time.h頭文件中,我們還可以看到一些函數(shù),它們都是以time_t為參數(shù)類(lèi)型或返回值類(lèi)型的函數(shù):
double difftime(time_t time1, time_t time0);
time_t mktime(struct tm * timeptr);
time_t time(time_t * timer);
char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);
此外,time.h還提供了兩種不同的函數(shù)將日歷時(shí)間(一個(gè)用time_t表示的整數(shù))轉(zhuǎn)換為我們平時(shí)看到的把年月日時(shí)分秒分開(kāi)顯示的時(shí)間格式tm:
struct tm * gmtime(const time_t *timer);??????????????????????????????????????????
struct tm * localtime(const time_t * timer);
通過(guò)查閱MSDN,我們可以知道Microsoft C/C++ 7.0中時(shí)間點(diǎn)的值(time_t對(duì)象的值)是從1899年12月31日0時(shí)0分0秒到該時(shí)間點(diǎn)所經(jīng)過(guò)的秒數(shù),而其它各種版本的Microsoft C/C++和所有不同版本的Visual C++都是計(jì)算的從1970年1月1日0時(shí)0分0秒到該時(shí)間點(diǎn)所經(jīng)過(guò)的秒數(shù)。
4.與日期和時(shí)間相關(guān)的函數(shù)及應(yīng)用
在本節(jié),我將向大家展示怎樣利用time.h中聲明的函數(shù)對(duì)時(shí)間進(jìn)行操作。這些操作包括取當(dāng)前時(shí)間、計(jì)算時(shí)間間隔、以不同的形式顯示時(shí)間等內(nèi)容。
4.1 獲得日歷時(shí)間
我們可以通過(guò)time()函數(shù)來(lái)獲得日歷時(shí)間(Calendar Time),其原型為:
time_t time(time_t * timer);
如果你已經(jīng)聲明了參數(shù)timer,你可以從參數(shù)timer返回現(xiàn)在的日歷時(shí)間,同時(shí)也可以通過(guò)返回值返回現(xiàn)在的日歷時(shí)間,即從一個(gè)時(shí)間點(diǎn)(例如:1970年1月1日0時(shí)0分0秒)到現(xiàn)在此時(shí)的秒數(shù)。如果參數(shù)為空(NUL),函數(shù)將只通過(guò)返回值返回現(xiàn)在的日歷時(shí)間,比如下面這個(gè)例子用來(lái)顯示當(dāng)前的日歷時(shí)間:
#include "time.h"
#include "stdio.h"
int main(void)
{
struct tm *ptr;
time_t lt;
lt =time(NUL);
printf("The Calendar Time now is %d\n",lt);
return 0;
}
運(yùn)行的結(jié)果與當(dāng)時(shí)的時(shí)間有關(guān),我當(dāng)時(shí)運(yùn)行的結(jié)果是:
The Calendar Time now is 1122707619
其中1122707619就是我運(yùn)行程序時(shí)的日歷時(shí)間。即從1970年1月1日0時(shí)0分0秒到此時(shí)的秒數(shù)。
4.2 獲得日期和時(shí)間
這里說(shuō)的日期和時(shí)間就是我們平時(shí)所說(shuō)的年、月、日、時(shí)、分、秒等信息。從第2節(jié)我們已經(jīng)知道這些信息都保存在一個(gè)名為tm的結(jié)構(gòu)體中,那么如何將一個(gè)日歷時(shí)間保存為一個(gè)tm結(jié)構(gòu)的對(duì)象呢?
其中可以使用的函數(shù)是gmtime()和localtime(),這兩個(gè)函數(shù)的原型為:
struct tm * gmtime(const time_t *timer);??????????????????????????????????????????
struct tm * localtime(const time_t * timer);
其中g(shù)mtime()函數(shù)是將日歷時(shí)間轉(zhuǎn)化為世界標(biāo)準(zhǔn)時(shí)間(即格林尼治時(shí)間),并返回一個(gè)tm結(jié)構(gòu)體來(lái)保存這個(gè)時(shí)間,而localtime()函數(shù)是將日歷時(shí)間轉(zhuǎn)化為本地時(shí)間。比如現(xiàn)在用gmtime()函數(shù)獲得的世界標(biāo)準(zhǔn)時(shí)間是2005年7月30日7點(diǎn)18分20秒,那么我用localtime()函數(shù)在中國(guó)地區(qū)獲得的本地時(shí)間會(huì)比世界標(biāo)準(zhǔn)時(shí)間晚8個(gè)小時(shí),即2005年7月30日15點(diǎn)18分20秒。下面是個(gè)例子:
#include "time.h"
#include "stdio.h"
int main(void)
{
struct tm *local;
time_t t;
t=time(NUL);
local=localtime(&t);
printf("Local hour is: %d\n",local->tm_hour);
local=gmtime(&t);
printf("UTC hour is: %d\n",local->tm_hour);
return 0;
}
運(yùn)行結(jié)果是:
Local hour is: 15
UTC hour is: 7
4.3 固定的時(shí)間格式
我們可以通過(guò)asctime()函數(shù)和ctime()函數(shù)將時(shí)間以固定的格式顯示出來(lái),兩者的返回值都是char*型的字符串。返回的時(shí)間格式為:
星期幾 月份 日期 時(shí):分:秒 年\n\0
例如:Wed Jan 02 02:03:55 1980\n\0
其中\(zhòng)n是一個(gè)換行符,\0是一個(gè)空字符,表示字符串結(jié)束。下面是兩個(gè)函數(shù)的原型:
char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);
其中asctime()函數(shù)是通過(guò)tm結(jié)構(gòu)來(lái)生成具有固定格式的保存時(shí)間信息的字符串,而ctime()是通過(guò)日歷時(shí)間來(lái)生成時(shí)間字符串。這樣的話,asctime()函數(shù)只是把tm結(jié)構(gòu)對(duì)象中的各個(gè)域填到時(shí)間字符串的相應(yīng)位置就行了,而ctime()函數(shù)需要先參照本地的時(shí)間設(shè)置,把日歷時(shí)間轉(zhuǎn)化為本地時(shí)間,然后再生成格式化后的字符串。在下面,如果t是一個(gè)非空的time_t變量的話,那么:
printf(ctime(&t));
等價(jià)于:
struct tm *ptr;
ptr=localtime(&t);
printf(asctime(ptr));
那么,下面這個(gè)程序的兩條printf語(yǔ)句輸出的結(jié)果就是不同的了(除非你將本地時(shí)區(qū)設(shè)為世界標(biāo)準(zhǔn)時(shí)間所在的時(shí)區(qū)):
#include "time.h"
#include "stdio.h"
int main(void)
{
struct tm *ptr;
time_t lt;
lt =time(NUL);
ptr=gmtime(<);
printf(asctime(ptr));
printf(ctime(<));
return 0;
}
運(yùn)行結(jié)果:
Sat Jul 30 08:43:03 2005
Sat Jul 30 16:43:03 2005
4.4 自定義時(shí)間格式
我們可以使用strftime()函數(shù)將時(shí)間格式化為我們想要的格式。它的原型如下:
size_t strftime(
???char *strDest,
???size_t maxsize,
???const char *format,
???const struct tm *timeptr
);
我們可以根據(jù)format指向字符串中格式命令把timeptr中保存的時(shí)間信息放在strDest指向的字符串中,最多向strDest中存放maxsize個(gè)字符。該函數(shù)返回向strDest指向的字符串中放置的字符數(shù)。
函數(shù)strftime()的操作有些類(lèi)似于sprintf():識(shí)別以百分號(hào)(%)開(kāi)始的格式命令集合,格式化輸出結(jié)果放在一個(gè)字符串中。格式化命令說(shuō)明串strDest中各種日期和時(shí)間信息的確切表示方法。格式串中的其他字符原樣放進(jìn)串中。格式命令列在下面,它們是區(qū)分大小寫(xiě)的。
%a 星期幾的簡(jiǎn)寫(xiě)
%A 星期幾的全稱
%b 月分的簡(jiǎn)寫(xiě)
%B 月份的全稱
%c 標(biāo)準(zhǔn)的日期的時(shí)間串
%C 年份的后兩位數(shù)字
%d 十進(jìn)制表示的每月的第幾天
%D 月/天/年
%e 在兩字符域中,十進(jìn)制表示的每月的第幾天
%F 年-月-日
%g 年份的后兩位數(shù)字,使用基于周的年
%G 年分,使用基于周的年
%h 簡(jiǎn)寫(xiě)的月份名
%H 24小時(shí)制的小時(shí)
%I 12小時(shí)制的小時(shí)
%j 十進(jìn)制表示的每年的第幾天
%m 十進(jìn)制表示的月份
%M 十時(shí)制表示的分鐘數(shù)
%n 新行符
%p 本地的AM或PM的等價(jià)顯示
%r 12小時(shí)的時(shí)間
%R 顯示小時(shí)和分鐘:hh:mm
%S 十進(jìn)制的秒數(shù)
%t 水平制表符
%T 顯示時(shí)分秒:hh:mm:ss
%u 每周的第幾天,星期一為第一天 (值從0到6,星期一為0)
%U 第年的第幾周,把星期日做為第一天(值從0到53)
%V 每年的第幾周,使用基于周的年
%w 十進(jìn)制表示的星期幾(值從0到6,星期天為0)
%W 每年的第幾周,把星期一做為第一天(值從0到53)
%x 標(biāo)準(zhǔn)的日期串
%X 標(biāo)準(zhǔn)的時(shí)間串
%y 不帶世紀(jì)的十進(jìn)制年份(值從0到99)
%Y 帶世紀(jì)部分的十進(jìn)制年份
%z,%Z 時(shí)區(qū)名稱,如果不能得到時(shí)區(qū)名稱則返回空字符。
%% 百分號(hào)
如果想顯示現(xiàn)在是幾點(diǎn)了,并以12小時(shí)制顯示,就象下面這段程序:
#include “time.h”
#include “stdio.h”
int main(void)
{
struct tm *ptr;
time_t lt;
char str[80];
lt=time(NUL);
ptr=localtime(<);
strftime(str,100,"It is now %I %p",ptr);
printf(str);
return 0;
}
其運(yùn)行結(jié)果為:
It is now 4PM
而下面的程序則顯示當(dāng)前的完整日期:
#include <stdio.h>
#include <time.h>
void main( void )
{
????????struct tm *newtime;
????????char tmpbuf[128];
????????time_t lt1;
????????time( <1 );
????????newtime=localtime(<1);
????????strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
????????printf(tmpbuf);
}
運(yùn)行結(jié)果:
Today is Saturday, day 30 of July in the year 2005.
4.5 計(jì)算持續(xù)時(shí)間的長(zhǎng)度
有時(shí)候在實(shí)際應(yīng)用中要計(jì)算一個(gè)事件持續(xù)的時(shí)間長(zhǎng)度,比如計(jì)算打字速度。在第1節(jié)計(jì)時(shí)部分中,我已經(jīng)用clock函數(shù)舉了一個(gè)例子。Clock()函數(shù)可以精確到毫秒級(jí)。同時(shí),我們也可以使用difftime()函數(shù),但它只能精確到秒。該函數(shù)的定義如下:
double difftime(time_t time1, time_t time0);
雖然該函數(shù)返回的以秒計(jì)算的時(shí)間間隔是double類(lèi)型的,但這并不說(shuō)明該時(shí)間具有同double一樣的精確度,這是由它的參數(shù)覺(jué)得的(time_t是以秒為單位計(jì)算的)。比如下面一段程序:
#include "time.h"
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
time_t start,end;
start = time(NUL);
system("pause");
end = time(NUL);
printf("The pause used %f seconds.\n",difftime(end,start));//<-
system("pause");
return 0;
}
運(yùn)行結(jié)果為:
請(qǐng)按任意鍵繼續(xù). . .
The pause used 2.000000 seconds.
請(qǐng)按任意鍵繼續(xù). . .
可以想像,暫停的時(shí)間并不那么巧是整整2秒鐘。其實(shí),你將上面程序的帶有“//<-”注釋的一行用下面的一行代碼替換:
printf("The pause used %f seconds.\n",end-start);
其運(yùn)行結(jié)果是一樣的。
4.6 分解時(shí)間轉(zhuǎn)化為日歷時(shí)間
這里說(shuō)的分解時(shí)間就是以年、月、日、時(shí)、分、秒等分量保存的時(shí)間結(jié)構(gòu),在C/C++中是tm結(jié)構(gòu)。我們可以使用mktime()函數(shù)將用tm結(jié)構(gòu)表示的時(shí)間轉(zhuǎn)化為日歷時(shí)間。其函數(shù)原型如下:
time_t mktime(struct tm * timeptr);
其返回值就是轉(zhuǎn)化后的日歷時(shí)間。這樣我們就可以先制定一個(gè)分解時(shí)間,然后對(duì)這個(gè)時(shí)間進(jìn)行操作了,下面的例子可以計(jì)算出1997年7月1日是星期幾:
#include "time.h"
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
struct tm t;
time_t t_of_day;
t.tm_year=1997-1900;
t.tm_mon=6;
t.tm_mday=1;
t.tm_hour=0;
t.tm_min=0;
t.tm_sec=1;
t.tm_isdst=0;
t_of_day=mktime(&t);
printf(ctime(&t_of_day));
return 0;
}
運(yùn)行結(jié)果:
Tue Jul 01 00:00:01 1997
現(xiàn)在注意了,有了mktime()函數(shù),是不是我們可以操作現(xiàn)在之前的任何時(shí)間呢?你可以通過(guò)這種辦法算出1945年8月15號(hào)是星期幾嗎?答案是否定的。因?yàn)檫@個(gè)時(shí)間在1970年1月1日之前,所以在大多數(shù)編譯器中,這樣的程序雖然可以編譯通過(guò),但運(yùn)行時(shí)會(huì)異常終止。
5.總結(jié)
本文介紹了標(biāo)準(zhǔn)C/C++中的有關(guān)日期和時(shí)間的概念,并通過(guò)各種實(shí)例講述了這些函數(shù)和數(shù)據(jù)結(jié)構(gòu)的使用方法。筆者認(rèn)為,和時(shí)間相關(guān)的一些概念是相當(dāng)重要的,理解這些概念是理解各種時(shí)間格式的轉(zhuǎn)換的基礎(chǔ),更是應(yīng)用這些函數(shù)和數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)。
參考文獻(xiàn)
[1] 標(biāo)準(zhǔn)C++程序設(shè)計(jì)教程,電子工業(yè)出版社,2003。
[2] MSDN Library, Microsoft Corporation,2003。
posted @
2006-07-05 12:12 Bourne 閱讀(3861) |
評(píng)論 (1) |
編輯 收藏
上網(wǎng)搜東西的時(shí)候搜到了這個(gè),覺(jué)得蠻使用的,放在這里以備后用!
--??LINK2001
學(xué)習(xí)VC++時(shí)經(jīng)常會(huì)遇到鏈接錯(cuò)誤LNK2001,該錯(cuò)誤非常討厭,因?yàn)閷?duì)于
編程者來(lái)說(shuō),最好改的錯(cuò)誤莫過(guò)于編譯錯(cuò)誤,而一般說(shuō)來(lái)發(fā)生連接錯(cuò)誤時(shí),
編譯都已通過(guò)。產(chǎn)生連接錯(cuò)誤的原因非常多,尤其LNK2001錯(cuò)誤,常常使人不
明其所以然。如果不深入地學(xué)習(xí)和理解VC++,要想改正連接錯(cuò)誤LNK2001非
常困難。
初學(xué)者在學(xué)習(xí)VC++的過(guò)程中,遇到的LNK2001錯(cuò)誤的錯(cuò)誤消息主要為:
unresolved external symbol “symbol”(不確定的外部“符號(hào)”)。
如果連接程序不能在所有的庫(kù)和目標(biāo)文件內(nèi)找到所引用的函數(shù)、變量或
標(biāo)簽,將產(chǎn)生此錯(cuò)誤消息。一般來(lái)說(shuō),發(fā)生錯(cuò)誤的原因有兩個(gè):一是所引用
的函數(shù)、變量不存在、拼寫(xiě)不正確或者使用錯(cuò)誤;其次可能使用了不同版本
的連接庫(kù)。
以下是可能產(chǎn)生LNK2001錯(cuò)誤的原因:
一.由于編碼錯(cuò)誤導(dǎo)致的LNK2001。
1.不相匹配的程序代碼或模塊定義(.DEF)文件能導(dǎo)致LNK2001。例如,
如果在C++ 源文件內(nèi)聲明了一變量“var1”,卻試圖在另一文件內(nèi)以變量
“VAR1”訪問(wèn)該變量,將發(fā)生該錯(cuò)誤。
2.如果使用的內(nèi)聯(lián)函數(shù)是在.CPP文件內(nèi)定義的,而不是在頭文件內(nèi)定
義將導(dǎo)致LNK2001錯(cuò)誤。
3.調(diào)用函數(shù)時(shí)如果所用的參數(shù)類(lèi)型同函數(shù)聲明時(shí)的類(lèi)型不符將會(huì)產(chǎn)生
LNK2001。
4.試圖從基類(lèi)的構(gòu)造函數(shù)或析構(gòu)函數(shù)中調(diào)用虛擬函數(shù)時(shí)將會(huì)導(dǎo)致LNK2001。
5.要注意函數(shù)和變量的可公用性,只有全局變量、函數(shù)是可公用的。
靜態(tài)函數(shù)和靜態(tài)變量具有相同的使用范圍限制。當(dāng)試圖從文件外部訪問(wèn)
任何沒(méi)有在該文件內(nèi)聲明的靜態(tài)變量時(shí)將導(dǎo)致編譯錯(cuò)誤或LNK2001。
函數(shù)內(nèi)聲明的變量(局部變量) 只能在該函數(shù)的范圍內(nèi)使用。
C++ 的全局常量只有靜態(tài)連接性能。這不同于C,如果試圖在C++的
多個(gè)文件內(nèi)使用全局變量也會(huì)產(chǎn)生LNK2001錯(cuò)誤。一種解決的方法是需要時(shí)在
頭文件中加入該常量的初始化代碼,并在.CPP文件中包含該頭文件;另一種
方法是使用時(shí)給該變量賦以常數(shù)。
二.由于編譯和鏈接的設(shè)置而造成的LNK2001
1.如果編譯時(shí)使用的是/NOD(/NODEFAULTLIB)選項(xiàng),程序所需要的運(yùn)行
庫(kù)和MFC庫(kù)在連接時(shí)由編譯器寫(xiě)入目標(biāo)文件模塊, 但除非在文件中明確包含
這些庫(kù)名,否則這些庫(kù)不會(huì)被鏈接進(jìn)工程文件。在這種情況下使用/NOD將導(dǎo)
致錯(cuò)誤LNK2001。
2.如果沒(méi)有為wWinMainCRTStartup設(shè)定程序入口,在使用Unicode和MFC
時(shí)將得到“unresolved external on _WinMain@16”的LNK2001錯(cuò)誤信息。
3.使用/MD選項(xiàng)編譯時(shí),既然所有的運(yùn)行庫(kù)都被保留在動(dòng)態(tài)鏈接庫(kù)之內(nèi),
源文件中對(duì)“func”的引用,在目標(biāo)文件里即對(duì)“__imp__func” 的引用。
如果試圖使用靜態(tài)庫(kù)LIBC.LIB或LIBCMT.LIB進(jìn)行連接,將在__imp__func上發(fā)
生LNK2001;如果不使用/MD選項(xiàng)編譯,在使用MSVCxx.LIB連接時(shí)也會(huì)發(fā)生LNK2001。
4.使用/ML選項(xiàng)編譯時(shí),如用LIBCMT.LIB鏈接會(huì)在_errno上發(fā)生LNK2001。
5.當(dāng)編譯調(diào)試版的應(yīng)用程序時(shí),如果采用發(fā)行版模態(tài)庫(kù)進(jìn)行連接也會(huì)產(chǎn)
生LNK2001;同樣,使用調(diào)試版模態(tài)庫(kù)連接發(fā)行版應(yīng)用程序時(shí)也會(huì)產(chǎn)生相同的
問(wèn)題。
6.不同版本的庫(kù)和編譯器的混合使用也能產(chǎn)生問(wèn)題,因?yàn)樾掳娴膸?kù)里可
能包含早先的版本沒(méi)有的符號(hào)和說(shuō)明。
7.在不同的模塊使用內(nèi)聯(lián)和非內(nèi)聯(lián)的編譯選項(xiàng)能夠?qū)е翷NK2001。如果
創(chuàng)建C++庫(kù)時(shí)打開(kāi)了函數(shù)內(nèi)聯(lián)(/Ob1或/Ob2),但是在描述該函數(shù)的相應(yīng)頭
文件里卻關(guān)閉了函數(shù)內(nèi)聯(lián)(沒(méi)有inline關(guān)鍵字),這時(shí)將得到該錯(cuò)誤信息。
為避免該問(wèn)題的發(fā)生,應(yīng)該在相應(yīng)的頭文件中用inline關(guān)鍵字標(biāo)志內(nèi)聯(lián)函數(shù)。
8.不正確的/SUBSYSTEM或/ENTRY設(shè)置也能導(dǎo)致LNK2001。
其實(shí),產(chǎn)生LNK2001的原因還有很多,以上的原因只是一部分而已,對(duì)初
學(xué)者來(lái)說(shuō)這些就夠理解一陣子了。但是,分析錯(cuò)誤原因的目的是為了避免錯(cuò)
誤的發(fā)生。LNK2001錯(cuò)誤雖然比較困難,但是只要注意到了上述問(wèn)題,還是能
夠避免和予以解決的。
posted @
2006-06-20 16:36 Bourne 閱讀(2492) |
評(píng)論 (2) |
編輯 收藏
還是我做的那個(gè)鏈表的模板類(lèi)
我分別寫(xiě)了頭文件Chain.h,源文件Chain.cpp,并且在main.cpp中進(jìn)行測(cè)試。
但是在連接的時(shí)候出現(xiàn)了問(wèn)題,不知道什么原因,希望能夠有高手指點(diǎn)一下,非常感謝!
其中Chain.h聲明了類(lèi)的數(shù)據(jù)成員和成員函數(shù),具體內(nèi)容如下:
#ifndef _CHAIN_H
#define _CHAIN_H
#include <iostream>
using namespace std;
template<class T>
class Chain;
template<class T>
class ChainNode
{
?friend class Chain<T>;
?friend ostream& operator<<(ostream& out, const Chain<T>& x);
private:
?T data;
?ChainNode<T> *link;
};
template<class T>
class Chain{
public:
?Chain(int p) {first = 0;};
?~Chain();
?bool IsEmpty() const {return first == 0;}
?int Length() const;
?bool Find(int k, T& x) const;
?int Search(const T& x) const;
?//Chain<T>& Delete(int k, T& x);
?Chain<T>& Insert(int k, const T& x);
?void Output(ostream& out = cout) const;
private:
?ChainNode<T> *first; // 指向第一個(gè)節(jié)點(diǎn)的指針
};
template<class T>
ostream& operator<<(ostream& out, const Chain<T>& x);
#endif? // _CHAIN
??在Chain.cpp中對(duì)Chain.h中聲明的函數(shù)進(jìn)行了定義,具體內(nèi)容如下:
#include "Chain.h"
#include <iostream>
using namespace std;
template<class T>
Chain<T>::~Chain()
{
?//鏈表的析構(gòu)函數(shù),用于刪除鏈表中的所有節(jié)點(diǎn)
?ChainNode<T> *ptr = first;
?while (ptr)
?{
??first = ptr->link;
??delete ptr;
??ptr = first;
?}
}
template<class T>
int Chain<T>::Length() const
{
?//返回鏈表中的元素總數(shù)
?int count = 0;
?ChainNode<T> *ptr = first;
?while (ptr)
?{
??++count;
??ptr = ptr->link;
?}
?return count;
}
template<class T>
bool Chain<T>::Find(int k, T& x) const
{
?//尋找鏈表中的第k個(gè)元素,并將其傳送至x
?//如果不存在第k個(gè)元素,則返回false,否則返回true
?if (k < 1)
?{
??return false;
?}
?int count = k;
?ChainNode<T> *ptr = first;
?while (count && ptr)
?{
??--count;
??ptr = ptr->link
?}
?if (!ptr)
?{
??return false;
?}
?x = ptr->data;
?return true;
}
template<class T>
int Chain<T>::Search(const T& x) const
{
?//尋找x,如果發(fā)現(xiàn)x,則返回x的地址
?//如果x不在鏈表中,則返回0
?int count = 1;
?ChainNode<T> *ptr = first;
?while(ptr && (ptr->data!=x))
?{
??++count;
??ptr = ptr->link;
?}
?if (ptr)
?{
??return count;
?}
?else
?{
??return 0;
?}
}
template<class T>
void Chain<T>::Output(ostream& out = cout) const
{
?ChainNode<T> *ptr = first;
?while (ptr)
?{
??out<<ptr->data<<"? ";
??ptr = ptr->link;
?}
}
//重載<<運(yùn)算符
template<class T>
ostream& operator<<(ostream& out, const Chain<T>& x)
{
?x.Output(out);
?return out;
}
template<class T>
Chain<T>& Chain<T>::Insert(int k, const T& x)
{
?ChainNode<T> *ptr = first;
?int count = 0;
?while (ptr && count < k)
?{
??++count;
??ptr = ptr->link;
?}
?if (!ptr)? //如果沒(méi)到第k個(gè)節(jié)點(diǎn)
?{
?
?}
?else
?{
??//要插入的新節(jié)點(diǎn)
??ChainNode<T>* cn = new ChainNode<T>;
??cn->data = x;
??cn->link = 0;
??if (ptr->link==0)? //到達(dá)了鏈表的結(jié)尾
??{
???ptr->link = cn;
??}
??else? //沒(méi)到達(dá)結(jié)尾
??{?
???cn->link = ptr->link;
???ptr->link = cn;
??}
?}
?return *this
}
?在main.cpp中進(jìn)行測(cè)試,測(cè)試的內(nèi)容很少,但是剛開(kāi)始就進(jìn)行不了了。main.cpp內(nèi)容如下:
#include "Chain.h"
using namespace std;
int main()
{
?Chain<int> c;
?cout<<c.Length();
?return 0;
}
編譯的時(shí)候沒(méi)有問(wèn)題,但是在連接的時(shí)候就出現(xiàn)了問(wèn)題,報(bào)錯(cuò)如下:
--------------------Configuration: Chain - Win32 Debug--------------------
Linking...
main.obj : error LNK2001: unresolved external symbol "public: __thiscall Chain<int>::~Chain<int>(void)" (??1?$Chain@H@@QAE@XZ)
main.obj : error LNK2001: unresolved external symbol "public: int __thiscall Chain<int>::Length(void)const " (?Length@?$Chain@H@@QBEHXZ)
Debug/Chain.exe : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.
Chain.exe - 3 error(s), 0 warning(s)
但是從報(bào)錯(cuò)信息來(lái)看,應(yīng)該是在main.cpp中沒(méi)有找到所用到的函數(shù) ~Chain<int>(void)和Length()的定義,在main.cpp中一共用到了三個(gè)函數(shù),構(gòu)造函數(shù)Chain(),但是構(gòu)造函數(shù)是在Chain.h中定義的,所以編譯器找到了其定義,但是另外兩個(gè)函數(shù)是在Chain.cpp中定義的,而且目前報(bào)錯(cuò)沒(méi)有找到,但是如果在main.cpp中引入#include "Chain.cpp"時(shí),編譯和連接就沒(méi)有問(wèn)題,這就證實(shí)了原來(lái)的估計(jì)是沒(méi)有錯(cuò)的。我實(shí)在是不知道問(wèn)題出現(xiàn)在哪里,所以希望哪位高手看出問(wèn)題來(lái)的話,請(qǐng)告訴我,多謝了!
以前寫(xiě)代碼的時(shí)候就遇到VC++對(duì)友元支持得不太好的問(wèn)題,同時(shí)也看過(guò)侯捷老師對(duì)gnu c++, VC++, BCB 三種編譯器的比較,其中VC++對(duì)模板友元的支持就不是很好。
今天晚上寫(xiě)了一個(gè)比較簡(jiǎn)單的鏈表的模板類(lèi),其中頭文件Chain.h原來(lái)的代碼如下:
#include <iostream>
using namespace std;
#ifndef _CHAIN
#define _CHAIN
template<class T>
class?ChainNode
{
?friend class Chain<T>;
private:
?T data;
?ChainNode<T> *link;
};
template<class T>
class Chain{
public:
?Chain()
?{
??first = 0;
?};
?~Chain();
?bool IsEmpty() const {return first == 0;}
?int Length() const;
?bool Find(int k, T& x) const;
?int Search(const T& x) const;
?//Chain<T>& Delete(int k, T& x);
?Chain<T>& Insert(int k, const T& x);
?void Output(ostream& out = cout) const;
private:
?ChainNode<T> *first; // 指向第一個(gè)節(jié)點(diǎn)的指針
};
#endif? // _CHAIN
結(jié)果報(bào)錯(cuò):
--------------------Configuration: Chain - Win32 Debug--------------------
Compiling...
Chain.cpp
g:\work plan\c++ code practice\chain\chain.h(17) : error C2059: syntax error : '<'
??????? g:\work plan\c++ code practice\chain\chain.h(21) : see reference to class template instantiation 'ChainNode<T>' being compiled
g:\work plan\c++ code practice\chain\chain.h(17) : error C2238: unexpected token(s) preceding ';'
??????? g:\work plan\c++ code practice\chain\chain.h(21) : see reference to class template instantiation 'ChainNode<T>' being compiled
g:\work plan\c++ code practice\chain\chain.h(40) : error C2989: 'Chain' : template class has already been defined as a non-template class
??????? g:\work plan\c++ code practice\chain\chain.h(17) : see declaration of 'Chain'
g:\work plan\c++ code practice\chain\chain.cpp(6) : error C2059: syntax error : '<'
g:\work plan\c++ code practice\chain\chain.cpp(6) : error C2588: '::~Chain' : illegal global destructor
g:\work plan\c++ code practice\chain\chain.cpp(6) : fatal error C1903: unable to recover from previous error(s); stopping compilation
Error executing cl.exe.
Chain.obj - 6 error(s), 0 warning(s)
感覺(jué)從代碼來(lái)看應(yīng)該是沒(méi)有問(wèn)題的,如果哪個(gè)高手看出問(wèn)題來(lái)了請(qǐng)一定告訴我啊,如果知道編譯不通過(guò)的原因也請(qǐng)一定要告訴我啊。沒(méi)辦法,最后采用解決的辦法就是修改ChainNode的定義了,定義為結(jié)構(gòu)體:)
template<class T>
struct ChainNode
{
? T data;
? ChainNode<T> *link;
};
反正結(jié)構(gòu)體中的數(shù)據(jù)成員都是public的,至于訪問(wèn)限制的實(shí)現(xiàn)就依靠迭代器來(lái)實(shí)現(xiàn)了,g++的STL中的樹(shù)結(jié)點(diǎn)不也是結(jié)構(gòu)體嗎?:)
posted @
2006-06-17 23:39 Bourne 閱讀(2673) |
評(píng)論 (4) |
編輯 收藏