[C/C++] C語言切割字串函式 strsep,分析 URL GET 參數

今天來簡介 UNIX 內建的 strsep 函式,這在 Windows Dev-C++ 是沒有支援的,在寫 UNIX 分析字串常常需要利用到此函式,大家可以 man strsep 來看如何使用 strsep,假設我們要分析 URL Get 字串:user_command=appleboy&test=1&test2=2,就可以利用兩次 strsep 函式,將字串全部分離,取的個別的 name, value。strsep(stringp, delim) 第一個參數傳入需要分析的字串,第二個參數傳入 delim 符號,假設 stringp 為 NULL 字串,則函式會回傳 NULL,換句話說,strsep 會找到 stringp 字串第一個出現 delim 符號,並將其取代為 \0 符號,然後將 stringp 更新指向到 \0 符號的下一個字串,strsep() function 回傳原來的 stringp 指標。看上面文字敘述,好像不太瞭解,沒關係,底下是 UNIX strsep.c 的原始碼:
/*
 * Get next token from string *stringp, where tokens are possibly-empty
 * strings separated by characters from delim.
 *
 * Writes NULs into the string at *stringp to end tokens.
 * delim need not remain constant from call to call.
 * On return, *stringp points past the last NUL written (if there might
 * be further tokens), or is NULL (if there are definitely no more tokens).
 *
 * If *stringp is NULL, strsep returns NULL.
 */
char *
strsep(stringp, delim)
    char **stringp;
    const char *delim;
{
    char *s;
    const char *spanp;
    int c, sc;
    char *tok;

    if ((s = *stringp) == NULL)
        return (NULL);
    for (tok = s;;) {
        c = *s++;
        spanp = delim;
        do {
            if ((sc = *spanp++) == c) {
                if (c == 0)
                    s = NULL;
                else
                    s[-1] = 0;
                *stringp = s;
                return (tok);
            }
        } while (sc != 0);
    }
    /* NOTREACHED */
}
Continue reading “[C/C++] C語言切割字串函式 strsep,分析 URL GET 參數”

[jQuery] AjaxFileUpload : Multiple File Upload plugin

最近 survey 一些 AJAX upload plugin by jQuery,或者是一些網路知名 upload opensource: SWFUpload, 以及目前很強大的 Plupload,先來說明 AjaxFileUpload 這個 jQuery Plugin 單一檔案上傳,如果想要簡單方便的單一上傳,我很推薦這個,搭配回傳的 json type 吐出錯誤訊息還蠻好用的,雖然作者給單一上傳的說明,不過還是可以將它改成多檔上傳,也就是多增加 input type=”file” 就可以了,底下介紹一下怎麼實作單一檔案或者是多檔案上傳。

單一檔案上傳

先 include AjaxFileUpload javascript


html:
jQuery code:
function ajaxFileUpload()
{
	//這部份可以省略,或者是撰寫當 ajax 開始啟動需讀取圖片,完成之後移除圖片
	$("#loading")
	.ajaxStart(function(){
		$(this).show();
	})
	.ajaxComplete(function(){
		$(this).hide();
	});
	
  /*
    prepareing ajax file upload
    url: the url of script file handling the uploaded files
    fileElementId: the file type of input element id and it will be the index of  $_FILES Array()
    dataType: it support json, xml
    secureuri:use secure protocol
    success: call back function when the ajax complete
    error: callback function when the ajax failed
  */
	$.ajaxFileUpload
	(
		{
			url:'doajaxfileupload.php', 
			secureuri:false,
			fileElementId:'fileToUpload',
			dataType: 'json',
			success: function (data, status)
			{
				if(typeof(data.error) != 'undefined')
				{
					if(data.error != '')
					{
						alert(data.error);
					}else
					{
						alert(data.msg);
					}
				}
			},
			error: function (data, status, e)
			{
				alert(e);
			}
		}
	)
	
	return false;

}
注意 fileElementId 對應到 input file 裡面的 ID 值,取 name 是後端程式需要用到,例如 PHP $_FILES,後端處理回傳 json Type 給 jQuery 處理,json 格式:
{
  "error" : 'test',
  "msg" : 'upload completed'
}
這樣大致上ok了。如果要多檔案上傳,其實就是改 jQuery 部份:html 部份請加上多個 input file

