2013年10月17日 星期四

[JavaScript] trim函數大賞


W3C那幫人的腦袋被驢踢了,直到javascript1.8.1才支持trim函數(與trimLeft,trimRight),可惜現在只有firefox3.5支持。由於去除字符串兩邊的空白實在太常用,各大類庫都有它的影子。加之,外國人都很有研究精神,搞鼓了相當多實現。

實現1

 String.prototype.trim = function() {
  return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
} 
看起來不怎麼樣,動用了兩次正則替換,實際速度非常驚人,主要得益於瀏覽器的內部優化。一個著名的例子字符串拼接,直接相加比用Array做成的StringBuffer還快。 base2類庫使用這種實現。

實現2

 String.prototype.trim = function() {
  return this.replace(/^\s+/, '').replace(/\s+$/, '');
} 
和實現1很相似,但稍慢一點,主要原因是它最先是假設至少存在一個空白符。 Prototype.js使用這種實現,不過其名字為strip,因為Prototype的方法都是力求與Ruby同名。

實現3

 String.prototype.trim = function() {
  return this.substring(Math.max(this.search(/\S/), 0),this.search(/\S\s*$/) + 1);
} 
以截取方式取得空白部分(當然允許中間存在空白符),總共調用了四個原生方法。設計得非常巧妙,substring以兩個數字作為參數。 Math.max以兩個數字作參數,search則返回一個數字。速度比上面兩個慢一點,但比下面大多數都快。

實現4

 String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g, '');
} 
這個可以稱得上實現2的簡化版,就是利用候選操作符連接兩個正則。但這樣做就失去了瀏覽器優化的機會,比不上實現3。由於看來很優雅,許多類庫都使用它,如JQuery與mootools

實現5

 String.prototype.trim = function() {
  var str = this;
  str = str.match(/\S+(?:\s+\S+)*/);
  return str ? str[0] : '';
} 
match是返回一個數組,因此原字符串符合要求的部分就成為它的元素。為了防止字符串中間的空白符被排除,我們需要動用到非捕獲性分組(?:exp)。由於數組可能為空,我們在後面還要做進一步的判定。好像瀏覽器在處理分組上比較無力,一個字慢。所以不要迷信正則,雖然它基本上是萬能的。

實現6

 String.prototype.trim = function() {
  return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, '$1');
} 
把符合要求的部分提供出來,放到一個空字符串中。不過效率很差,尤其是在IE6中。

實現7

 String.prototype.trim = function() {
  return this.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, '$1');
} 
和實現6很相似,但用了非捕獲分組進行了優點,性能效之有一點點提升。

實現8

 String.prototype.trim = function() {
  return this.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
} 
沿著上面兩個的思路進行改進,動用了非捕獲分組與字符集合,用?頂替了*,效果非常驚人。尤其在IE6中,可以用瘋狂來形容這次性能的提升,直接秒殺火狐。

實現9

 String.prototype.trim = function() {
  return this.replace(/^\s*([\S\s]*?)\s*$/, '$1');
} 
這次是用懶惰匹配頂替非捕獲分組,在火狐中得到改善,IE沒有上次那麼瘋狂。

實現10

 String.prototype.trim = function() {
  var str = this,
  whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
  for (var i = 0,len = str.length; i < len; i++) {
    if (whitespace.indexOf(str.charAt(i)) === -1) {
      str = str.substring(i);
      break;
    }
  }
  for (i = str.length - 1; i >= 0; i--) {
    if (whitespace.indexOf(str.charAt(i)) === -1) {
      str = str.substring(0, i + 1);
      break;
    }
  }
  return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
} 
我只想說,搞出這個的人已經不是用牛來形容,已是神一樣的級別。它先是把可能的空白符全部列出來,在第一次遍歷中砍掉前面的空白,第二次砍掉後面的空白。全過程只用了indexOf與substring這個專門為處理字符串而生的原生方法,沒有使用到正則。速度快得驚人,估計直逼上內部的二進制實現,並且在IE與火狐(其他瀏覽器當然也毫無疑問)都有良好的表現。速度都是零毫秒級別的。

