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