|
2010年4月17日
偶然發現了盛大的maiku, 是一個不錯的日志和資源整理平臺。于是轉向了它,地址是 http://note.sdo.com/u/dongwq
歡迎來看看。
• 前者:看見與不看見,但是位置保留。
• 后者處理與位置有關:block, inline, none 分別是有前后換行,不換行,不顯示功能但是不保留位置。
• 二者功能差異:保留位置,和位置形式
<script language="javascript">
function toggleVisibility(me)
{
if(me.style.visibility=="hidden")
{
me.style.visibility="visible";
}
else
{
me.style.visibility="hidden";
}
}
</script>
<DIV onclick="toggleVisibility(this)"
style="position:relative">
第一行文本將會觸發"hidden"和"visible"屬性,注意第二行的變化。
</DIV>
<DIV>因為visibility會保留元素的位置,所以第二行不會移動.</DIV>
<script language="javascript">
function toggleDisplay(me){
if(me.style.display=="block"){
me.style.display="inline";
alert("文本現在是:'inline'.");
}
else{
if(me.style.display=="inline"){
me.style.display="none";
alert("文本現在是:'none'.3秒鐘后自動重新顯示。");
window.setTimeout("blueText.style.display='block';",
3000,"javascript");
}
else{
me.style.display="block";
alert("文本現在是:'block'.");
}
}
}
</script>
<DIV>在<span id="blueText"
onclick="toggleDisplay(this)"
style="color:blue;position:relative;cursor:hand;">
藍色</span>文字上點擊來查看效果.</DIV>
摘要: 1 . 日志的組成:配置文件,寫日志
log.cfg
############################################################
# Default Logging Configuration File
#
# You&nbs... 閱讀全文
文章分類:軟件開發管理
副標題——名不正言不順,項目管理難度加倍
你能想象美國總統上任,卻沒有總統就職儀式嗎?
你能想象北京奧林匹克運動會,沒有開幕式表演嗎??
OK。相信你一定見過這樣的場景:
某老板匆匆忙忙地進了屋,忽地來了一嗓子:“大家靜靜,通知大家一下:以后,某項目就由小張負責了!”
**************************************************
話說楚漢相爭。劉邦在蕭何的再三舉薦下,決定讓韓信為大將。
“來人,叫韓信過來,我要封他為大將。”劉邦道。
蕭何表示異議:“漢王你一向傲慢沒有禮貌,現在拜大將就和喊一個小孩子那么隨便,所以韓信才會離開的。漢王要想用人家,必須選一個吉日,吃素,設祭壇,用非常鄭重地禮節來拜將才行。”劉邦同意蕭何的意見。
結果,盡管韓信是個無名小卒,卻順利的接過了軍權,而沒有碰到那些元老們的抵抗,成功地導演了一幕幕戰爭奇跡。
**************************************************
登臺拜將,是一件具有深刻管理內涵的故事。它告訴我們這樣一個道理:
——內容是重要的,但形式卻是不容忽視。
我們不求老板非要在某個公開場合悠揚地宣告:“某項目成立了!!小張從此站起來了!!!”什么吉日,什么齋戒,什么禮儀。。。也就罷了。
但是,不給正式任命書;不在正式場合公布;甚至連一個頭銜都舍不得。這絕對是沒天理的。
**************************************************
“看,老板不重視這個項目。。。”(相關人員)
“瞧,老板不重視這個家伙。估計這個家伙沒有什么后臺” (相關人員)
“你負責某項目?我怎么不知道有這么個項目呢?你是哪位啊?” (相關人員)
“老板似乎并不重視/信任我啊” (項目經理)
***************************************************
以上種種,對項目的推動極為不利的。尤其是手下有資深員工、或者項目經理候補者等挑戰者的時候,問題將會加倍嚴重。
大家可能會懷疑:“沒有那么嚴重吧?”
沒有不嚴重,只有更嚴重!!
這其中蘊含著一個深刻的道理——名不正則言不順!!
言不順是什么意思呢?
-你的意見可能被忽視;
-你的命令可能被當作建議;
-你的計劃可能被別人忘記;
試想,你如果是項目經理,你的項目將會怎樣。。。。。。
*********************************************************
Question: 我沒有辦法叫老板改變。那么,我該怎么辦?
Answer:要寫一封郵件!!告訴別人你是誰。
*********************************************************
你的老板犯了錯誤,可是你不能將錯就錯!你的老板忽視了“名”的問題(形式問題),你一定要扳回來!!
試想,你的老板不重視,你也不重視,你能指望別人重視嗎??
當然,答案就是別人會更不重視!!
那么,這封郵件該怎么寫呢??
**************************************************
MailTo: 所有下屬
CC: 所有相關領導,所有相關人員,自己
Title: 【A項目】A項目的新項目經理小張向大家問好
Content:
1 開門見山地告訴別人自己的位置(正名)
2 向相關人員致敬,并自然地點出自己的優勢(自我介紹)
3 向領導致敬致謝(拉近和領導關系)
4 暗示自己的權利范圍(宣布自己的領地)
5 喊兩句口號(合作和積極的姿態是必要的)
6 不要忘了簽名(進一步加深印象)
//其中,1、2、4是必須要表現出來的
**************************************************
上面這封郵件,基本上完成了告訴別人你是誰的問題,而且完成了你的位置身份暗示。
如果說老板不負責任的任命形式帶給你身份位置認同危機,沉重打擊了你的威信的話,
通過這份郵件,你已經用身份暗示這個武器,奪回了主動權!!
從這封信以后,由于你的身份位置的明確,
相關人員在潛意識中會認同你的領地所有權,
會對在你的領地上和你發生沖突產生不自然,不合法甚至負罪感,
從而下意識中就會避免和你發生沖突。
反過來講,你的位置身份的明確,將成為你自信的源泉,
而這種位置感產生的自信將使你的發言充滿了正義感,
加上項目經理這個位置所帶來的小小的勢能。。。
權力這個東西,真好!!
嗯,一個好的開端,不是嗎?
1、函數定義和使用
<script>
function sqrt(x) {
return x * x;
}
function other(f) {
var y = f(10);
return y;
}
var farr = new Array();
farr[0] = function(arg) { return arg + arg;};
farr[1] = function(arg) { return arg * arg;};
document.write(farr[0](10) + '<br/>');
document.write(farr[1](10));
document.write(other(sqrt));
</script>
sqrt.count = 0;
sqrt.getcount = function() {
return this.count;
}; // 附加函式
//sqrt();
document.write(sqrt.count, '<br/>');
document.write(sqrt.getcount());
杜拉拉升級記:
關鍵一點,你的上級要喜歡你。工作中涉及要決策的都要跟上級報告。這是上級的作用。
對于平級的同事是不能用命令,不能要求別人做事的。
事情不能自己承擔下來。
感謝小熊同學借我這本書看
說說我的感受:此書沒有書評中說的那么好,當然也沒有那么壞。大家各取所需就好。與其叫小說,不如說是一種創新形式的職場教材。不要太去在意作者的文筆,而要更多的體會書中各位同學的處事之道。
幾句話總結一下:
1、勤奮是王道,其他的都屬于EQ范疇了
2、要注意技巧,尤其是溝通技巧,別干了半天,沒人知道你的工作量有多少。
3、掂量自己的能力,做好該做的事,不做不該做的事,比如越級匯報。
4、不要說人壞話,能幫助別人時要幫,關鍵時刻即使沒有人幫你說話,但也不會有人說你的壞話。不信的話,去看看圣經怎么說得吧。
5、要有氣量,做事要圓通。
6、要有自己的風格,風格沒有好壞之分,但是一定要有。
7、告訴我們什么是好工作,這點比較長,見下面的摘抄(感謝“木馬|造化弄人”的貢獻):
“一、關于什么樣的職位算好職位
1.你得找一家好公司
什么是好公司?
1)產品附加值高,生意好,并且從業務線看,具備持續發展的能力和前景;
2)有專業的/聰明能干的/經驗豐富的/并且為人現實的管理層,在把握這公司,并且有保護一貫這樣用人的制度的公司;
3)有嚴格的財務制度,對預算、費用和利潤等于投入產出有關的內容,敏感并且具有強控制力的公司;
4)崇尚客戶導向/市場導向/結果導向/執行力的公司;
5)有專業嚴謹全面的流程和制度,并且其執行有利于推動業務的良性發展,具有控制性和實操性兼備的特點;
---總結起來,就是一家具有持續贏利能力的牛B公司
2.你的找一個好的方向
什么是好的方向?
永遠不要遠離核心業務線。你得看明白,在企業中,哪個環節是實現利潤最大化的關鍵環節。有時候是銷售環節,有時候是市場策劃環節,有時候是研發環節,有時候是生產環節,視乎你所在行業而不同。
最重要的環節,總是 最貴的,最牛的,最得到重視的,也是最有發展前途的部門。它擁有最多的資源和最大的權威--你應該依附在這樣的核心業務線上發展,至少能避免被邊緣化,而成為關鍵人才的可能性則更大了。
3.你得跟一個好老板。
好老板的標準很多,關鍵的是,你要設法跟上一個在公司處于強勢地位的老板。他強,你才能跟著上。跟了一個弱勢的老板,你的前途就很同意被根著給耽擱了。
二、關于具備謀取好職位的資格
要具備怎么樣的資格呢?一般情況下,你得是用人部門眼中的優秀者。
怎么樣才算優秀呢?
1.對上級
1)你要知道與他建立一致性,他覺得重要的事情,你就覺得重要,他認為緊急的事情你也認為緊急,你得和他勁往一處使--通常情況下,你得表現和能力好還是不好,主要是你得直接主管說了算的;
2)你的具備從上級那里獲得支持和資源的能力--別你干的半死,你的老板還對你愛搭不理的,那你就不具備本條件的能力。
2.對下級
1)要能明確有效的設置正確的工作目標,使其符合SMART原則;
2)要能有效地管理團隊內部沖突;
3)要能公平合理地控制分配團隊資源;
4) 要有愿望和能力發展指導下屬,并恰當授權;
5)恰當的贊揚鼓勵認可團隊成員;
6)尊重不同想法,分享知識經驗和信息,建立信任的氛圍。
3.對內、外部客戶
1)愿意提供協助和增值服務(不然要你干嘛);
2)善意聆聽并了解需求(搞明白人家需要的到底是啥);
3)可靠的提供產品和服務,及時跟進(千萬注意及時);
4)了解組織架構并具影響力。及早地建立并維護關鍵的關系,是這樣的關系有利于你達成業績(專業而明智的選擇);
比如你想取得一個內部職位,你的搞明白了,誰是關鍵的做決定的人物,別傻乎乎不小心給這個人留下壞印象。
比如必要去客人那里拿訂單,你找了一個關鍵的人物A,可是你也別忽略作購買決定環節上的另一個人物B,沒準B和A是死敵,本來B會同意給你下訂單的,就因為A同意給你單子,B就是不同意給你單子。
4.對本崗任務
1)清楚自己的定位和職責--別搞不清楚自己是誰,什么是自己的活,知道什么該報告,什么要自己獨立做決定;
2)結果導向--設立高目標,信守承諾,承擔責任,注重質量、速度和期限,爭取主動,無需督促;
3)清晰的制定業務計劃并有效實施;
4)學習能力--愿意學,堅持學,及時了解行業趨勢/競爭狀況和技術更新,并學以致用;
5)承受壓力的能力--嚴峻的工作條件下,能堅忍不拔,想辦法獲取資源、支持和信息,努力以實現甚至超越目標;
6)適應的能力--如適應多項要求并存,優先級變換以及情況不明等工作條件,及時調整自己的行為和風格來適應不同個人及團隊的需要(工作重心會變化,老板會換人,客人也會變,別和他們說“我過去如何如何”,多去了解對方的風格) ”。
方與圓:
最少期望的去感謝別人。不要抱著目的去感謝別人,甚至事前感謝也好。感謝只需說一次。
發掘別人不明顯的優點加以贊揚。
贊揚行動和品性,而不要擴大到贊揚一個人。贊揚的原因要說明。
和氣生財嗎?喝杯水。
對陌生人要特別要笑。微笑是影響人氣質的一個特別重要的東西。
對生活的真誠,快樂的感情最能夠打動人。 男的微笑也很好。
認真的品質:畫一個月和十年。
組裝的質量差?認真的態度。德國人的認真,指路會指出的很具體的。
只有最認真的人才能做出最好的產品。
自動自發的精神,一定要發揮自己的主觀能動性。
當成自己的事來做吧。要主動的來做。
做好產品是人的一種尊嚴。爭強好勝在自己的工作上面。因為這是你的發揮場地。
只辦總裁班?成本與質量觀念不一樣的? 規模經濟?質量了的產品成本會降低。
檢查的目的是為了改進生活流程。
管制圖?
困定的供貨商?不是投標。是指定方式做。
永遠追求持續不斷的完善。
有必要再試一次。
改進自己的產品吧。
也淘汰了自己的競爭者。 一個系列的生產方式是不錯的。
到外去演講,不做化療?活過了三年?
要有自己的追求。活就要活出自己的價值。無論在何時的年齡,都要有自己的追求。
人生不是直線的,是C型的人生。
人生可以隨時開始。
<設計模式:java語言中的應用>摘要、總結 收藏
<設計模式:java語言中的應用>一書已經學完,現做個摘要、總結。
創建模式(Creational Patterns)
Abstract Factory Builder
Factory Method Prototype
Singleton
結構模式(Structural Patterns)
Adapter Bridge
Composite Decorator
Facade Flyweight
Proxy
行為模式(Behavioral Pattern)
Chain of Responsibility Command
Interpreter Iterator
Mediator Memento
Observer State
Strategy Template Method
Visitor
一、創建模式(Creational Patterns)
1.Abstract Factory(抽象工廠)—把相關零件組合成產品
Abstract Factory Pattern 是把各種抽象零件組合成抽象產品。換句話說,處理的重點是在接口(API)而不是零件的具體實現。只利用接口(API)就能把零件組合成產品.
程序示例:
--Main.java 測試用的類
|-factory
| |-------Factory.java 表示抽象工廠的類(產生Link,Tray,Page)
| |-------Itme.java 用來統一處理Link和Tray的類
| |-------Link.java 抽象零件:表示HTML連接的類
| |-------Tray.java 抽象零件:抽取Link和Tray的類
| |-------Page.java 抽象零件:表示HTML網頁的類
|
|-listfactory
|-------listFactory.java 表示具體工廠的類(產生ListLink,ListTray,ListPage)
|-------listLink.java 具體零件:表示HTML連接的類
|-------listTray.java 具體零件:抽取Link和Tray的類
|-------listPage.java 具體零件:表示HTML網頁的類
步驟:定義抽象零件->用抽象零件定義抽象工廠->定義具體零件(繼承實現抽象零件)->定義具體工廠(繼承實現抽象工廠,制造實際產品)
2.Factory Method
Factory Method Pattern 在父類規定對象的創建方法,但并沒有深入到較具體的類名.所有具體的完整內容都放在子類.根據這個原則,我們可以大致分成產生對象實例的大綱(框架)和實際產生對象實例的類兩方面.
程序示例:
--Main.java 測試用的類
|-framework
| |-------Product.java 僅定義抽象方法use的抽象類
| |-------Factory.java 規定createProduct,registerProduct,實現create的抽象類(類似模板方法)
|
|-idcard
|-------IDCard.java 實現方法use的具體類
|-------IDCardFactory.java 實現方法createProduct,registerProduct的類
步驟:定義抽象產品->根據抽象產品定義抽象工廠->定義具體產品(繼承實現抽象產品)->定義具體工廠(繼承實現抽象工廠,制造實際產品)
3.Singleton(單件)-唯一的對象實例
Singleton Pattern 是針對一個類而言. Singleton類只會產生1個對象實例.Singleton類把singleton定義為static字段(類變量),再以Singleton類的對象實例進行初始化.這個初始化的操作僅在加載Singleton類時進行一次.
Singleton類的構造函數是private的,主要是為了禁止從非Singleton類調用構造函數.即使下面這個表達式不在此類之內,編譯時仍然會出現錯誤.
程序示例:
|--Main.java 測試用的類
|--Singleton.java 只有1個對象實例的類
步驟:定義一個該類類型的static字段,同時實例化->該類的構造方法設為private->定義一個static的getInstance()方法,返回已經實例化的static字段.
4.Builder(生成器)-組合復雜的對象實例
Builder Pattern 是采用循序漸進的方式組合較復雜對象實例的.
程序示例:
|--Main.java 測試用的類
|--Builder.java 規定建立文件時的方法的抽象類
|--Director.java 產生1個文件的類
|--TextBuilder.java 產生plaintext格式(一般文本格式)的類
|--HTMLBuilder.java 產生HTML格式的類
步驟:定義建立文件時的通用方法(Builder.java)->根據通用方法組織建立文件(Director.java)->根據不同需求實現建立文件的通用方法(TextBuilder.java,HTMLBuilder.java)
5.Prototype(原型)-復制建立對象
Prototype Pattern 不是利用類產生對象實例,而是從一個對象實例產生出另一個新對象實例.
程序示例:
|--Main.java 測試用的類
|--MessageBox.java 把字符串框起來use的類.實現use和createClone
|--UnderlinePen.java 把字符串加上下劃線的類.實現use和createCone
|--framework
|-------Product.java 已聲明抽象方法use和createClone的接口
|-------Manager.java 利用createClone復制對象實例的類
步驟:規定可復制產品的接口(Product.java,繼承Cloneable接口)->保存可復制的產品(以Product類型存以哈西表中),并提供復制產品的方法create(調用產品的復制方法,復制工作在具體產品類中執行)(Manager.java)->定義可復制的具體產品(UnderlinePen.java,MessageBox.java,實現復制產品方法)
二、結構模式(Structural Patterns)
1.Adapter(適配器)-換個包裝再度利用
Adapter Pattern 把既有的無法直接利用的內容轉換成必要的類型后再使用.具有填平"既有內容"和"需要結果"兩者間"落差"的功能.
Adapter Pattern 有繼承和委托兩種形式.
程序示例:
|--Main.java 測試用的類
|--Banner.java 具有原始功能showWithParen,showWithAster的類
|--Print.java 所需新功能printWeak,printStrong的接口或抽象類
|--PrintBanner.java 把原始功能轉換成新功能的類
步驟:
(繼承)構造具有原始功能的類(Banner.java)->定義具有新功能的接口(Print.java)->轉換(PrintBanner.java,繼承Banner實現Print接口,即繼承舊方法實現新功能)
(委托)構造具有原始功能的類(Banner.java)->定義具有新功能的抽象類(Print.java)->轉換(PrintBanner.java,繼承具有新功能的Print類.定義委托對象,即原始功能類.構造時傳入原始功能實例對象,新功能的實現利用委托對象的原始功能.)
2.Bridge(橋接)-分成功能層次和實現層次
Bridge Pattern 溝通著"功能的類層次"和"實現的類層次"
功能的類層次:給父類增加不同的功能
實現的類層次:給父類以不同的實現
Bridge Pattern 本質上是通過功能類(最上層的功能類)中的一個實現類(最上層的實現類,一般是抽象類)字段來橋接兩個類層次的.
程序示例:
|--Main.java 測試用的類
|--Display.java 功能類層次的最上層類
|--CountDisplay.java 功能類層次的新增功能類
|--DisplayImpl.java 實現類層次的最上層類
|--StringDisplayImpl.java 實現類層次的實現類
步驟:定義實現類層次的最上層類(DisplayImpl.java)->定義功能類層次的最上層類(Display.java,使用Adapter Pattern的委托方式把DisplayImpl.java的原始功能轉換成Display.java的新功能)->定義功能類層次的新增功能類(CountDisplay.java)->定義實現類層次的實現類(StringDisplayImpl.java)
3.Composite(組成)-對容器和內容一視同仁
有時候把容器和內容當作是同類來處理會比較好下手。容器里面可以是內容,也可以是更小一號的容器;而這個小一號的容器里還可以再放更小一號的容器,可以建立出像這樣大套小的結構和遞歸結構的Pattern就是Composite Pattern
使用Composite Pattern,容器和內容必須有一定的共性.
程序示例:
|--Main.java 測試用的類
|--File.java 表示文件的類
|--Directory.java 表示目錄的類
|--Entry.java 對File和Directory一視同仁的抽象類
|--FileTreatmentException.java 欲在文件內新增Entry時所發生的異常類
步驟:定義異常類(FileTreatmentException.java)->定義進入點類,即將容器和內容一視同仁的抽象類(Entry.java,容器和內容都含有共同的方法)->定義容器類和內容類(File.java,Directory.java,繼承Entry,實現通用方法)
4.Decorator(裝飾)-對裝飾和內容一視同仁
先建立一個核心對象,再一層層加上裝飾用的功能,就可以完成符合所需的對象.可以看成是多個通用的適配器.
程序示例:
|--Main.java 測試用的類
|--Display.java 打印字符串用的抽象類
|--StringDisplay.java 只有1行的打印字符串用的類
|--Border.java 表示"裝飾外框"的抽象類
|--SideBorder.java 只在左右加上裝飾外框的類
|--FullBorder.java 在上下左右加上裝飾外框的類
步驟:定義核心對象的抽象類(Display.java)->定義核心對象類(StringDisplay.java)->定義裝飾類的抽象類(Border.java,繼承核心對象的抽象類Display.java,以便裝飾和內容一視同仁.裝飾類中繼承自核心對象抽象類的方法委托給傳入的核心對象)->定義其它裝飾類(SideBorder.java,FullBorder.java,繼承Border.java)
5.Facade(外觀)-單一窗口
Facade Pattern 能整理錯綜復雜的來龍去脈,提供較高級的接口(API).Facade參與者讓系統外部看到較簡單的接口(API).而且Facade參與者還會兼顧系統內部各類功能和互動關系,以最正確的順序利用類.
Facade Pattern 把業務邏輯封裝起來,只提供一個簡單的接口給外部調用.
程序示例:
|--Main.java 測試用的類
|--maildata.txt 郵件列表文件
|--pagemaker
|-------Database.java 從郵件信箱取得用戶名稱的類
|-------HtmlWriter.java 產生HTML文件的類
|-------PageMaker.java 根據郵件信箱產生用戶網頁的類
步驟:定義業務邏輯需要的相關類(Database.java,HtmlWriter.java)->定義外部接口類(PageMaker.java)
6.Flyweight(享元)-有相同的部分就共享,采用精簡政策
"盡量共享對象實例,不做無謂的new".不是一需要對象實例就馬上new,如果可以利用其他現有的對象實例,就讓它們共享.這就是Flyweigth Pattern的核心概念.
Flyweight Pattern 實質是把創建的占用內存量大的對象存儲起來(一般用hashtable存儲),后續使用時,再從hashtable取出.
程序示例:
|--Main.java 測試用的類
|--BigChar.java 表示"大型字符"的類
|--BigCharFactory.java 共享并產生BigChar的對象實例的類
|--BigString.java 表示多個BigChar所產生的"大型文本"的類
步驟:定義占用內存量大,需要共享的類(Display.java)->定義共享實例的類(BigCharFactory.java,共享處理在此進行,將產生的共享對象存儲在哈希表中,第二次使用時從表中取出即可,不需要new)->定義共享對象組合使用類(BigString.java)
7.Proxy(代理)-需要再建立
代理就是那個代替本來應該自己動手做事的本人的人.
由于代理純粹只是代理工作而已,因此能力范圍也有限.如果遇到超出代理能力所及的范圍,代理就應該去找本人商量才對.
程序示例:
|--Main.java 測試用的類
|--Printer.java 表示命名的打印機的類(本人)
|--Printable.java Printer和PrinterProxy共享的接口
|--PrinterProxy.java 表示命名的打印機的類(代理)
步驟:定義本人和代理都能處理的問題的接口(Printable.java)->建立本人類(Printer.java,實現Printable.java接口)->建立代理類(PrinterProxy.java,定義本人字段,把代理無法處理的問題交給本人)
三、行為模式(Behavioral Pattern)
1.Chain of Responsibility(職責鏈)-責任轉送
先對人產生一個要求,如果這個人有處理的能力就處理掉;如果不能處理的話,就把要求轉送給"第二個人".同樣的,如果第二個人有處理的能力時就處理掉,不能處理的話,就繼續轉送給"第三個人",依此類推.這就是Chain of Responsiblility Pattern.
Chain of Responsibility Pattern 的關鍵在于定義轉送字段(next)和定義職責鏈.
程序示例:
|--Main.java 建立Support的連鎖,產生問題的測試用類
|--Trouble.java 表示發生問題的類.內有問題編號.
|--Support.java 解決問題的抽象類.內有轉送字段和處理方法.
|--NoSupport.java 解決問題的具體類(永遠"不處理")
|--LimitSupport.java 解決問題的具體類(解決小于指定號碼的問題)
|--OddSupport.java 解決問題的具體類(解決奇數號碼的問題)
|--SpecialSupport.java 解決問題的具體類(解決特殊號碼的問題)
步驟:建立問題類(Trouble.java)->建立解決問題的抽象類(Support.java,定義了轉送字段next,設置轉送字段的方法setNext和處理問題的方法support)->建立解決問題的具體類(NoSupport.java,LimitSupport.java,OddSupport.java,SpecialSupport.java,繼承Support.java)->產生處理問題的對象,建立職責鏈
2.Command(命令)-將命令寫成類
用一個"表示命令的類的對象實例"來代表欲執行的操作,而不需采用"調用方法"的類的動態處理.如欲管理相關紀錄,只需管理該對象實例的集合即可.而若預先將命令的集合存儲起來,還可再執行同一命令;或者是把多個命令結合成一個新命令供再利用.
Command Pattern 重點在于存儲/使用命令
程序示例:
--Main.java 測試用的類
|-command
| |-------Command.java 表示"命令"的接口
| |-------MacroCommand.java 表示"結合多個命名的命令"的類
|
|-drawer
|-------DrawCommand.java 表示"點的繪制命令"的類
|-------Drawable.java 表示"繪制對象"的接口
|-------DrawCanvas.java 表示"繪制對象"的類
步驟:建立命令接口(Command.java)->建立命令結合類(MacroCommand.java,將各個命令存儲到一個Stack類型的字段)->建立繪制命令類(DrawCommand.java,定義繪制對象字段drawable,實現命令接口)->建立繪制對象接口(Drawable.java)->建立繪制對象類(DrawCanvas.java,實現繪制對象接口,定義命令集合字段history)->測試
3.Interpreter(解釋器)-以類來表達語法規則
Interpreter Pattern 是用簡單的"迷你語言"來表現程序要解決的問題,以迷你語言寫成"迷你程序"而表現具體的問題.迷你程序本身無法獨自啟動,必須先用java語言另外寫一個負責"解釋(interpreter)"的程序.解釋程序能分析迷你語言,并解釋\執行迷你程序.這個解釋程序也稱為解釋器.當應解決的問題發生變化時,要修改迷你程序來對應處理.而不是修改用java語言寫成的程序.
迷你語言語法:
<program>::=program<command list>
<command list>::=<command>* end
<command>::=<repeat command>|<primitive command>
<repeat command>::=repeat<number><command list>
<primitive command>::=go|right|left
程序示例:
|--Main.java 測試用的類
|--Node.java 樹狀剖析中"節點"的類
|--ProgramNode.java 對應<program>的類
|--CommandListNode.java 對應<command list>的類
|--CommandNode.java 對應<command>的類
|--RepeatCommandNode.java 對應<repeat command>的類
|--PrimitiveCommandNode.java 對應<primitive command>的類
|--Context.java 表示語法解析之前后關系的類
|--ParseException.java 語法解析中的例外類
步驟:確定迷你語言的語法->建立語法解析類(Context.java,使用java.util.StringTokenizer類)->建立解析異常類(ParseException.java)->建立語法節點抽象類(Node.java,定義parse解析方法)->建立各語法節點對應的語法類(ProgramNode.java,CommandListNode.java,CommandNode.java,RepeatCommandNode.java,PrimitiveCommand.java,繼承語法節點Node.java類)
4.Iterator-迭代器
Iterator Pattern 是指依序遍歷并處理多個數字或變量.
程序示例:
|--Main.java 測試用的類
|--Aggregate.java 表示已聚合的類
|--Iterator.java 執行遞增\遍歷的接口
|--Book.java 表示書籍的類
|--BookShelf.java 表示書架的類
|--BookShelfIterator.java 掃描書架的類
步驟:定義聚合接口(Aggregate.java)->定義遍歷接口(Iterator.java)->建立具體的遍歷對象類(Book.java)->建立具體的聚合類(BookShelf.java,實現聚合接口)->建立具體的遍歷類(BookShelfIterator.java,實現遍歷接口)
5.Mediator(中介者)-只要面對一個顧問
每個成員都只對顧問提出報告,也只有顧問會發出指示給各個成員;成員們彼此也不會去探問目前狀況如何,或亂發指示給其他成員.
程序示例:
|--Main.java 測試用的類
|--Mediator.java 決定"顧問"接口(API)的接口
|--Colleague.java 決定"成員"接口(API)的接口
|--ColleagueButton.java 實現Colleagues接口.表示按鍵的類
|--ColleagueTextField.java 實現Colleagues接口.輸入文本的類
|--ColleagueCheckbox.java 實現Colleagues接口.表示選擇項目(在此為選擇按鈕)的類
|--LoginFrame.java 實現Mediator接口.表示登錄對話框的類
步驟:定義顧問接口(Mediator.java)->定義成員接口(Colleague.java)->建立具體的成員類(ColleagueButton.java,ColleagueTextField.java,ColleagueCheckbox.java,實現成員接口)->建立具體的顧問類(LoginFrame.java,實現顧問接口)
6.Memento(備忘錄)-存儲狀態
Memento Pattern 會把某個時間點的對象實例狀態記錄存儲起來,等到以后再讓對象實例復原到當時的狀態.
程序示例:
|--Main.java 進行游戲的類.先把Memento的對象實例存儲起來,如有必要時再復原Gamer的狀態
|--game
|-------Gamer.java 玩游戲的主人翁的類
|-------Memento.java 表示Gamer狀態的類.產生Memento的對象實例
步驟:建立需要存儲狀態的類(Gamer.java)->建立狀態類(Memento.java,狀態類與需要存儲狀態的類Gamer.java應具有相同的必要字段)
7.Observer(觀察者)-通知狀態變化
當被Observer Pattern 列入觀察名單的狀態發生變化,就會通知觀察者.在寫一些跟狀態變化有關的處理時,Observer Pattern是很好用的工具.
程序示例:
|--Main.java 測試用的類
|--Observer.java 表示觀察者的接口
|--NumberGenerator.java 表示產生數值對象的抽象類
|--RandomNumberGenerator.java 產生隨機數的類
|--DigitObserver.java 以數字表示數值的類
|--GraphObserver.java 以簡易長條圖表示數值的類
步驟:定義觀察者接口(Observer.java)->建立被觀察的類(NumberGenerator.java,RandomNumberGenerator.java,定義觀察者結合字段將觀察者存儲起來)->建立具體的觀察者類(DigitObserver.java,GraphObserver.java,實現觀察者接口)
8.State(狀態)-以類表示狀態
以類來表示狀態之后,只要切換類就能表現“狀態變化”,而且在必須新增其他狀態時,也很清楚該編寫哪個部分。
程序示例:
|--Main.java 測試用的類
|--State.java 表示金庫狀態的接口
|--DayState.java 實現State的類。表示白天的狀態
|--NightState.java 實現State的類。表示夜間的狀態
|--Context.java 管理金庫的狀態變化,跟保安中心聯絡的接口
|--SafeFrame.java 實現Context的類。含有按鈕、畫面顯示等的用戶接口
步驟:定義狀態接口(State.java,將使用State Pattern之前各種行為方法抽象出來)->建立具體的狀態類(DayState.java,NightState.java,實現狀態接口,狀態變化的具體動作在這里執行)->定義管理狀態變化的接口(Context.java,規定狀態變化及相關的調用方法)->建立狀態管理類(SafeFrame.java,實現狀態管理接口)
9.Strategy(策略)-把算法整個換掉
在Strategy Pattern之下,可以更換實現算法的部分而且不留痕跡。切換整個算法,簡化改為采用其他方法來解決同樣的問題。
程序示例:
|--Main.java 測試用的類
|--Hand.java 表示猜拳“手勢”的類
|--Strategy.java 表示猜拳“戰略”的接口
|--WinningStrategy.java 表示猜贏之后繼續出同樣招式的戰略的類
|--ProbStrategy.java 表示從上一次出的招式,以概率分配方式求出下一個招式機率的類
|--Player.java 表示玩猜拳的游戲者的類
步驟:定義策略接口(Strategy.java)->建立具體的策略類(WinningStrategy.java,ProbStrategy.java,實現策略接口)->建立使用策略的類(Player.java,定義策略字段,以便使用切換策略)->建立其它類(Main.java,Hand.java)
10.Template Method(模板方法)-實際處理交給子類
在父類指定處理大綱、在子類規定具體內容的Design Pattern就稱為Template Method Pattern
程序示例:
|--Main.java 測試用的類
|--AbstractDisplay.java 只實現方法display的抽象類
|--CharDisplay.java 實現方法open,print,close的類
|--StringDisplay.java 實現方法open,print,close的類
步驟:定義模板類(AbstractDisplay.java,實現dispaly方法,即制作了模板)->建立具體內容類(CharDisplay.java,StringDisplay.java,繼承模板類,實現模板類沒有實現的方法)
11.Visitor(訪問者)-在結構中穿梭還同時做事
Visitor Pattern 把數據結構和處理兩者分開,另外寫一個表示在數據結構內穿梭來去的主體“訪客”的類,然后把處理交給這個類來進行。如此一來,如果想追加新的處理行為時,只要再建立一個新的“訪客”即可。而在數據結構這邊,也只要能接受來敲門的“訪客”就能完成動作。
在父類指定處理大綱、在子類規定具體內容的Design Pattern就稱為Template Method Pattern
程序示例:
|--Main.java 測試用的類
|--Visitor.java 表示訪問文件或目錄的訪客的抽象類
|--Acceptor.java 表示接受Visitor類的對象實例的數據結構的接口
|--ListVisitor.java Visitor類的子類,打印文件和目錄信息的類
|--Entry.java File和Directory的父類的抽象類(實現Acceptor接口)
|--File.java 表示文件的類
|--Directory.java 表示目錄的類
|--FileTreatmentException.java 發生在對File進行add時的例外類
步驟:定義訪問者的抽象類(Visitor.java,定義訪問方法)->定義受訪者接口(Acceptor.java,定義接受訪問的方法)->建立具體的訪問者類(ListVisitor.java,繼承訪問者抽象類,實現訪問方法)->建立具體的受訪者類(Entry.java,File.java,Directory.java,實現受訪者接口)->編寫異常類(FileTreatmentException.java)
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/pian_yun/archive/2007/09/14/1784981.aspx
直接在html中使用xml導入數據
<xml id="cdcat" src="cd_catalog.xml"></xml>
<table border="1" datasrc ="#cdcat">
<tr>
<td><span datafld="ARTIST"></span></td>
<td><span datafld="TITLE"></span></td>
<td datafld="price"> </td>
<td><span datafld="year"></span></td>
</tr>
</table>
注意可以引入xml字段的元素有 限:
例如,與DIV元素綁定的代碼如下:
d: U) f1 y
注意:并非所有的HTML元素都能與XML數據島綁定。目前,支持這種DSO綁定機制的元素如下:. H2 V- _% j! E/ {4 i
$ \( \$ l" b+ H( M& Y
A、APPLET、BUTTON、DIV、FRAME、IFRAME、 IMG、INPUT (此處類型是:CHECKBOX、HIDDEN、 LABEL、PASSWORD、RADIO和TEXT)、LABEL、 MARQUEE、SELECT、SPAN、TABLE和 TEXTAREA。
H.264中的NAL技術
NAL技術
1.NAL概述
NAL全稱Network Abstract Layer, 即網絡抽象層。
在H.264/AVC視頻編碼標準中,整個系統框架被分為了兩個層面:視頻編碼層面(VCL)和網絡抽象層面(NAL)。其中,前者負責有效表示視頻數據的內容,而后者則負責格式化數據并提供頭信息,以保證數據適合各種信道和存儲介質上的傳輸。
現實中的傳輸系統是多樣化的,其可靠性,服務質量,封裝方式等特征各不相同,NAL這一概念的提出提供了一個視頻編碼器和傳輸系統的友好接口,使得編碼后的視頻數據能夠有效地在各種不同的網絡環境中傳輸。
2.NAL單元
NAL單元是NAL的基本語法結構,它包含一個字節的頭信息和一系列來自VCL的稱為原始字節序列載荷(RBSP)的字節流。頭信息中包含著一個可否丟棄的指示標記,標識著該NAL單元的丟棄能否引起錯誤擴散,一般,如果NAL單元中的信息不用于構建參考圖像,則認為可以將其丟棄;最后包含的是NAL單元的類型信息,暗示著其內含有效載荷的內容。
送到解碼器端的NAL單元必須遵守嚴格的順序,如果應用程序接收到的NAL單元處于亂序,則必須提供一種恢復其正確順序的方法。
3.NAL實現編解碼器與傳輸網絡的結合
NAL提供了一個編解碼器與傳輸網絡的通用接口,而對于不同的網絡環境,具體的實現方案是不同的。對于基于流的傳輸系統如H.320、MPEG等,需要按照解碼順序組織NAL單元,并為每個NAL單元增加若干比特字節對齊的前綴以形成字節流;對于RTP/UDP/IP系統,則可以直接將編碼器輸出的NAL單元作為RTP的有效載荷;而對于同時提供多個邏輯信道的傳輸系統,我們甚至可以根據重要性將不同類型的NAL單元在不同服務質量的信道中傳輸[2]。
4.結論
為了實現編解碼器良好的網絡適應性,需要做兩方面的工作:第一、在Codec中將NAL這一技術完整而有效的實現;第二、在遵循H.264/AVC NAL規范的前提下設計針對不同網絡的最佳傳輸方案。如果實現了以上兩個目標,所實現的就不僅僅是一種視頻編解碼技術,而是一套適用范圍很廣的多媒體傳輸方案,該方案適用于如視頻會議,數據存儲,電視廣播,流媒體,無線通信,遠程監控等多種領域。
NALU類型
標識NAL單元中的RBSP數據類型,其中,nal_unit_type為1, 2, 3, 4, 5及12的NAL單元稱為VCL的NAL單元,其他類型的NAL單元為非VCL的NAL單元。
0:未規定
1:非IDR圖像中不采用數據劃分的片段
2:非IDR圖像中A類數據劃分片段
3:非IDR圖像中B類數據劃分片段
4:非IDR圖像中C類數據劃分片段
5:IDR圖像的片段
6:補充增強信息 (SEI)
7:序列參數集
8:圖像參數集
9:分割符
10:序列結束符
11:流結束符
12:填充數據
13 – 23:保留
24 – 31:未規定
NALU的順序要求
H.264/AVC標準對送到解碼器的NAL單元順序是有嚴格要求的,如果NAL單元的順序是混亂的,必須將其重新依照規范組織后送入解碼器,否則解碼器不能夠正確解碼。
1.序列參數集NAL單元必須在傳送所有以此參數集為參考的其他NAL單元之前傳送,不過允許這些NAL單元中間出現重復的序列參數集NAL單元。所謂重復的詳細解釋為:序列參數集NAL單元都有其專門的標識,如果兩個序列參數集NAL單元的標識相同,就可以認為后一個只不過是前一個的拷貝,而非新的序列參數集。
2.圖像參數集NAL單元必須在所有以此參數集為參考的其他NAL單元之先,不過允許這些NAL單元中間出現重復的圖像參數集NAL單元,這一點與上述的序列參數集NAL單元是相同的。
3.不同基本編碼圖像中的片段(slice)單元和數據劃分片段(data partition)單元在順序上不可以相互交叉,即不允許屬于某一基本編碼圖像的一系列片段(slice)單元和數據劃分片段(data partition)單元中忽然出現另一個基本編碼圖像的片段(slice)單元片段和數據劃分片段(data partition)單元。
4.參考圖像的影響:如果一幅圖像以另一幅圖像為參考,則屬于前者的所有片段(slice)單元和數據劃分片段(data partition)單元必須在屬于后者的片段和數據劃分片段之后,無論是基本編碼圖像還是冗余編碼圖像都必須遵守這個規則
5.基本編碼圖像的所有片段(slice)單元和數據劃分片段(data partition)單元必須在屬于相應冗余編碼圖像的片段(slice)單元和數據劃分片段(data partition)單元之前。
6.如果數據流中出現了連續的無參考基本編碼圖像,則圖像序號小的在前面。
7.如果arbitrary_slice_order_allowed_flag置為1,一個基本編碼圖像中的片段(slice)單元和數據劃分片段(data partition)單元的順序是任意的,如果arbitrary_slice_order_allowed_flag置為零,則要按照片段中第一個宏塊的位置來確定片段的順序,若使用數據劃分,則A類數據劃分片段在B類數據劃分片段之前,B類數據劃分片段在C類數據劃分片段之前,而且對應不同片段的數據劃分片段不能相互交叉,也不能與沒有數據劃分的片段相互交叉。
8.如果存在SEI(補充增強信息) 單元的話,它必須在它所對應的基本編碼圖像的片段(slice)單元和數據劃分片段(data partition)單元之前,并同時必須緊接在上一個基本編碼圖像的所有片段(slice)單元和數據劃分片段(data partition)單元后邊。假如SEI屬于多個基本編碼圖像,其順序僅以第一個基本編碼圖像為參照。
9.如果存在圖像分割符的話,它必須在所有SEI 單元、基本編碼圖像的所有片段slice)單元和數據劃分片段(data partition)單元之前,并且緊接著上一個基本編碼圖像那些NAL單元。
10.如果存在序列結束符,且序列結束符后還有圖像,則該圖像必須是IDR(即時解碼器刷新)圖像。序列結束符的位置應當在屬于這個IDR圖像的分割符、SEI 單元等數據之前,且緊接著前面那些圖像的NAL單元。如果序列結束符后沒有圖像了,那么它的就在比特流中所有圖像數據之后。
11.流結束符在比特流中的最后。
本文來自CSDN博客,轉載請標明出處:file:///D:/新建文件夾/桌面/H_264中的NAL技術%20-%20Bolt%20的專欄%20-%20CSDN博客.htm
生成zigzag序,
1、分析關鍵,在以zigzag序的每一行,以上三角為計算對象分別以i或j的增序排列,因此利用這一點就可以得出結果。
程序中s即為zigzag行號,而變換則以i和j交替。所以程序很簡單。
#include<iostream>
#include<iomanip>
using namespace std;
#define M 255
void zigzag(const int N)
{
int squa = N * N;
int a[M][M]={0};
for (int i = 0;i < N; i++)
{
for (int j = 0;j < N;j++)
{
int s = i + j;
if ( s < N)
{
a[i][j] = s * (s+1)/2 + ( (s %2 !=0)?i:j);//注意?:的優先級低于+
}
else
{
int sn = (N-1-i) + (N-1-j);
a[i][j] = squa - sn * (sn+1)/2 - (N - ( (sn%2 != 0)? i:j));
}
}
}
for (int i=0; i < N; i++)
{
for (int j = 0;j < N;j++)
{
cout<<setw(4)<<a[i][j]<<",";
}
cout<<endl<<endl;
}
}
int main()
{
zigzag(5);
cout<<endl;
zigzag(8);
cout<<endl;
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void zigzag(int n)
{
int **a =(int**) malloc(n*sizeof(int *)); //分配空間
if(NULL == a)
return ;
int i;
for(i = 0; i < n; i++) {
if((a[i] =(int*) malloc(n * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return;
}
}
bool flag = false; //這個標志位用來判斷是從45度角生成還是225度角生成
int count = 0;
for(i=0; i<n; i++) //生成的上半部分的數據
{
if(flag)
{
for(int r = 0; r<=i; r++)
{
a[r][i-r] = count;
count++;
}
flag = false;
}
else
{
for(int r = i; r>=0; r--)
{
a[r][i-r] = count;
count++;
}
flag = true;
}
}
for(i=n-1; i>=0; i--) //生成的是下半部分的數據
{
// cout<<i<<endl;
if(flag)
{
for(int r = 0; r<=i-1; r++)
{
int r1 = n-i+r; //代表當前行
int c1 = 2*n-i-1-r1; //代表當前列
a[r1][c1] = count;
count++;
}
flag = false;
}
else
{
for(int r = i-1; r>=0; r--)
{
cout<<"ddd"<<endl;
int r1 = n-i+r;
int c1 = 2*n-i-1-r1;
// cout<<r1<<","<<c1<<endl;
a[r1][c1] = count;
count++;
}
flag = true;
}
}
for(int r = 0; r<n; r++)
{
for(int c=0; c<n; c++)
cout<<a[r][c]<<",";
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
zigzag(n);
return 0;
}
網上還有一個人寫了一個比較巧的算法:
/**
* 得到如下樣式的二維數組
* zigzag(jpeg編碼里取象素數據的排列順序)
*
* 0, 1, 5, 6,14,15,27,28,
* 2, 4, 7,13,16,26,29,42,
* 3, 8,12,17,25,30,41,43,
* 9,11,18,24,31,40,44,53,
* 10,19,23,32,39,45,52,54,
* 20,22,33,38,46,51,55,60,
* 21,34,37,47,50,56,59,61,
* 35,36,48,49,57,58,62,63
*/
#include <stdio.h>
int main()
{
int N;
int s, i, j;
int squa;
scanf("%d", &N);
/* 分配空間 */
int **a = malloc(N * sizeof(int *));
if(a == NULL)
return 0;
for(i = 0; i < N; i++) {
if((a[i] = malloc(N * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return 0;
}
}
/* 數組賦值 */
squa = N*N;
for(i = 0; i < N; i++)
for(j = 0; j < N; j++) {
s = i + j;
if(s < N)
a[i][j] = s*(s+1)/2 + (((i+j)%2 == 0)? i : j);
else {
s = (N-1-i) + (N-1-j);
a[i][j] = squa - s*(s+1)/2 - (N - (((i+j)%2 == 0)? i : j));
}
}
/* 打印輸出 */
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++)
printf("%-6d", a[i][j]);
printf("\n");
}
return 0;
}
幾道面試筆試題
2008-02-26 18:38
一、如何判斷一個單鏈表是有環的?(注意不能用標志位,最多只能用兩個額外指針)
struct node { char val; node* next;}
bool check(const node* head) {} //return false : 無環;true: 有環
一種O(n)的辦法就是(搞兩個指針,一個每次遞增一步,一個每次遞增兩步,如果有環的話兩者必然重合,反之亦然):
bool check(const node* head)
{
if(head==NULL)
return false;
node *low=head, *fast=head->next;
while(fast!=NULL && fast->next!=NULL)
{
low=low->next;
fast=fast->next->next;
if(low==fast)
return true;
}
return false;
}
二、刪除一個單項鏈表的最中間的元素,要求時間盡可能短(不能使用兩次循環)
struct link
{
int data;
struct link *next;
};
void delMiddle(link *head)
{
if(head == NULL)
return;
else if(head->next == NULL)
{
delete head;
return;
}
else
{
link *low = head;
link *fast = head->next;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
if(fast == NULL)
break;
low = low->next;
}
link *temp = low->next;
low->next = low->next->next;
delete temp;
}
}
int main()
{
struct link *head,*l;
struct link *s;
head = (link*)malloc(sizeof(link));
head->data=0;
head->next = NULL;
l = head;
for(int i=1; i<9; i++)
{
s = (link*)malloc(sizeof(link));
s->data = i;
s->next = NULL;
l->next= s;
l = l->next;
}
print(head);
delMiddle(head);
print(head);
return 0;
}
三、輸入n,求一個n*n矩陣,規定矩陣沿45度線遞增(威盛)
/**
* 得到如下樣式的二維數組
* zigzag(jpeg編碼里取象素數據的排列順序)
*
* 0, 1, 5, 6,14,15,27,28,
* 2, 4, 7,13,16,26,29,42,
* 3, 8,12,17,25,30,41,43,
* 9,11,18,24,31,40,44,53,
* 10,19,23,32,39,45,52,54,
* 20,22,33,38,46,51,55,60,
* 21,34,37,47,50,56,59,61,
* 35,36,48,49,57,58,62,63
*/
void zigzag(int n)
{
int **a =(int**) malloc(n*sizeof(int *)); //分配空間
if(NULL == a)
return ;
int i;
for(i = 0; i < n; i++) {
if((a[i] =(int*) malloc(n * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return;
}
}
bool flag = false; //這個標志位用來判斷是從45度角生成還是225度角生成
int count = 0;
for(i=0; i<n; i++) //生成的上半部分的數據
{
if(flag)
{
for(int r = 0; r<=i; r++)
{
a[r][i-r] = count;
count++;
}
flag = false;
}
else
{
for(int r = i; r>=0; r--)
{
a[r][i-r] = count;
count++;
}
flag = true;
}
}
for(i=n-1; i>=0; i--) //生成的是下半部分的數據
{
// cout<<i<<endl;
if(flag)
{
for(int r = 0; r<=i-1; r++)
{
int r1 = n-i+r; //代表當前行
int c1 = 2*n-i-1-r1; //代表當前列
a[r1][c1] = count;
count++;
}
flag = false;
}
else
{
for(int r = i-1; r>=0; r--)
{
cout<<"ddd"<<endl;
int r1 = n-i+r;
int c1 = 2*n-i-1-r1;
// cout<<r1<<","<<c1<<endl;
a[r1][c1] = count;
count++;
}
flag = true;
}
}
for(int r = 0; r<n; r++)
{
for(int c=0; c<n; c++)
cout<<a[r][c]<<",";
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
zigzag(n);
return 0;
}
網上還有一個人寫了一個比較巧的算法:
/**
* 得到如下樣式的二維數組
* zigzag(jpeg編碼里取象素數據的排列順序)
*
* 0, 1, 5, 6,14,15,27,28,
* 2, 4, 7,13,16,26,29,42,
* 3, 8,12,17,25,30,41,43,
* 9,11,18,24,31,40,44,53,
* 10,19,23,32,39,45,52,54,
* 20,22,33,38,46,51,55,60,
* 21,34,37,47,50,56,59,61,
* 35,36,48,49,57,58,62,63
*/
#include <stdio.h>
int main()
{
int N;
int s, i, j;
int squa;
scanf("%d", &N);
/* 分配空間 */
int **a = malloc(N * sizeof(int *));
if(a == NULL)
return 0;
for(i = 0; i < N; i++) {
if((a[i] = malloc(N * sizeof(int))) == NULL) {
while(--i>=0)
free(a[i]);
free(a);
return 0;
}
}
/* 數組賦值 */
squa = N*N;
for(i = 0; i < N; i++)
for(j = 0; j < N; j++) {
s = i + j;
if(s < N)
a[i][j] = s*(s+1)/2 + (((i+j)%2 == 0)? i : j);
else {
s = (N-1-i) + (N-1-j);
a[i][j] = squa - s*(s+1)/2 - (N - (((i+j)%2 == 0)? i : j));
}
}
/* 打印輸出 */
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++)
printf("%-6d", a[i][j]);
printf("\n");
}
return 0;
}
四、打印1到1000的整數,不能使用流程控制語句(for,while,goto等)也不能使用遞歸
1.
typedef struct _test{
static int a;
_test(){
printf("%d\n",_test::a);
a++;
}
}Test;
int Test::a = 1;
int main()
{
Test tt[1000];
return 0;
}
2.
#include <stdio.h>
#define B P,P,P,P,P,P,P,P,P,P
#define P L,L,L,L,L,L,L,L,L,L
#define L I,I,I,I,I,I,I,I,I,I,N
#define I printf( "%3d ",i++)
#define N printf( "\n ")
int main()
{
int i = 1;
B;
}
或
#define A(x) x;x;x;x;x;x;x;x;x;x;
int main ()
{
int n = 1;
A(A(A(printf ("%d ", n++))));
return 0;
}
五、struct S {
int i;
int * p;
};
void main()
{
S s;
int * p = &s.i;
p[0] = 4;
p[1] = 3;
s.p = p;
s.p[1] = 1;
s.p[0] = 2;
}
問程序會在哪一行死掉。 (microsoft)
解: S s;
int * p = &s.i; //s.i的地址存儲在p里
p[0] = 4; //修改了s.i
p[1] = 3; //修改了s.p
s.p = p; //s.p指向s.i
s.p[1] = 1; //修改s.p本身
s.p[0] = 2; //s.p指向的是0x00000001,嘗試向這里寫,出錯
s.p[0] = 2; 時出錯
因為s.p存的是s.i的地址,s.p[1]為s.p,當s.p[1]=1時,s.p此時存放的是1了,而不是地址s.i,故在s.p[0] = 2時出錯.
此時相當于s.p=ox00000001;地址ox0000001 = 2;當然就出錯了
如果語句s.p[0] =2 先于s.p[1]=1則程序就不會出錯.此時語句相當于s.i=2;s.p=1;
六、題目描述:
1. int swap(int *x,int *y)
{
if(x==NULL | | y==NULL)
return -1;
*x += *y;
*y = *x- *y;
*x -= *y;
return 1;
}
請改錯,溢出已經考慮,不是錯誤
2.
void foo(int *x, int *y)
{
*x += *y;
*x += *y;
}
void fun(int *x, int *y)
{
*x += 2 * (*y);
}
問兩個函數是否等價,能否互換
解答:第一題的函數是交換。但假如考慮x, y都是指向同一個變量,結果是這個變量的值為0.
第二題的兩個函數是有區別的,也考慮x,y是指向同一個變量.這樣第一個函數的結果是這個變量的4倍.但第二個函數的結果是變量的3倍.
|
C++ placement new 用法舉例zz
2009-12-17 16:16
在處理內存分配的時候,C++程序員會用new操作符(operator new)來分配內存,并用delete操作符(operator delete)來釋放內存。這是一個new操作符的例子。
class CTest
{
/* 成員函數和成員數據 */
};
// . . . 代碼
// 分配一個對象
CTest * pTest = new Test;
// 分配一個有十個對象的數組 (CTest 要有缺省構造函數(default constuctor))
CTest * p10Tests = new Test[ 10];
雖然這種寫法在大多數時候都工作得很好,但還是有些情況下使用new是很煩人的,比如當你想重新分配一個數組或者當你想在預分配的內存上構造一個對象的時候。
比如第一種情況,重新分配一個數組效率是很低的:
// 分配一個有10個對象的數組
CTest * pTests = new Test[ 10];
// . . .
// 假設現在我們需要11個對象
CTest * pNewTests = new Test[ 11];
// . . . 我們必須把原來的對象拷貝到新分配的內存中
for ( int i = 0; i < 10; i++)
pNewTests[ i] = pTests[ i];
delete pTests;
pTests = pNewTests;
如果你想在預分配的內存上創建對象,用缺省的new操作符是行不通的。要解決這個問題,你可以用placement new構造。它允許你構造一個新對象到預分配的內存上:
// buffer 是一個void指針 (void *)
// 用方括號[] 括起來的部分是可選的
[CYourClass * pValue = ] new( buffer) CYourClass[( parameters)];
下面是一些例子:
#include <new>
class CTest
{
public:
CTest()
{}
CTest( int)
{}
/* 代碼*/
};
int main(int argc, char* argv[])
{
// 由于這個例子的目的,我們不考慮內存對齊問題
char strBuff[ sizeof( CTest) * 10 + 100];
CTest * pBuffer = ( CTest *)strBuff;
// 缺省構造
CTest * pFirst = new(pBuffer) CTest;
// 缺省構造
CTest * pSecond = new(pBuffer + 1) CTest;
// 帶參數的構造;
// 不理會返回的指針
new(pBuffer + 2) CTest( 5);
// 帶參數的構造
CTest * pFourth = new( pBuffer + 3) CTest( 10);
// 缺省構造
CTest * pFifth = new(pBuffer + 4) CTest();
// 構造多個元素(缺省構造)
CTest * pMultipleElements = new(pBuffer + 5) CTest[ 5];
return 0;
}
當你有自己的內存緩沖區或者在你實現自己的內存分配策略的時候,placement new會很有用。事實上在STL中廣泛使用了placement new來給容器分配內存;每個容器類都有一個模版參數說明了構造/析構對象時所用的分配器(allocator)。
在使用placement new的時候,你要記住以下幾點:
- 加上頭文件#include <new>
- 你可以用placement new構造一個數組中的元素。
- 要析構一個用placement new分配的對象,你應該手工調用析構函數(并不存在一個“placement delete”)。它的語法如下:
pFirst->~CTest();
pSecond->~CTest();
前段事件,我問過關于placement new的問題,一位仁兄講了一些道理,他說道:
::棧上的對象(注意,是類對象,char類型就無需了,后面還會提到)保證放在對齊地址上.
但是,個人實驗了一下,發現并不是這樣
例如:
int main()
{
char c1 = 'A' ;
char c2 = 'B' ;
char c3 = 'C' ;
char c4 = 'D' ;
char c5 = 'E' ;
//-------- 驗證這四個地址是否是 4 的倍數 --------------//
if ( ((int)(&c1)) % 4 == 0 )
cout << "c1:Yes" << endl ;
if ( ((int)(&c2)) % 4 == 0 )
cout << "c2:Yes" << endl ;
if ( ((int)(&c3)) % 4 == 0 )
cout << "c3:Yes" << endl ;
if ( ((int)(&c4)) % 4 == 0 )
cout << "c4:Yes" << endl ;
if ( ((int)(&c5)) % 4 == 0 )
cout << "c5:Yes" << endl ;
cout << (int)(&c1) << endl // 輸出四個字符所在的地址(輸出結果都是 4 的倍數)
<< (int)(&c2) << endl
<< (int)(&c3) << endl
<< (int)(&c4) << endl
<< (int)(&c5) << endl ;
}
-----------------------------
上面的執行結果在VC下運行都是 4 的倍數
--------------
--> 問題1:連棧上分配的空間地址都是 4 的倍數,那就說明系統分配的空間都是 4 的倍數吧???
--> 問題2:如果萬一,如果放一個對象的地址不是4的倍數,那么會出現什么情況??可以給簡單說一下嗎?
--> 問題3:地址對齊的通用性???
-------------
程序1:
Class C1
{
int i ;
char c ;
} ;
cout << sizeof(C1) << endl ;// 輸出結果: 8 (是 4 的倍數)
程序2:
class C2
{
char c1 ;
char c2 ;
} ;
cout << sizeof(C2) << endl ;// 輸出結果:2 ( 上一個中char類型也給了4個字節,怎么這個地方都給了一個字節??)
--> 問題4:由上面的程序2 引出下面的程序
class C2// sizeof(C2) =2 ,在VC實驗下的結果,不是 4
{
char c1 ;
char c2 ;
} ;
//----------用placement new方法建立對象----------------
void *ptr = operator new(100) ;// 分配內存
C2 *POINTER = (C2*)ptr ;// 類型轉換
String *str1 = new (POINTER) C2() ;// 建立一C2對象
String *str2 = new (POINTER+1) C2() ;// 再建立一個對象
String *str3 = new (POINTER+2) C2() ;// 再建立一個對象
cout << (int)(str1) << endl// 結果:3608720( 是4的倍數)
<< (int)(str2) << endl // 結果:3608722(不是4的倍數)!!
<< (int)(str3) << endl ;// 結果:3608724(不是4的倍數)!!
|
很實用的word的高級用法總匯2009-04-23 16:26
任意放大/變小 字體
快捷鍵ctrl+] 放大 字體 ctrl+[ 縮小字體
把文字替換成圖片
首先把圖片復制到 剪貼板中,然后打開替換對話框,在“查找內容”框中輸入將被替換的文字,接著在 “替換為”框中輸入“^c”(注意:輸入的一定要是半角字符,c要小寫),單擊替換 即可。說明:“^c”的意思就是指令Word XP以剪貼板中的內容替換“查找內容”框中的內 容。按此原理,“^c”還可替換包括回車符在內的任何可以復制到剪貼板的可視內容,甚至Excel表格。
三招去掉頁眉那條橫線
1、在頁眉中,在“格式”-“邊框和底紋”中設置表格和邊框為“無”,應用于“段落”
2、同上,只是把邊框的顏色設置為白色(其實并沒有刪的,只是看起來沒有了,呵呵)
3、在“樣式”欄里把“頁眉”換成“正文”就行了——強烈推薦!
會多出--(兩個橫杠) 這是用戶不愿看到的,又要多出一步作刪除--
解決方法:替換時在前引號前加上一個空格 問題就解決了
插入日期和時間的快捷鍵
Alt+Shift+D:當前日期
Alt+Shift+T:當前時間
批量轉換全角字符為半角字符
首先全選。然后“格式”→“更改大小寫”,在對話框中先選中“半角”,確定即可
Word啟動參數簡介
單擊“開始→運行”命令,然后輸入Word所在路徑及參數確定即可運行,如“C:\ PROGRAM FILES \MICROSOFT Office \Office 10\ WINWord.EXE /n”,這些常用的參數及功能如下:
/n:啟動Word后不創建新的文件。
/a:禁止插件和通用模板自動啟動。
/m:禁止自動執行的宏。
/w:啟動一個新Word進程,獨立與正在運行的Word進程。
/c:啟動Word,然后調用Netmeeting。
/q:不顯示啟動畫面。
另外對于常需用到的參數,我們可以在Word的快捷圖標上單擊鼠標右鍵,然后在“目標”項的路徑后加上該參數即可。
快速打開最后編輯的文檔
如果你希望Word在啟動時能自動打開你上次編輯的文檔,可以用簡單的宏命令來完成:
(1)選擇“工具”菜單中的“宏”菜單項,單擊“錄制新宏”命令打開“錄制宏”對話框;
(2)在“錄制宏”對話框中,在“宏名”輸入框中輸入“autoexec”,點擊“確定”;
(3)從菜單中選擇“文件”,點擊最近打開文件列表中顯示的第一個文件名;并“停止錄制”。保存退出。下次再啟動Word時,它會自動加載你工作的最后一個文檔。
格式刷的使用
1、設定好文本1的格式。
2、將光標放在文本1處。
3、單擊格式刷按鈕。
4、選定其它文字(文本2),則文本2的格式與文本1 一樣。
若在第3步中單擊改為雙擊,則格式刷可無限次使用,直到再次單擊格式刷(或按Esc鍵)為止。
刪除網上下載資料的換行符(象這種“↓”)
在查找框內輸入半角^l(是英文狀態下的小寫L不是數字1),在替換框內不輸任何內容,單擊全部替換,就把大量換行符刪掉啦。
選擇性刪除文件菜單下的最近使用的文件快捷方式。
工具→選項→常規把“列出最近使用文件數改為0”可以全部刪除,若要選擇性刪除,可以按ctrl+Alt+ -三個鍵,光標變為一個粗減號后,單擊文件,再單擊要刪除的快捷方式就行了。
建立一個矩形選區:
一般的選區建立可用鼠標左鍵,或用shift鍵配合pgup、pgdn、home、end、箭頭等功能鍵,當復制一個規則的矩形區域時,可先按住Alt鍵,然后用鼠標左鍵來選。我一般用此來刪除段首多余的成塊的空格。大家試一試*^_^*
將字體快速改為上標或下標的方法:
本人在一次無意間發現了這個方法,選定你要下標的字,然后在英文狀態下按住Ctrl,再按一下BASKSPACE旁的+/=的鍵,就可以了。上標只要在按Ctrl的同時也按住Shift,大家可以試試。
讓Word表格快速一分為二
將光標定位在分開的表格某個位置上,按下“Ctrl+Shift+Enter”組合鍵。這時你就會發現表格中間自動插入一個空行,這樣就達到了將一個表格一分為二的目的。
用Word來拆字
首先點擊“工具/自定義/命令/分解圖片”,按住鼠標左鍵把它拖放到工具欄任意位置即可;然后點擊“插入/圖片/藝術字”,例如輸入空心字“心”,選擇該“心”字剪切,在選擇性粘貼中選圖片(Windows圖元文件),選中該字,點擊工具欄中的“分解圖片”按鈕,這樣可以選擇“心”中的任意筆畫進行一筆一畫的拆分了。
快速刪除段前段后的任意多個空格
選定這些段段落,單擊居中按鈕,然后再單擊原來的那種對齊方式按鈕(如果原來是居中對齊的,先單擊其它對齊方式按鈕,再單擊居中按鈕就行了),是不是這些空格全不見了?
只要打開WORD新建一個空文檔的時候,出現的不是空的文檔,而是我以前打的一份文檔
首先:將資源管理器設置為顯示所有文件和文件夾;
然后:
C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates文件夾下將所有Normal.doc文件刪掉;
然后:OK(XP系統)
快速輸入平方的方法
先輸入2,然后選重后,按ctrl加shift加+就可以了.
WORD中表格的選擇性錄入
1.設置好表格,選定表格-視圖-工具-窗體-插入下拉型窗體域
2.輸入數據,完成
3.點擊鎖按鈕,保護,輸入完后再點擊進行其它的輸入.
標點符號的全角/半的轉換用:Ctrl+.
數字字母的全角/半的轉換用:Shift+空格
輕松了解工具欄按鈕的作用
按下“shift+F1”鍵,鼠標指針旁多了一個“?”號,想知道哪個按鈕
的作用,就用鼠標單擊哪個。
要經常在文檔中插入自己公司的信息
公司名稱
公司住址
聯系電話
聯系人姓名
QQ號碼
可以先選定這些內容,再單擊工具→自動更正→在替換框中輸入標記名稱(如“公司信息”)→添加→確定,以后凡是在文檔中要用到這個信息的地方鍵入“公司信息”(不要引號)這幾個字后就自動替換成:
公司名稱
公司住址
聯系電話
聯系人姓名
QQ號碼
說明:有些輸入法不支持這個功能,鍵入標記名稱后要按一下空格才行。
快速換頁的方法
雙擊某頁的右下腳,光標即可定位在那里,然后按回車直到換頁。ctrl+回車點插入按紐,分隔符,選中分頁符,然后確認就OK了 !!!
表格的簡單調整寬度
鼠標放在表格的右邊框上帶鼠標變成可以調整大小的時候
雙擊
根據表格內的內容調節表格大小
代替金山詞霸
點工具——語言——翻譯,在右邊出現的搜索框中輸入要查的單詞,回車就可以翻譯了。可以選擇英語翻成中文或中文翻成英語。
第一次使用可能要安裝。
[Alt]鍵實現標尺的精確定位
如果你經常使用水平標尺來精確定位標簽、頁邊框、首字縮進及頁面對象的位置,那么你點擊標尺設置頁邊框或標簽時,您只可以將其設置為1字符或2字符,但不能設為1.5字符!要想設置更為精確的度量單位(例如百分之幾字符),在按住[Alt]鍵的同時,點擊并移動標尺或邊框,此時標尺將用數字精確顯示出當前的位置為百分之幾字符位置。
用“記事本”去除格式
網頁上COPY下來的東西往往都是有網格的,如果直接粘貼在WORD中會雜亂無章。先粘貼到記事本當中,再粘貼到WORD中,就可以去除網格等格式,再全選選擇清除格式,居中再取消居中即可取消所有格式。可以直接在WORD中進行:(菜單)編輯/選擇性粘貼……/無格式文本/確定。這樣省事多了。
快速將文檔轉換成圖片
先把欲想轉換的文檔保存退出.如:保存在桌面
然后新建一個文件.把想轉換的文檔(鼠標左建按住該文檔不放)直接施放在頁面上
恢復office的默認設置
比如不小心把word設置亂了(如刪了菜單欄等等).
查找normal.dot直接刪除.
下一次啟動word會恢復默認值.
讓Word只粘貼網頁中的文字而自動去除圖形和版式
方法一、選中需要的網頁內容并按“Ctrl+C”鍵復制,打開Word,選擇菜單“編輯”→“選擇性粘貼”,在出現的對話框中選擇“無格式文本”。
方法二、選中需要的網頁內容并按“Ctrl+C” 鍵復制,打開記事本等純文本編輯工具,按“Ctrl+V”鍵將內容粘貼到這些文本編輯器中,然后再復制并粘貼到Word中。
ctrl+alt+f可以輸入腳注
這個對于經常寫論文的朋友應該有點幫助。
將阿拉伯數字轉換成中文數字或序號
1、先輸入阿拉伯數字(如1234),全選中,單擊“插入/數字/數字類型(壹、貳……)/確定”,即變為大寫數字(如壹仟貳佰叁拾肆),會計朋友非常適用。
2、其他像一千二百三十四,甲、乙……,子、丑……,羅馬數字等的轉換,可參考上法。
Word中的常用快捷鍵吧
“字體”對話框 Ctrl+D
選擇框式工具欄中的“字體”框 Ctrl+Shift+F
加粗 Ctrl+B
傾斜 Ctrl+I
下劃線Ctrl+U
“上標”效果 Ctrl+Shift+=
“下標”效果 Ctrl+=
“關閉”命令 Ctrl+W
Word快捷鍵一覽表
序號 快捷鍵CTRL+ 代表意義
1…………Z…………撤消
2…………A…………全選
3…………X…………剪切
4…………C…………復制
5…………V…………粘貼
6…………S…………保存
7…………B…………加粗
8………… Q…………左對齊
9…………E…………據中
10…………R…………右對齊
11…………]…………放大
22…………[…………縮小
12…………N…………新建文檔
13…………I…………字體傾斜
14…………W…………退出
15…………P…………打印
16…………U…………下劃線
17…………O…………打開
18…………k…………插入超級連接
19…………F…………查找
20…………H…………替換
21…………G…………定位
23…Ctrl+Alt+L……帶括號的編號
24…Ctrl+Alt+.________…
25…Alt+數字………區位碼輸入
26…Ctrl+Alt+Del………關機
27…Ctrl+Alt+Shift+?……¿
28…Ctrl+Alt+Shift+!……¡
29…Alt+Ctrl+E……………?
30…Alt+Ctrl+R……………®
31…Alt+Ctrl+T……………™
32…Alt+Ctrl+Ctrl…………©
33……Ctrl+D……………格式字體
34……Ctrl+Shift+= ………上標
35……Ctrl+=………………下標
36……Ctrl+Shift+>……放大字體
37……Ctrl+Shift+< ……縮小字體
38……Alt+Ctrl+I………打印預覽
39……Alt+Ctrl+O………大剛示圖
40……Alt+Ctrl+P………普通示圖
41……Alt+Ctrl+M………插入批注
42……Alt+菜單上字母………打開該菜單
無級微調
打開“繪圖”工具欄-點開下拉菜單-繪圖網格...-將水平間距和垂直間距調到最小0.01-確定,這樣你就可以無級微調
把work設置成在線打開,但不能修改‘只讀’怎搞啊?
文件夾共享為只讀
在WORD中輸入三個等號然后回車。。。出來的是雙橫線哦。。。
同樣的方法也可以做出波浪線單橫線哦!~~~~~ ,
###為中間粗上下細的三線, ***為點線, ~~~為波浪線, ---為單線
輸入拼音字母的音調怎么輸入
用智能ABC,鍵入v9,然后自己挑選吧!
頁碼設置
1、打開頁眉/頁腳視圖,點擊插入頁碼按鈕,將頁碼插入(此時所有的頁碼是連續編號的) 2、切換到頁面視圖,在需要從1計數的頁面上插入連續分節符(插入--分隔符--分節符--連續) 3、再次換到頁眉/頁腳視圖,點擊設置頁碼格式按鈕,將頁碼編排-起始頁碼設置為1
把Excel中的表格以圖片形式復制到Word中
除了用抓圖軟件和全屏拷貝法外還有更簡單的呢
先選定區域,按住Shift健點擊"編輯"會出現"復制圖片""粘貼圖片",復制了后,在Word中選"粘貼圖片"就可像處理圖片一樣處理Excel表格了!
Ctrl+鼠標滑輪(左右鍵中間的那個輪子)可以迅速調節顯示比例的大小(100%)。向上滑擴大,向下滑縮小。
快速調整頁眉橫線長度
在word插入頁眉后,會自動在此位置添加一條長橫線。如果需要調整此線的長度及其水平位置,可以首先激活頁眉,選擇格式下的段落命令,調整一下左右縮進的字符值,確定可以看到最終效果了!
快速瀏覽圖片
在WORD2003中,如果插入的圖片過多,會影響打開和翻滾的速度。其實,我們可以通過改變圖片的顯示方式改變瀏覽速度。
工具--選項--視圖--圖片框
這樣,先顯示的是圖片框,需要看的時候,停留,即可顯示!
WORD 中如何輸入分數
1、打開word,點擊工具菜單欄的“插入”,在下拉菜單中點“域”。
2、在打開的復選框中的類別欄中“選等式公式”,域名中“EQ”。然后點擊“選項”,在出現的菜單選項中選“F(,)”,接著點擊“添加到域”并“確定”。
3、然后在輸入F(,)數字,如要輸入23 只需在F(,)輸入F(2,3)就能得到2/3
怎樣使WORD 文檔只有第一頁沒有頁眉,頁腳
答:頁面設置-頁眉和頁腳,選首頁不同,然后選中首頁頁眉中的小箭頭,格式-邊框和底紋,選擇無,這個只要在“視圖”——“頁眉頁腳”,其中的頁面設置里,不要整個文檔,就可以看到一個“同前”的標志,不選,前后的設置情況就不同了
Word中雙擊鼠標的妙用
在Word的程序窗口中不同位置上雙擊,可以快速實現一些常用功能,我們歸納如下:
在標題欄或垂直滾動條下端空白區域雙擊,則窗口在最大化和原來狀態之間切換;
將鼠標在標題欄最左邊WORD文檔標記符號處雙擊,則直接退出WORD(如果沒有保存,會彈出提示保存對話框);
將鼠標移到垂直滾動條的上端成雙向拖拉箭頭時雙擊,則快速將文檔窗口一分為二;
將鼠標移到兩個窗口的分界線處成雙向拖拉箭頭時雙擊,則取消對窗口的拆分;
在狀態欄上的“修訂”上雙擊,則啟動“修訂”功能,并打開“審閱”工具欄。再次雙擊,則關閉該功能,但“審閱”工具欄不會被關閉;
在狀態欄上的“改寫”上雙擊,則轉換為“改寫”形式(再次“雙擊”,轉換為“插入”形式);
如果文檔添加了頁眉(頁腳),將鼠標移到頁眉(頁腳)處雙擊,則激活頁眉(頁腳)進入編輯狀態,對其進行編輯;在空白文檔處雙擊,則啟動“即點即輸”功能;
在標尺前端空白處雙擊,則啟動“頁面設置”對話框。
在word編輯中經常要調整字休大小來滿足編輯要求
選中要修改的文字,按ctrl+]或ctrl+[來改變字體的大小!
這個方法可以微量改字體大小~
文本框的線條
1. 制作好文檔后,通過“視圖→頁眉頁腳”命令,調出“頁眉頁腳”工具欄,單擊其中的“顯示→隱藏文檔正文文字”按鈕,隱藏正文部分的文字內容。
2. 選擇“插入”菜單中的“文本框”命令,在頁眉的下方插入一個空文本框。
3. 在文本框內加入作為水印的文字、圖形等內容,右擊圖片,選擇快捷菜單中的“設置圖片格式”命令,在對話框中“圖片”選項卡下,通過“圖像控制”改變圖像的顏色,對比度和亮度,并手動調整圖片的大小。
4. 通過“設置文本框格式”命令,把文本框的線條色改為無線條色。
5. 單擊“頁眉頁腳”工具欄的“關閉”按鈕,退出“頁眉頁腳”編輯。
每頁添加水印的操作
1. 制作好文檔后,通過“視圖→頁眉頁腳”命令,調出“頁眉頁腳”工具欄,單擊其中的“顯示→隱藏文檔正文文字”按鈕,隱藏正文部分的文字內容。
2. 選擇“插入”菜單中的“文本框”命令,在頁眉的下方插入一個空文本框。
3. 在文本框內加入作為水印的文字、圖形等內容,右擊圖片,選擇快捷菜單中的“設置圖片格式”命令,在對話框中“圖片”選項卡下,通過“圖像控制”改變圖像的顏色,對比度和亮度,并手動調整圖片的大小。
4. 通過“設置文本框格式”命令,把文本框的線條色改為無線條色。
5. 單擊“頁眉頁腳”工具欄的“關閉”按鈕,退出“頁眉頁腳”編輯。
6. 完成上述步驟的操作,水印制作得以完成,這樣就為每一頁都添加了相同的水印。
讓Word頁面快速一分為二
將光標定位在想分開的位置上,按下“Ctrl+Shift+Enter”組合鍵。
使Word中的字體變清晰
Word文檔中使用 “仿宋” 字體很淡,可按以下方法使字體更清晰:
右擊桌面,點 “屬性”,點 “外觀”,點 “效果”,選中“使用下列方式使屏幕字體的邊緣平滑”選“清晰”,確定。
Word雙面打印技巧
我們平時用電腦的時候可能都少不了打印材料,Word是我們平常用的最多的Office軟件之一。有時我們要用Word打印許多頁的文檔,出于格式要求或為了節省紙張,會進行雙面打印。
我們一般常用的操作方法是:選擇“打印”對話框底部的“打印”下拉列表框中的“打印奇數頁”或“打印偶數頁”,來實現雙面打印。我們設定為先打印奇數頁。等奇數頁打印結束后,將原先已打印好的紙反過來重新放到打印機上,選擇該設置的“打印偶數頁”,單擊“確定”按鈕。這樣通過兩次打印命令就可以實現雙面打印。
我們也可以利用另一種更靈活的雙面打印方式:打開“打印”對話框,選中“人工雙面打印”,確定后就會出現一個“請將出紙器中已打印好的一面的紙取出并將其放回到送紙器中,然后‘確定’按鍵,繼續打印”的對話框并開始打印奇數頁,打完后將原先已打印好的紙反過來重新放到打印機上,然后按下該對話框的“確定”按鍵,Word就會自動再打印偶數頁,這樣只用一次打印命令就可以了。
兩種方法對比,后者較前者更為方便。
|
字符串拆分的中文處理問題
容健行@2007年7月
轉載請注明出處
原文出處:http://www.devdiv.net/home/space.php?uid=125&do=blog&id=365
概述:
拆分一個字符串在程序中使用非常廣泛,特別是我們經常跟表格打交道的程序員們。所謂拆分字符串,就是將一個字符串中間以某個(或某些)字符為分隔,拆分成多個字符串。如 std::string s = "abc | ddd | 中國"; 如果以豎線“|”拆分,可以將這個字符串拆分成三個字符串。
當然字符串拆分還包括通過正則表達式來拆分,為了簡化問題,我們以單個字符做分隔的拆分,因為這種拆分用得最多。代碼使用C++來講解。
問題:
問題來源于實際,是之前我們組和其他組都有遇上的。先看一個例子,使用"|"拆分以下字符串,看起來怎么數都是分為48列,但我看到好幾個版本的字符串拆分函數卻報有49列:
"AGZGY1000004|200|劉瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾曉翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||"
原因分析:
讓我們先把以上字符串放到UltraEdit中,并切換到16進制的編輯模式,看看它的編碼。
原因是原來的字符串拆分函數只是簡單的查找“|”(編碼為0x7c),而沒有考慮到中文的處理(源代碼太多,且有好幾個版本,這里略去)。
在boss中,c++程序使用的編碼方式幾乎全為ansi,而在ansi中,表示中文是用兩個字符,且第一個字符是一個大于0x80的字符(字符的第一位為1),第二個字符為任意字符。這里引起一個問題:
當我們要分割字符串時,假如用"|"(0x7c)作為分割符,當分析上面這個字符遇到"瓅"(編碼為0xad,0x7c)這個字符時,會把它第二個字符作為了分割符,結果就多出了一列。
解決方案:
問題原因找到了,重新寫了一下字符串拆分函數-Split,這里使用的方法是:找到分隔符后,再向前查找字符看一下它前一個字符是否為東亞文字的第一個字符編碼(編碼大于0x80)。
考慮到以后支持unicode,這里使用了模板。以下可能不是最高效簡單的實現,但如果以后遇上這種問題,可以參考一下。
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
// unicode 分割策略
inline
bool __SplitPolicy(
const std::wstring& s,
const std::wstring& splitchar,
std::wstring::size_type& pos)
{
pos = s.find_first_of(splitchar, pos);
return pos != std::string::npos;
}
// ansi 分割策略
inline
bool __SplitPolicy(
const std::string& s,
const std::string& splitchar,
std::string::size_type& pos)
{
pos = s.find_first_of(splitchar, pos);
if (pos != std::string::npos)
{
// 如果前一個字符的第一位為1,且當前字符是在東亞文字的第二個字符,
// 則認為該字符是東亞字的其中一個字符,要跳過,不作為分割符。
std::string::size_type i = 1;
for (; i < pos; ++i)
{
if (!((char)(s[pos - i]) & 0x80)) // 判斷第一位是否為1。(0x80的二進制為 10000000)
break;
}
if (!(i % 2)) // 看一下當前字符是否為東亞文字的第二個字符
{
++pos;
__SplitPolicy(s, splitchar, pos);
}
}
return pos != std::string::npos;
}
template<typename char_type> inline
int Split(
const std::basic_string<char_type>& s,
const std::basic_string<char_type>& splitchar,
std::vector<std::basic_string<char_type> >& vec)
{
typedef std::basic_string<char_type> string_t;
typedef typename string_t::size_type size_t;
string_t tmpstr;
size_t pos = 0, prev_pos = 0;
vec.clear();
while (__SplitPolicy(s, splitchar, pos))
{
tmpstr = s.substr(prev_pos, pos - prev_pos);
vec.push_back(tmpstr);
prev_pos = ++pos;
}
size_t len = s.length() - prev_pos;
if (len > 0)
vec.push_back(s.substr(prev_pos, len));
return static_cast<int>(vec.size());
}
// ansi版本測試
void testSplit()
{
std::vector<std::string> vec;
const std::string str = "AGZGY1000004|200|劉瓅瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾曉翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||a";
const std::string sp = "|";
int count = Split(str, sp, vec);
for (std::vector<std::string>::const_iterator it = vec.begin(); it != vec.end(); ++it)
std::cout << *it << " ";
}
// unicode版本測試
void testSplitW()
{
std::vector<std::wstring> vec;
const std::wstring str = L"AGZGY1000004|200|劉瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾曉翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||";
const std::wstring sp = L"|";
Split(str, sp, vec);
const char head[3] = {0xff, 0xfe, 0};
const wchar_t line[3] = L" ";
// 控制臺輸出不了unicode字符,使用輸出到文件的方式
std::ofstream fileOut("C:/out.txt");
fileOut.write(head, 2);
for (std::vector<std::wstring>::iterator it = vec.begin(); it != vec.end(); ++it)
{
fileOut.write((const char*)it->c_str(), it->length() * 2);
fileOut.write((const char*)line, 2);
}
}
int main()
{
testSplit();
testSplitW();
}
參考:
1.http://unicode.org/
2.《談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞》
一 引入問題
代碼 wchar_t a[3]=L”中國”,編譯時出錯,出錯信息為:數組越界。但wchar_t 是一個寬字節類型,數組a的大小應為6個字節,而兩個漢字的的unicode碼占4個字節,再加上一個結束符,最多6個字節,所以應該不會越界。難道是編譯器出問題了?
二 解決引入問題所需的知識
主要需兩方面的知識,第一個為字符尤其是漢字的編碼,以及語言和工具的支持情況,第二個是vc/c++中MutiByte Charater Set 和 Wide Character Set有關內存分配的情況.
三 漢字的編碼方式及在vc/c++中的處理
1.漢字編碼方式的介紹
對英文字符的處理,7位ASCII碼字符集中的字符即可滿足使用需求,且英文字符在計算機上的輸入及輸出也非常簡單,因此,英文字符的輸入、存儲、內部處理和輸出都可以只用同一個編碼(如ASCII碼)。
而漢字是一種象形文字,字數極多(現代漢字中僅常用字就有六、七千個,總字數高達5萬個以上),且字形復雜,每一個漢字都有"音、形、義"三要素,同音字、異體字也很多,這些都給漢字的的計算機處理帶來了很大的困難。要在計算機中處理漢字,必須解決以下幾個問題:首先是漢字的輸入,即如何把結構復雜的方塊漢字輸入到計算機中去,這是漢字處理的關鍵;其次,漢字在計算機內如何表示和存儲?如何與西文兼容?最后,如何將漢字的處理結果從計算機內輸出?
為此,必須將漢字代碼化,即對漢字進行編碼。對應于上述漢字處理過程中的輸入、內部處理及輸出這三個主要環節,每一個漢字的編碼都包括輸入碼、交換碼、內部碼和字形碼。在計算機的漢字信息處理系統中,處理漢字時要進行如下的代碼轉換:輸入碼→交換碼→內部碼→字形碼。
(1)輸入碼: 作用是,利用它和現有的標準西文鍵盤結合來輸入漢字。輸入碼也稱為外碼。主要歸為四類:
a) 數字編碼:數字編碼是用等長的數字串為漢字逐一編號,以這個編號作為漢字的輸入碼。例如,區位碼、電報碼等都屬于數字編碼。
b) 拼音碼:拼音碼是以漢字的讀音為基礎的輸入辦法。
c) 字形碼:字形碼是以漢字的字形結構為基礎的輸入編碼。例如,五筆字型碼(王碼)。
d) 音形碼:音形碼是兼顧漢字的讀音和字形的輸入編碼。
(2)交換碼:用于漢字外碼和內部碼的交換。交換碼的國家標準代號為GB2312-80。
(3)內部碼:內部碼是漢字在計算機內的基本表示形式,是計算機對漢字進行識別、存儲、處理和傳輸所用的編碼。內部碼也是雙字節編碼,將國標碼兩個字節的最高位都置為"1",即轉換成漢字的內部碼。
(4)字形碼:字形碼是表示漢字字形信息(漢字的結構、形狀、筆劃等)的編碼,用來實現計算機對漢字的輸出(顯示、打印)。
2.VC中漢字的編碼方式
vc/c++正是采用了GB2312內部碼作為漢字的編碼方式,因此vc/c++中的各種輸入輸出方法,如cin/wcin,cout/wcout,scanf/wsanf,printf/wprintf...都是基于GB2312的,如果漢字的內碼不是這種編碼方式,那么利用上述各種方法就不會正確的解析漢字。
仔細觀察ASCII字符表,從第161個字符開始,后面的字符并不經常為用戶所使用,負值也未使用。GB2312編碼方式充分利用這一特性,將161-255(-95~-1)之間的數值空間作為漢字的標識碼。既然255-161 = 94不能滿足漢字容量的要求,就將每兩個字符并在一塊(即一個漢字占兩個字節),顯然,94* 94 =8836基本上已經滿足了常用漢字個數的要求。計算機處理字符時,當連續處理到兩個大與160(或-95~-1)的字節時,就認為這兩個字節存放了一個漢字字符。可以用下面的Demo程序來模擬vc/c++中輸出漢字字符的過程。
unsigned char input[50];
cin>>input;
int flag=0;
for(int i =0 ;i < 50 ;i++)
{
if(input[i] > 0xa0 && input[i] != 0)
{
if(flag == 1)
{
cout<<"chinese character"<<endl;
flag = 0;
}
else
{
flag++;
}
}
else if(input[i] == 0)
{
break;
}
else
{
cout<<"english character"<<endl;
}
}
輸入:Hello中國 (“中國”對應的GB2312內碼為:214 208,185 250)
輸出:english character
english character
english character
english character
english character
chinese character
chinese character
vc/c++中的英文字符仍然采用ASCII編碼方式。可以設想,其他國家程序員利用vc/c++編寫程序輸入本國字符時,vc/c++則會采用該國的字符編碼方式來處理這些字符。
問題又產生了,韓國的vc/c++程序在中國的vc/c++上運行時,如果沒有相應的內碼庫,則對韓語字符的顯示有可能出現亂碼。我個人猜測,vc安裝程序中應該帶有不同國家的內碼庫,這樣一來肯定會占用很大的空間。如果所有的國家使用統一的編碼方式,且所有的程序設計語言和開發工具都支持這種編碼方式該多好!而現實中,確實已經有這種編碼方式了,且許多新的語言也都支持這種編碼方式,如Java、C#等,它就是下面的Unicode編碼
3.新的內碼標準---Unicode
Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公布。隨著計算機工作能力的增強,Unicode也在面世以來的十多年里得到普及。最新版本的 Unicode 是 2005年3月31日推出的Unicode 4.1.0 。另外,5.0 Beta已于2005年12月12日推出,以供各會員評價。
Unicode 編碼系統可分為編碼方式和實現方式兩個層次。
編碼方式:Unicode 的編碼方式與 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相對應,目前的用于實用的 Unicode 版本對應于 UCS-2,使用16位的編碼空間。也就是每個字符占用2個字節。這樣理論上一共最多可以表示 216 個字符。基本滿足各種語言的使用。實際上目前版本的 Unicode 尚未填充滿這16位編碼,保留了大量空間作為特殊使用或將來擴展。
實現方式:Unicode 的實現方式不同于編碼方式。一個字符的 Unicode 編碼是確定的。但是在實際傳輸過程中,由于不同系統平臺的設計不一定一致,以及出于節省空間的目的,對 Unicode 編碼的實現方式有所不同。Unicode 的實現方式稱為Unicode轉換格式(Unicode Translation Format,簡稱為 UTF)。如,UTF-8 編碼,這是一種變長編碼,它將基本7位ASCII字符仍用7位編碼表示,占用一個字節(首位補0)。而遇到與其他 Unicode 字符混合的情況,將按一定算法轉換,每個字符使用1-3個字節編碼,并利用首位為0或1進行識別。
Java與C#語言都是采用Unicode編碼方式,在這兩種語言中定義一個字符,在內存中存放的就是這個字符的兩字節Unicode碼。如下所示:
char a='我'; => 內存中存放的Unicode碼為:25105
4.內碼的相互轉換
(1)vc中的實現方法
利用Windows系統提供的API:::MultiByteToWideChar和::WideCharToMultiByte
::MultiByteToWideChar:實現當前碼到Unicode碼的轉換;
::WideCharToMultiByte:實現Unicode碼到當前碼的轉換;
(2)Java中的實現方法
String vcString=new String(javaString.getBytes("UTF-8"),"gb2312");
java的編碼應該是UTF-8
(3)C#中的實現方法
??
四 vc中的MutiByte Charater Set 和 Wide Character Set
1.MultiByte Charater Set方式
這種方式以按字節為單位存放字符,即如果一個字符碼為兩字節,則在內存中占兩字節,字符碼為一字節,就占一字節。例如,字符串“中國abc”的編碼為:中(0xd6、0xd0)、國(0xb9、0xfa)、a(0x61)、b(0x62)、c(0x63)、\0(0x00),就存為如下方式:
對應的類型,方法有:
char、scanf、printf、cin、cout …
2.Wide Character Set
這種方式是以兩字節為單位存放字符,即如果一個字符碼為兩字節,則在內存中占四字節,字符碼為一字節,就占兩字節。例如,字符串“中國abc”就存為如下方式:
對應的類型,方法有:
wchar_t、wscanf、wprintf、wcin、wcout …
造成上面存儲方式的根本原因在于,wchar_t類型其實是一個unsigned short 類型。如,存儲上面字符串的數組的定義為:wchar_t buffer[8] 等價于unsigned short buffer[8].而所有以字母w開頭的方法也都是以unsigned short類型,即兩字節為單位來處理字符,因此,存儲在wchar_t類型數組中的字符串無法用cout顯示,只能用wcout方法來顯示。
由于Unicode碼也是采用兩個字節,因此Wide Character Set方式能夠很好的支持Unicode碼的存儲,但是在vc的環境下要將一個Unicode碼存入兩字節而不是四字節內存中,必須通過上面的API函數::MultiByteToWideChar。首先,將當前的編碼轉換為Unicode碼,然后,將每個字符的Unicode碼放入每一個wchar_t類型的變量中。以下是一個實例代碼:
char input[50];
cin>>input;
int size;
size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0);
if(size==0)
return -1;
wchar_t *widebuff=new wchar_t[size];
::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);
輸入:中國abc
Debug斷點調試:
size==6
數組widebuff[0-size]占12字節,存放了6個字符的Unicode碼,碼值為:
中(0x4e2d) 國(0x56fd) a(0x0061) b(0x0062) c(0x0063) d(0x0000)
這時,數組的大小size等于輸入的字符個數加上一個結束符,符合我們的想象。
五 引入問題的錯誤分析
(1) 沒有理解編譯器中的編碼方式
雖然vc/c++中漢字的編碼占兩個字節,但并不是Unicode碼,是GB2312碼。
(2) 沒有理解MutiByte Charater Set 和 Wide Character Set的存儲原則;
在vc/c++中,“中國”按char[5]來對待,而wchar_t a[3]實際上是三個unsigned short類型的變量,因此賦值時會越界。
//gameloft 筆試題
/*
1、RGB值轉灰度值對32位整數取R,G,B對應的8位并加權合成。
2、求一個字符串中出現頻率最高的字符。字符范圍并渦有說明,通常應
指ASCII字符集,可是當時考慮復雜了,于是想到了stl的map來做。
結果沒有寫完。就交了。
*/
#include<iostream>
using namespace std;
#define CHARNUM 256
//計算一個串最出現頻率最高的字符
char mostFreq(const char* str)
{
int freq[CHARNUM]= {0};
int firstPos[CHARNUM] = {0};
int pos = 0;
const char* p = str;
while( *p != '\0')
{
if(freq[*p] == 0)
{
firstPos[*p] = pos;
}
freq[*p++]++;
pos++;
}
int maxF = -1;
int ch = '\0';
for(int i = 1;i < 256;i++)
{
if( freq[i] > maxF)
{
ch = i;
maxF = freq[i];
}
if( freq[i] == maxF)
{
if( firstPos[i] < firstPos[ch])
{
ch = i;
}
}
}
cout<<" maxF ="<<maxF<<endl;
return (char)ch;
}
int main()
{
int* a[9][4][5];
int b = a[5] - a[3];
cout<<"b = "<<b<<endl;
int* c[3];
char * str = "aabyebbdfdf 1`5454545$$$#$#$2788kldef";
char ch;
ch = mostFreq( str);
cout<<"ch = " <<ch<<endl;
}
4.給出一個CThing 類的源代碼讓分析,其中有三個語句要求解釋語句作用。
一個填空,分析時有點忙了,應該一個函數一個函數的分析,或許會有清晰思路。
將各個類的名稱和功能整理下會理出些思路。
5、給出strcpy的源代碼讓說明其功能,并指出參數設置上只少一人錯誤
6、給出一個將整數i轉換為8進制的方法,要求對其進行改進。
src:
void count(int i, char* str)
{
map[
sorry, 記憶不清楚了
7、給幾個名詞讓解釋placement new,ARM, GCC, android, 還有一人??
8、英文解釋題目。第一個還好。第二個說游戲加速的
increment ...update frame , ??這詞詞認識,放一起讀不出來表示什么
意思
|