實現11

 String.prototype.trim = function() {
  var str = this,
  str = str.replace(/^\s+/, '');
  for (var i = str.length - 1; i >= 0; i--) {
    if (/\S/.test(str.charAt(i))) {
      str = str.substring(0, i + 1);
      break;
    }
  }
  return str;
} 
實現10已經告訴我們普通的原生字符串截取方法是遠勝於正則替換,雖然是複雜一點。但只要正則不過於復雜,我們就可以利用瀏覽器對正則的優化,改善程序執行效率,如實現8在IE的表現。我想通常不會有人在項目中應用實現10,因為那個whitespace實現太長太難記了(當然如果你在打造一個類庫,它絕對是首先)。實現11可謂其改進版,前面部分的空白由正則替換負責砍掉,後面用原生方法處理,效果不遜於原版,但速度都是非常逆天。

實現12

 String.prototype.trim = function() {
  var str = this,
  str = str.replace(/^\s\s*/, ''),
  ws = /\s/,
  i = str.length;
  while (ws.test(str.charAt(--i)));
  return str.slice(0, i + 1);
} 
實現10與實現11在寫法上更好的改進版,注意說的不是性能速度,而是易記與使用上。和它的兩個前輩都是零毫秒級別的,以後就用這個來工作與嚇人。
下面是老外給出的比較結果,執行背景是對Magna Carta 這文章(超過27,600字符)進行trim操作。
實現Firefox 2IE 6
trim115ms< 0.5ms
trim231ms< 0.5ms
trim346ms31ms
trim447ms46ms
trim5156ms1656ms
trim6172ms2406ms
trim7172ms1640ms
trim8281ms< 0.5ms
trim9125ms78ms
trim10< 0.5ms< 0.5ms
trim11< 0.5ms< 0.5ms
trim12< 0.5ms< 0.5ms
原文鏈接:http://blog.stevenlevithan.com/archives/faster-trim-javascript

2013年7月31日 星期三