多重檔案上傳

  
jQuery 部份改成:
  
  $().ready(function() {  
    $('#uploadfile').click(function(){      
      $('input:file').each(function(){		  
        $.ajaxFileUpload
    		(
    			{
    				url:'doajaxfileupload.php', 
    				secureuri:false,
    				fileElementId: $(this).attr('id'),
    				dataType: 'json',
    				success: function (data, status)
    				{
  						if(data.error != '')
  						{
  							alert(data.error);
  						}else
  						{
  							alert(data.msg);
  						}
    				},
    				error: function (data, status, e)
    				{
    					alert(e);
    				}
    			}
    		); 
     });
     
    });
  });
另外也可以參考 jQuery Plugin: jQuery Multiple File Upload Plugin v1.47

[CSS] IE 6, 7, 8 FireFox hack 支援透明背景圖 background or img javascript

先前在國外部落格發現一篇非常好用的教學:Quick Tip: How to Target IE6, IE7, and IE8 Uniquely with 4 Characters,裡面有提供一部教學影片,非常好用,也很實在,底下可以先看影片,看完大概就可以針對 IE, FireFox, Chrome 進行 CSS Hack。 目前網頁製作,要符合多瀏覽器跨平台(IE, Safari, Chrome, FireFox…等),就必須動到 CSS Hack,雖然 Google 已經宣稱不支援 IE6,但是很多單位,很多學校跟客戶都是使用 IE6 瀏覽器,不只國內這樣,國外大廠也都希望支援 IE 系列,包含 IE6, IE7, IE8,這時候就必須知道如何分別針對各種不同 IE 做設定,底下就來看看實做例子。 Continue reading “[CSS] IE 6, 7, 8 FireFox hack 支援透明背景圖 background or img javascript”

[C/C++] strpbrk 在字串中找尋指定的符號或字母

繼上一篇:『[C/C++] 切割字串函數:strtok, Network mac address 分割』,內容寫到 Microsoft 用到 strpbrk 來找尋字串中特定符號,並且回傳該符號的位址,用法如下:
#include "string.h"
#include "stdlib.h"
#include "stdio.h"

int main ()
{
  char str[] = "This is a sample string";
  char key[] = "aeiou";
  char * pch;
  printf ("Vowels in '%s': ",str);
  pch = strpbrk (str, key);
  while (pch != NULL)
  {
    printf ("%c " , *pch);
    /* 也可以直接輸出字串 */
    printf("\noutput=%s\n", pch);
    pch = strpbrk (pch+1,key);
  }
  printf ("\n");
  system("pause");
  return 0;
}
輸出結果: strpbrk 我們看一下 /usr/src/lib/libc/string/strpbrk.c 原始碼:
/*
 * Find the first occurrence in s1 of a character in s2 (excluding NUL).
 */
char *
strpbrk(s1, s2)
    const char *s1, *s2;
{
    const char *scanp;
    int c, sc;

    while ((c = *s1++) != 0) {
        for (scanp = s2; (sc = *scanp++) != 0;)
            if (sc == c)
                return ((char *)(s1 - 1));
    }
    return (NULL);
}
首先將指定字串(str),跟愈找尋的字串(key)方別帶入 s1, s2,當跑 while 迴圈時,會先去判斷是否到了字串最後一個字元,判斷是否為 NULL,如果不是,則進入 while 迴圈,在利用 for 迴圈去比對字串 key,其實都是利用 ASCII 轉換比對是否相同,如果相同,則回傳該指定字母之位址,回傳時還需要 s1 -1 呢?因為在 while 條件中已經將字串指到下一個字母位址,所以必需要在重新指回去前一字母。

[C/C++] 切割字串函數:strtok, Network mac address 分割

今天寫了 strtok 的範例:『如何分離網路 mac address』程式碼如下,大家一定會有疑問 strtok 第一次呼叫,第一參數輸入愈分離的字串,在 while 迴圈,則是輸入 NULL 呢?底下就來解析 strtok.c 的程式碼。
/*
*
* Author      : appleboy
* Date        : 2010.04.01
* Filename    : strtok.c
*
*/

#include "string.h"
#include "stdlib.h"
#include "stdio.h"

int main()
{
  char str[]="00:22:33:4B:55:5A";
  char *delim = ":";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok(str,delim);
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, delim);
  }      
  system("pause");
  return 0;
}
執行結果如下圖: strtok strtok.c 在 FreeBSD 7.1 Release 裡面路徑是 /usr/src/lib/libc/string/strtok.c,可以看到底下函式 __strtok_r
__strtok_r(char *s, const char *delim, char **last)
{
    char *spanp, *tok;
    int c, sc;

    if (s == NULL && (s = *last) == NULL)
        return (NULL);

    /*
     * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
     */
cont:
    c = *s++;
    for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
        if (c == sc)
            goto cont;
    }

    if (c == 0) {       /* no non-delimiter characters */
        *last = NULL;
        return (NULL);
    }
    tok = s - 1;

    /*
     * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
     * Note that delim must have one NUL; we stop if we see that, too.
     */
    for (;;) {
        c = *s++;
        spanp = (char *)delim;
        do {
            if ((sc = *spanp++) == c) {
                if (c == 0)
                    s = NULL;
                else
                    s[-1] = '\0';
                *last = s;
                return (tok);
            }
        } while (sc != 0);
    }
    /* NOTREACHED */
}
大家可以看到,在第一次執行 strtok 時候,會針對傳入s字串每一個字進行比對,c = *s++; 意思就是 c 先設定成 *s,這行執行結束之後,會將 *s 指標加1,也就是字母 T -> h 的意思,這地方必須注意,如果第一個字母符合 delim 分隔符號,就會執行 goto cont;,如果不是,則會將 tok 指標指向 s 字串第一個位址,再來跑 for 迴圈找出下一個分隔字串,將其字串設定成 \0 中斷點,回傳 tok 指標,並且將s字串初始值指向分隔字串的下一個位址。 接下來程式只要繼續執行 strtok(NULL, delim),程式就會依照上次所執行的 s 字串繼續比對下去,等到 *last 被指向 NULL 的時候就不會在執行 strtok 了,我相信這非常好懂,微軟 Visual Studio 有不同的寫法: https://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/strtok.c.htm
/* Copyright (c) Microsoft Corporation. All rights reserved. */

#include 

/* ISO/IEC 9899 7.11.5.8 strtok. DEPRECATED.
 * Split string into tokens, and return one at a time while retaining state
 * internally.
 *
 * WARNING: Only one set of state is held and this means that the
 * WARNING: function is not thread-safe nor safe for multiple uses within
 * WARNING: one thread.
 *
 * NOTE: No library may call this function.
 */

char * __cdecl strtok(char *s1, const char *delimit)
{
    static char *lastToken = NULL; /* UNSAFE SHARED STATE! */
    char *tmp;

    /* Skip leading delimiters if new string. */
    if ( s1 == NULL ) {
        s1 = lastToken;
        if (s1 == NULL)         /* End of story? */
            return NULL;
    } else {
        s1 += strspn(s1, delimit);
    }

    /* Find end of segment */
    tmp = strpbrk(s1, delimit);
    if (tmp) {
        /* Found another delimiter, split string and save state. */
        *tmp = '\0';
        lastToken = tmp + 1;
    } else {
        /* Last segment, remember that. */
        lastToken = NULL;
    }

    return s1;
}
微軟用了 strpbrk 來取代 for 迴圈的字串比對,但是整個流程是差不多的,大家可以參考看看,果然看 Code 長知識。