[C#] String常用技巧整理(IndexOf、LastIndexOf、Substring、Split)


String.IndexOf

String.IndexOf 方法 (Char, Int32, Int32)
報告指定字符在此範例中的第一個匹配項的索引。搜索從指定字符位置開始,並檢查指定數量的字符位置。
String.IndexOf(value, startIndex, count)

參數
value:要查找的 Unicode 字符。
startIndex:搜索起始位置。
count:要檢查的字符位置數。
返回值(Int32):
如果找到該字符,則為value 的索引位置;否則如果未找到,則為-1。

範例:
string str = "深圳市盈基實業有限公司國際通鄧事文*深圳市盈基實業有限公司國際通鄧事文";
Label1.Text = str.IndexOf("中國").ToString();//返回-1
Label1.Text = str.IndexOf("盈基").ToString();//返回3
Label1.Text = str.IndexOf("盈基",10).ToString();//返回21 說明:這是從第10個字符開始查起。
Label1.Text = str.IndexOf("鄧",15,10).ToString();//返回-1
Label1.Text = str.IndexOf("鄧",15,20).ToString();//返回-32 說明:從第15個字符開始查找,
要查找的範圍是從第15個字符開始後20個字符,即從第15-35個字符中查找。

<---------------------------------------------------------------------------------------------------------->

String.LastIndexOf

String.LastIndexOf 方法
報告指定的Unicode 字符或String 在此實例中的最後一個匹配項的索引位置。


名稱 說明
String.LastIndexOf (Char)報告指定Unicode 字符在此實​​例中的最後一個匹配項的索引位置。
String.LastIndexOf (String)報告指定的String 在此實例內的最後一個匹配項的索引位置。
String.LastIndexOf (Char, Int32)報告指定Unicode 字符在此實​​例中的最後一個匹配項的索引位置。該搜索從指定字符位置開始。
String.LastIndexOf (String, Int32)報告指定的String 在此實例內的最後一個匹配項的索引位置。該搜索從指定字符位置開始。
String.LastIndexOf (String, StringComparison)報告指定字符串在當前String 對像中最後一個匹配項的索引。一個參數指定要用於指定字符串的搜索類型。
String.LastIndexOf (Char, Int32, Int32)報告指定的Unicode 字符在此實​​例內的子字符串中的最後一個匹配項的索引位置。搜索從指定字符位置開始,並檢查指定數量的字符位置。
String.LastIndexOf (String, Int32, Int32)報告指定的String 在此實例內的最後一個匹配項的索引位置。搜索從指定字符位置開始,並檢查指定數量的字符位置。
String.LastIndexOf (String, Int32, StringComparison)報告指定字符串在當前String 對像中最後一個匹配項的索引。參數指定當前字符串中的起始搜索位置,以及要用於指定字符串的搜索類型。
String.LastIndexOf (String, Int32, Int32, 
StringComparison)
報告指定的String 對像在此實例內的最後一個匹配項的索引位置。參數指定當前字符串中的起始搜索位置、要搜索的當前字符串中的字符數量,以及要用於指定字符串的搜索類型。



範例:
string str = "深圳市盈基實業有限公司國際通鄧事文*深圳市盈基實業有限公司國際通鄧事文";
Label1.Text = str.LastIndexOf("鄧文").ToString();//返回-1
Label1.Text = str.LastIndexOf("鄧").ToString();//返回32

Label1.Text = str.LastIndexOf("鄧",8).ToString();//返回-1
Label1.Text = str.LastIndexOf("鄧",20).ToString();//返回14
Label1.Text = str.LastIndexOf("鄧",33).ToString();//返回32
說明:在指定的範圍內查找字符,這個範圍是上面的輸入的參數,
理解為,從索引0開始到指定的數值位置範圍內查找最後一個匹配的的字符串的位置。示例中,0-8中沒有“鄧”字,
所以返回-1,0-20範圍中,有一個“鄧”字在索引14位置上,0-33範圍中有兩個“鄧”字,
因為LastIndexOf是返回最後一個匹配項索引位置,所以返32,而不是14。

PS : IndexOf、LastIndexOf都是返回一個位置,是個整數值;找不到都返回-1;
IndexOf是從左向右查,LastIndexOf是從右向左查,不管是IndexOf還是LastIndexOf,
索引序列都是從左到右的(起始值是0)
<---------------------------------------------------------------------------------------------------------->
String.Substring

String.Substring 方法
從此實例檢索子字符串。
名稱 說明
String.Substring (Int32) 從此實例檢索子字符串。子字符串從指定的字符位置開始。
String.Substring (Int32, Int32) 從此實例檢索子字符串。子字符串從指定的字符位置開始且具有指定的長度。

示例:
string str = "深圳市盈基實業有限公司國際通鄧事文*深圳市盈基實業有限公司國際通鄧事文";
Label1.Text = str.Substring(11);//返回“國際通鄧事文*深圳市盈基實業有限公司國際通鄧事文”
Label1.Text = str.Substring(11,7);//返回“國際通鄧事文*”

<---------------------------------------------------------------------------------------------------------->

String.Split



1,用字符串分隔:


using System.Text.RegularExpressions;

string str="aaajsbbbjsccc";

string[] sArray=Regex.Split(str,"js",RegexOptions.IgnoreCase);

foreach (string i in sArray) Response.Write(i.ToString() + "<br>");


輸出結果:
aaa
bbb
ccc

2,用多個字符來分隔:


string str="aaajbbbscccjdddseee";

string[] sArray=str.Split(new char[2]{'j','s'});

foreach(string i in sArray) Response.Write(i.ToString() + "<br>");


輸出結果:
aaa
bbb
ccc
ddd
eee

3,用單個字符來分隔:

字符串str=“aaajbbbjccc”;

字符串[] sArray= str.Split(“J”);

的foreach(字符串sArray我)回复於(i.ToString()+“ - ”);

輸出結果:
aaa
bbb
ccc

轉自:http://a-jau.blogspot.tw/2012/01/cstringindexoflastindexofsubstringsplit.html

2013年5月6日 星期一

[JavaScript] 傳說中的 parseInt('08')

轉自:http://audi.tw/Blog/JavaScript/javascript.parseInt.asp
原文發布時間:6/3 08' 


眾所周知,parseInt() 是用來把字串轉換成整數的函式,一般來說,只要是數字開頭的字串,都能夠轉換成功,例如 parseInt('123a') 的結果為 123,parseInt('12 34') 的結果為12。
關於 parseInt() 有個著名的情況,有些人稱為臭蟲,讓各位自己來評斷。

parseInt('01') 得出的結果是1,事實上,一直到 07 為止,都能得到預期結果,問題來了,parseInt('08') 和 parseInt('09') 這兩者運算的結果,都得到0,這是為什麼呢?

主要原因在於 parseInt() 這個函式,本身可以傳遞兩個參數,語法是:
parseInt(string, radix)
第一個參數 string 當然是要轉換為數字的字串,第二個參數 radix 則是要用二進位、還是八進位或十六進位,又或是最熟悉的十進位來解譯這個字串呢?

也就是說,如果 parseInt('FF',16),代表以 16 進位方式來解析FF這個字串,當然得到的結果就是 255 了,同理,parseInt('FF',10) 以 10 進位來解析FF這個字串,根本就不是數字,所以得到的結果會是 NaN。

但大多數人不會特別指定第二個參數,這時 JavaScript 就自動判斷第一個傳遞的參數是否為某種數字型式。

在 JavaScript 眼中,以 0x 開頭的字串,都視為十六進位字串,如果單單是0開頭,第二個字母不是 x,則視為八進位或二進位字串,
十六進位使用的字母計有 0-9,A-F,而八進位使用的字母則為 0-7,所以,當發生parseInt('08') 又未指定以何種數值型態解析時,JavaScript 以 0 為起頭,接下來的字母又不是 x,那一定是八進位了,但是,八進位裡,怎麼可能有 8 和 9 這兩個字母呢?所以,一定是不合法的字串,於是就傳回 0。

同理,parseInt('010') 回傳的值,也不是 10,而是 8,因為 parseInt() 認為 0 開頭,接下來的字母不是 x,而是 1,就以二進位來解析 010 這個字串,所以一切問題都在於以 0 開頭,所造成的誤會。

最好的解決辦法,就是別偷懶,把第二個參數也加進去,例如 parseInt('08',10)、parseInt('010',10),那就萬無一失了!

2013年4月23日 星期二

「許功蓋」的問題

節錄自http://203.64.20.7/lifetype126/index.php?op=ViewArticle&articleId=15


許功蓋是何許人? 令人頭疼的傢伙
  有人說中國人像一盤散沙,不但不團結又愛搞分化,無論在學校、公司、部隊或社會,小圈圈或小山頭林立,想要中立者很難不被人貼上標籤,一旦被歸類到哪個派系時禍福難料。台海兩岸不就是最明顯的例子,上一代的鬥爭,下一代繼續鬥,非要弄得大家頭破血流為止。
實體和虛擬都在搞分裂
  在電腦的領域裡也一樣,中文字分裂成兩大類;你有你的一套而我也自成一派,現實生活玩分裂遊戲到虛擬世界還在搞,真令老外們百思不得其解?

  常摸電腦的人都知道,台灣和香港這邊號稱自由地區的人,雖然人少卻依然堅持正統的繁體字,統領著五湖四海華人文化界,其精神多麼地偉大呀!這派中文字型編碼以"大五碼(BIG5)"為首。對岸的大陸同胞在文革前,早開始「破四舊、立四新」,所謂的四舊是:“舊思想、舊文化、舊風俗、舊習慣”這些八股東西通通要拋掉,要改革就改的徹底,繁體自筆畫多太麻煩,不符合新的標準。而四新就是指相對應的:「新思想、新文化、新風俗、新習慣」,因此,以後電腦的中文環境都受此意識型態影響,奇怪得是既然統一寫簡體中文,後來簡體中文的編碼又搞出三這種不同派系:「GB18030、GB2312及HZ」,看來中國人真是與眾不同的民族。

  相同地,自由地區的台灣及香港雖同樣都使用大五碼來號令中文字型,妙就妙在我老廣講的粵語要維持我原來語意的精神,又多增加些令台灣人看了莫宰羊的港仔字型,於是,中文字和西方文字一字一位元組的單純性更顯得複雜難懂,英美語系的ASCII Code全球通行無障礙,這也難怪啦!電腦本來就是西方所發明出來的呀!

  相形之下,台灣也單純得多,幾乎人人全用大五碼,可是,如今不是都在全球化,台灣不能搞鎖國,文字總要交流,一有交流網絡一旦離開台灣島後,問題及麻煩也跟著來了。撇開亂碼的問題不談,因為這是先天不良所致沒辦法改變,然而,麻煩的事並不侷限在簡繁中文字的轉換上,就算在台灣普遍使用大五碼環境,一樣會有後天失調的問題出現。

大名鼎鼎的許功蓋

  無論是許功蓋或是許蓋功其實只是本尊與分身的差別不同,意思是在電腦世界裡都代表一個相同問題,我想只要曾經用過"PHP+MySQL"架站過的人,幾乎是無人不知無人不曉這頭疼的傢伙,且絕對是這些架站人心中永遠的痛。仔細探究原因,你會發現,錯的人其實不該是許功蓋,而是通稱大五碼的BIG5碼,關於大五碼的歷史傳說眾說紛紜,無一定論。我們並不評論當初編碼的對錯與是非,對這歷史有興趣的讀者不妨到google搜尋"BIG5″,相信可以找到一堆資料。

  既然大五碼聽來似乎有些問題,為何目前幾乎所有的繁體中文卻又都採用此一編碼呢?在西元1983-1984年間,個人電腦正在台灣逐漸推廣,電腦上的套裝軟體也開始盛行,為了解決電腦處理中文的問題,因而制定一套中文內碼,也就是我們通稱的"BIG5碼",又稱大五碼。而經歷過這段時間的人,一定不會忘記當初倚天中文的行銷手法,在國外軟體廠商開始引進原版軟體觀念的當時,倚天中文卻反其道而行,允許校園甚至一般使用者無條件且免費複製其中文系統,因此,讓倚天中文在當時幾乎成為中文的標準,也由於倚天中文正是採用BIG5編碼,嚴格說來,也就是BIG5碼為何一直沿用到現今的主要原因了。

大五碼錯在哪裡?

  錯在編碼時沒有把美國標準資訊交換碼 ASCII(American Standard Code for Information Interchange)的控制碼摒除在外,凡是唸過計算機概論的人都知道ASCII是以位元組(byte)為單位,又1 byte=8 bits,所以ASCII最多可以編2^8=256個字元,對於只有26個字母的英文語系國家來說已綽綽有餘,但對於有幾萬字的中文絕對不夠,因此必須用兩個byte來代表一個中文字,如"中"字的編碼即是"A4A4″。然而,BIG5碼設計時為了避免與ASCII衝突,每個中文字的第一個byte僅使用 ASCII裡的高字元(129-255),但在第二個byte卻用到了部分低字元(1-128),這正是BIG5碼在日後應用上造成極大不便的最大幫兇了。

BIG5不只找php麻煩,連UNIX都倖免於難

  7C 是 ASCII 裡的 pipe ‘|’ 用過 UNIX的人應該知道它是作什麼的,舉一個簡單的例子,如果你用 FTP 上傳一個 “四.doc” 的檔名到 UNIX 作業系統 ,傳完後立刻變成 “北.doc’,我想有太多人碰過這種經驗,原因無他,中文字 “四” 的 BIG5 碼是"A57C",當 UNIX 看到 7C 時會覺得莫名其妙,上傳一個 “|” 給我做什麼?於是就自己處理掉了…

  因此,你可以想像只要是中文字第二個byte是 “7C” 的,保證也都難逃BIG5的魔掌。

許功蓋的解決之道

  一、去除程式裡出現問題那段程式碼裡的STRIPSLASHES函數,如此,除了顯示"許蓋功"時可能變成"許蓋功"之外,似乎也沒太大的問題,但是,MySQL Server的隱碼及跳脫字元問題還是存在的。

  二、使用big5_func字串處理函數集

  當你決定使用big5_func來處理時,就必須將mysql的charset也一併改為BIG5,切記千萬不可讓許、功、蓋等字放在要插入資料字串的最後面。還有一個比較嚴重的問題是,變更charset是必須重新編譯mysql的,也就是說如果你是已經運作正常的主機,必須重新安裝MySQL Server並加入 charset=big5 的參數,若如果你是租用的虛擬主機,那問題就會變得更為複雜,因為主機供應商通常不會特別因為你要使用big5_func的函數而重新去編譯他們的資料庫系統。

  幸虧得是網絡上資源浩瀚無窮,可以搜尋繁體中文OSC版本,僅針對MySQL的charset為latin1的一些修正資料。由於BIG5所造成的問題幾乎無所不在,筆者認為除非BIG5有一個完整的補救計劃,否則許功蓋將會一直困擾著所有用PHP+MySQL架站的人,相信網絡上許多熱心的高手可以來解決BIG5的問題。或者,省得這麼多的麻煩乾脆全部改採萬國碼(Unicode),值得高興的是MySQL終於從善如流接受雙字元,自 v4.1版 以上已經支援 UTF-8 編碼了,真是可喜可賀,造福華人世界呀!

附錄:
BIG5碼中容易衝碼的文字:
(請注意看你的內文是否用到了下列的字:)

ASCII(5C) == “”
A45C么 AE5C娉 B85C稞 C25C擺 A55C功
AF5C珮 B95C鈾 C35C黠 A65C吒 B05C豹
BA5C暝 C45C孀 A75C吭 B15C崤 BB5C蓋
C55C髏 A85C沔 B25C淚 BC5C墦 C65C躡
A95C坼 B35C許 BD5C穀 AA5C歿 B45C廄
BE5C閱 AB5C俞 B55C琵 BF5C璞 AC5C枯
B65C跚 C05C餐 AD5C苒 B75C愧 C15C縷
ASCII(7C) == “|”
AA7C泜 B47C揉 A87C育 BE7C魯 B27C琍
BC7C慝 C67C鸛 A97C尚 B37C逖 BD7C罵
A77C坑 B17C悴 BB7C誡 C57C疊 A67C帆
B07C院 BA7C漏 C47C辮 AB7C咽 B57C稅
BF7C糕 AC7C洱 B67C閏 C07C嚐 AD7C迢
B77C會 C17C舉 A47C弋 AE7C徑 B87C腮
C27C甕 A57C四 AF7C砝 B97C頌 C37C牘

2013年3月27日 星期三

XP無法進入系統,一直重開機


1.首先準備好原版XP光碟(不要用網路上人家重新包裝、整合過的)
2.以光碟開機,如同系統安裝
3.選擇r,修復系統
4.進入DOS後,輸入CHKDSK(檢查系統磁碟)
5.檢查完出現錯誤訊息
6.再次輸入
CHKDSK /r
7.等100%後及修復完成,重新開機。