2009-04-24 22:15

[C語言] 取得目錄名稱路徑(dirname)

dirname

#include <libgen.h>

int main(){
char W_path1[] = "E:\\test" ;
char W_path2[] = "E:\\Program\\clear\\ape-06\\Debug" ;
char W_path3[] = "E:\\Program\\clear\\.metadata\\.plugins\\org" ;

dirname(W_path1);
printf("%s\n",W_path1);
// E:\

dirname(W_path2);
printf("%s\n",W_path2);
// E:\Program\clear\ape-06

dirname(W_path3);
printf("%s\n",W_path3);
// E:\Program\clear\.metadata\.plugins

char L_path1[] = "/test" ;
char L_path2[] = "/Program/clear/ape-06/Debug" ;
char L_path3[] = "/Program/clear/.metadata/.plugins/org" ;

dirname(L_path1);
printf("%s\n",L_path1);
// /

dirname(L_path2);
printf("%s\n",L_path2);
// /Program/clear/ape-06

dirname(L_path3);
printf("%s\n",L_path3);
// /Program/clear/.metadata/.plugins


_getch();
return 0;
}



參考來源:
<libgen.h>
2009-04-24 21:44

[C語言] 遞迴掃瞄目錄下所有文件(dir_recursive)

opendir , readdir , closedir

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <dirent.h>


/* dir_recursive [遞迴掃瞄目錄下所有文件]
* 掃瞄 path 下所有的文件,並輸出至 output 的文件中
* output 必須為可寫入的文件
* */
int dir_recursive(char *path, FILE *output){
char glue='\\'; // Windows 的分隔符號
//char glue='/'; // Linux 的分隔符號

// 嘗試開啟目錄
DIR * dp = opendir(path);

if (!dp){
// 不是目錄,輸出至檔案
fprintf(output,"%s\n",path);
return 1;
}

struct dirent *filename;
while((filename=readdir(dp))){
// 跳過當前及母目錄
if(!strcmp(filename->d_name,"..") || !strcmp(filename->d_name,".")){
continue;
}

// 計算新的路徑字串所需的長度
int pathLength=strlen(path)+strlen(filename->d_name)+2;
// 產生新的陣列空間
char *pathStr = (char*)malloc(sizeof(char) * pathLength);
// 複製當前目錄路徑至新的陣列空間
strcpy(pathStr, path);

// 檢查目錄分隔符號
int i=strlen(pathStr);
if(pathStr[i-1]!=glue){
pathStr[i]=glue;
pathStr[i+1]='\0';
}

// 串接次目錄名稱或檔案名稱至新的陣列空間
strcat(pathStr, filename->d_name);

// 遞迴呼叫目錄掃瞄
dir_recursive(pathStr,output);

}

// 關閉目錄
closedir(dp);

return 1;
}



int main(){
// 建立輸出的文件檔
FILE *fileOut = fopen("output.txt", "w");

// 掃瞄 E:\test 下所有的文件
dir_recursive("E:\\test",fileOut);

return 0;
}



參考來源:
[原创]LINUX下用C语言历遍目录 C语言列出目录_小徐博客 学无止境 minix and linux
2009-04-24 20:09

[C語言] 字串相加(string_concat)

strlen , strcpy , strcat

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* string_concat [字串相加]
* 將 str1 與 str2 相加,並返回新的字串
* */
char *string_concat(char *str1, char *str2) {
// 計算所需的陣列長度
int length=strlen(str1)+strlen(str2)+1;

// 產生新的陣列空間
char *result = (char*)malloc(sizeof(char) * length);

// 複製第一個字串至新的陣列空間
strcpy(result, str1);
// 串接第二個字串至新的陣列空間
strcat(result, str2);

return result;
}


int main(){
char *a="123456";
char *b="abcde";
char *c=string_concat(a,b);
printf("%s\n",c);

_getch();
return 0;
}



參考來源:
Standard C String and Character [C++ Reference]
2009-04-24 19:10

[C語言] 檔案讀寫

fclose , feof , fopen , fprintf , fscanf , printf , remove , rename , rewind , scanf , ftell , fseek
#include <stdio.h>

int main(){
    FILE *fileIn;
    FILE *fileOut;

    fileIn = fopen("input.txt", "r");
    if(fileIn == NULL){printf("檔案不存在\n"); return 0;}

    fileOut = fopen("output.txt", "w");
    /* Mod:
    * "r" : 開啟檔案,以純文字方式[讀取]。
    * "w" : 開啟或建立檔案,以純文字方式[寫入],會複寫原先的資料。
    * "a" : 開啟或建立檔案,以純文字方式[寫入],並將檔案指標移到最後。
    * "rb" : 同 "r" 但以二進位(binary)方式[讀取]。
    * "wb" : 同 "w" 但以二進位(binary)方式[寫入]。
    * "ab" : 同 "a" 但以二進位(binary)方式[寫入]。
    * "r+" : 同 "r" 但同時具有[讀取/寫入]的權力
    * "w+" : 同 "w" 但同時具有[讀取/寫入]的權力
    * "a+" : 同 "a" 但同時具有[讀取/寫入]的權力
    * "rb+" : 同 "rb" 但同時具有[讀取/寫入]的權力
    * "wb+" : 同 "wb" 但同時具有[讀取/寫入]的權力
    * "ab+" : 同 "ab" 但同時具有[讀取/寫入]的權力。
    */


    int    a1;
    float  a2;
    char   a3;
    char   a4[100];

    while(!feof(fileIn)){// 當讀取結束時會回傳 true
        // 依格式讀取一列文字,所有的變數都要取址,除了字元陣列
        fscanf(fileIn,"%d %f %c %s",&a1,&a2,&a3,a4);

        // 依格式將資料輸出至螢幕上
        printf("%d %f %c %s\n",a1,a2,a3,a4);

        // 依格式寫入一列文字
        fprintf(fileOut,"%d %f %c %s\n",a1,a2,a3,a4);

        /* %c : 一個字元(char)格式
        * %s : 一個字串格式
        *
        * %i : 一個整數(int)格式
        * %d : 一個十進位整數(int)格式
        * %u : 一個十進位無符號整數(unsigned)格式
        *
        * %e, %f, %g : 一個浮點數(float)格式
        * %lf: 一個浮點數(double)格式
        *
        * %o : 八進位(02732)格式
        * %x : 十六進位(0x27fa)格式
        * %% : 跳脫成 %
        * */

    }

    // 輸出當前的檔案指標位址
    printf("offset = %ld\n", ftell(fileIn) );

    // 將檔案指標返回至最上面,失敗則回傳 0
    // 會清除錯誤並將 EOF 標示清除
    // 當需要重新讀取時可利用此函數
    rewind(fileIn);

    // 將移動檔案指標從開始處偏移 5 個字元,成功則回傳 0
    // 會將 EOF 標示清除
    fseek(fileIn,5,SEEK_SET);
    /* int fseek( FILE *stream, long offset, int origin );
    * stream : 檔案指標
    * offset : 偏移量,可為正負數
    * origin : 偏移的依據位址
    *   SEEK_SET 0  檔案起始位址
    *   SEEK_CUR  1  當前位址
    *   SEEK_END  2  檔案結束位址
    * */


    // 關閉檔案指標
    fclose(fileIn);
    fclose(fileOut);

    // 將檔案 "input.txt" 移除
    remove("input.txt");

    // 將 "output.txt" 的檔案名稱變更為 "input.txt"
    rename("output.txt","input.txt");


    // 按任意鍵結束
    _getch();
    return 0;
}



參考來源:
Standard C I/O [C++ Reference]
printf() 與 scanf()
2009-04-24 16:11

[C語言] 動態記憶體配置(malloc)

malloc , calloc , realloc , free

#include <stdlib.h>

int main(){

/*一維陣列*/
int size1=1000;
int *array1;

// 利用 malloc 配置空間 。
array1 = (int*) malloc(size1 * sizeof(int));

// 利用 calloc 配置空間,會初始為 0 。
array1 = (int*) calloc(size1 , sizeof(int));

// 利用 realloc 將原本的空間調整成兩倍,並且複製原本的內容,
// 但不保證是原本的空間位址。
array1 = (int*) realloc(array1, 2 * size1 * sizeof(int));


// 釋放記憶體空間。
free(array1);


/*二維陣列*/
int i;
int size_x=100;
int size_y=100;
int **array2;

// 利用 malloc 配置二維空間 。
array2 = (int**) malloc(size_x * sizeof(int*));
for (i=0; i<size_x; i++){
array2[i] = (int*) malloc(size_y * sizeof(int));
}


// 釋放記憶體空間
for (i=0; i<size_x; i++){
free(array2[i]);
}
free(array2);

return 0;
}


參考來源:
Standard C Memory [C++ Reference]
2009-04-24 12:31

Dos 下的目錄顯示(DIR)

顯示檔案清單以列出目錄中的檔案及子目錄。

DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/S] [/T[[:]timefield]] [/W] [/X] [/4]

[drive:][path][filename]
 指定要顯示的磁碟機、目錄或檔案。

/?顯示參數說明。

/A依照指定的檔案屬性來顯示檔案。
attributesD 目錄
R 唯讀檔
H 隱藏檔
A 保存檔
S 系統檔案
- 無意義

/B使用單純格式 (沒有標頭資訊或摘要)。

/C顯示檔案大小千位數分隔符號。這是預設值。 使用 /-C 來停用分隔符號的顯示。

/D與寬的列表格式相同,但是依照欄來排序。

/L使用小寫顯示。

/N使用新的長列表格式,檔名會顯示在最右方。

/O依照指定的排序順序來列出檔案。
sortorderN 依名稱 (英文字母)
S 依大小 (最小的在前)
E 依副檔名 (英文字母)
D 依照日期與時間 (日期較早的在前)
G 先列出子目錄 - 表示相反的順序

/P當資料填滿整個螢幕時暫停顯示。

/Q顯示檔案擁有者。

/S顯示指定目錄及所有子目錄中的檔案。

/T指定用來顯示或排序的時間欄位
timefieldC 建立
A 上次檔案存取時間
W 上次寫入檔案時間

/W使用寬的列表格式。

/X顯示對非 8.3 格式的檔案產生的短檔名。這個格式和 /N 相同,但是短檔名會插入在長檔名之前。 如果沒有長檔名存在,該處會顯示空白。

/4顯示四位數的年份

參數可能會在 DIRCMD 環境變數預先設定。您可以在任何參數使用連字號字首(-)來覆蓋預先的設定--例如: /-W。


操作範例:

# 列出所有 D:\test 下的檔案與目錄
DIR D:\test /S /B
# print:
# D:\test\001.jpg
# D:\test\002.jpg
# D:\test\003.jpg
# D:\test\pics
# D:\test\pics\001.jpg
# D:\test\pics\002.jpg


# 列出當前目錄下的檔案與目錄,並將結果輸出至 D:\test\dir.txt
DIR /S /B >D:\test\dir.txt

# 將列出的結果加入至 D:\test\dir.txt 檔案後面
DIR /S /B >>D:\test\dir.txt


# 找出 D:\test 下的副檔名為 jpg 的檔案
DIR D:\test /S /B |FIND /I ".jpg"
# print:
# D:\test\001.jpg
# D:\test\002.jpg
# D:\test\003.jpg
# D:\test\pics\001.jpg
# D:\test\pics\002.jpg
2009-04-23 20:51

PhotoShop 實用教學-動作與批次處理

在 PhotoShop 中有個很實用的功能,那就是動作紀錄與批次處理,可能你對這個軟體不是很熟悉,但這個功能可以方便你在處理大量圖片,我最喜歡的就是這個功能完全的客製化,只要你會的功能通通都可以錄製個人的批次處理,好處就是只要這套軟體就可以處理很多事。


PhotoShop 實用教學-動作與批次處理
廢話那麼多,我用一個為圖片加上個人標註的範例來說明好了。


PhotoShop 實用教學-動作與批次處理
首先開啟一個圖檔,並點選動作視窗。


PhotoShop 實用教學-動作與批次處理
按下動作視窗中的建立新增動作。


PhotoShop 實用教學-動作與批次處理
取一個適合的名稱,以免以後忘記當初做的事。
這裡還可以為此動作設立快捷鍵,在平時編輯圖片上也是蠻方便的。


PhotoShop 實用教學-動作與批次處理
這裡要注意錄製的按鈕是否按下,在一開始都會預設啟動,為了保險起見來是注意一下,以免等一下都白做了。


PhotoShop 實用教學-動作與批次處理
一開始先選取影像尺寸調整圖片的解析度,這也是最重要的事。
因為在不同的解析度下,編輯單位會大大的受影響,免得最後做出來的動作不通用,為了方便通用性,建議先規定圖片的大小跟解析度。


PhotoShop 實用教學-動作與批次處理
這裡建議固定寬度與高度,只調整圖片的解析度至網頁用的 72 dpi。


PhotoShop 實用教學-動作與批次處理
為產生上下所需要的高度,選擇調整版面尺寸。


PhotoShop 實用教學-動作與批次處理
以相對方式為上下各增加 30 px,這裡的高度就依個人需要而定了,沒有特別限制,最後會為寬高都增加至 40 px。


PhotoShop 實用教學-動作與批次處理
選擇文字工具。


PhotoShop 實用教學-動作與批次處理
這裡要特別注意,文字定位是採用 % 來計算的,盡可能讓文字的 X Y 值壓在最邊界上,為了通用性的考量,我想沒有人願意接受非預期的效果,所以這裡要特別注意。


PhotoShop 實用教學-動作與批次處理
你可以在動作紀錄中發現文字處理上所記錄的事項,這裡很明顯的看到文字的定位單位(%)。


PhotoShop 實用教學-動作與批次處理
再來選取版面尺寸增加剩下的高度與寬度。


PhotoShop 實用教學-動作與批次處理
為寬度增加 40 px 及高度 10 px。


PhotoShop 實用教學-動作與批次處理
最後做一的影像平面化。


PhotoShop 實用教學-動作與批次處理
最後點選停止紀錄。
到這裡動作的錄製就算完成了,你可以嘗試的按下旁邊的播放扭,就可以發覺剛剛錄製的效果了。


PhotoShop 實用教學-動作與批次處理
接下就要將錄製好的動作轉存批次處理的程序檔。
在上一個選項批次處理可以快速的將錄製的動作直接使用,但為了讓批次處理可以更方便,也為了讓這個動作可以好好的保存,我建議製作成程序檔,雖然程序檔不可以再改寫及察看。


PhotoShop 實用教學-動作與批次處理
選擇程序檔(.exe)要存放的位置,當然最好還是取一個好一點的名稱,要不然到時候又忘記是做什麼用的,那今天的努力又白費了。


PhotoShop 實用教學-動作與批次處理
選擇剛剛錄製好的動作,當然你也可以選擇其他預設的動作。


PhotoShop 實用教學-動作與批次處理
選擇儲存的方式,這裡我選擇直接覆蓋原始圖片的方式,當然也可以另存至其他目錄。
這裡要記得勾選上面兩個選項,『包括全部的次當案夾』可以讓選取目錄下所有的圖檔,都套用此批次處理,這樣在批次套用上會很方便,『抑制色彩描述警告』如果你不想再批次處理的過程中,一直點選討厭的對話匡的話,最好勾選此選項。


PhotoShop 實用教學-動作與批次處理
你可以利用文件管理,將圖檔或目錄拖放至程序上,接下來就會套用批次處理中動作記錄。


當然也可以使用命令列去執行套用的動作,建議使用目錄當作參數,在處理大量圖片的時候會比較簡短。

E:\>著作權標示.exe E:\photo-test\001.jpg E:\photo-test\002.jpg

E:\>著作權標示.exe E:\photo-test\ss
2009-04-17 20:10

利用 switch 該善程式碼的閱讀性

一個簡單的網頁 Script 架構,不外乎一個進入點及一個輸出點,由上到下一個很單純的流程。

在資料驗證上也是一個接一個,但卻數量多的時候,卻會讓整體流程看起來很複雜,很不直覺。

一個基本 switch 的撰寫方法,用在代替有結構的 IF 時還蠻放便的。

<?php
switch ($_GET['type']) {
// 當 $_GET['type']=="apple" 時進入程式片段
case "apple":
//程式片段...
break;

// 當 $_GET['type']=="bar" 時進入程式片段
case "bar":
//程式片段...
break;

// 當以上都不符合,預設進入程式片段
default :
//程式片段...
break;
}
?>


這個例子,將判斷式移到 case 上,讓原本的 switch 更加彈性,但這不是主要目的,在 switch 裡主要的好處是可以利用 break 跳出流程,這樣的用法跟 function 很像,利用跳出的方式結束剩下的程序,在區塊中檢查到錯誤的數入參數時,直接丟出訊息並讓輸出程序去處理顯示的問題。

<?php
switch (true){
case ($_GET['type']=='view'):
//其他判斷或動作...
break;

case ($_GET['action']=='delete'):
//其他判斷或動作...
break;

case ($_GET['action']=='add'):
//標題檢查
$title=trim($_GET['title']);/*去除頭尾空白*/
$title=htmlspecialchars($title,ENT_QUOTES);/*HTML 跳脫*/
$title=mb_substr($title, 0, 100);/*100字剪裁*/
if(!$title){ //利用 if 判斷,錯誤則跳出 switch
// 列出錯誤訊息
break;
}

//訊息檢查
$msg=trim($_GET['msg']);/*去除頭尾空白*/
$msg=htmlspecialchars($msg,ENT_QUOTES);/*HTML 跳脫*/
$msg=mb_substr($msg, 0, 1000);/*1000字剪裁*/
if(!$msg)){ //利用 if 判斷,錯誤則跳出 switch
// 列出錯誤訊息
break;
}

//其他判斷或動作...
break;

default :
// 列出錯誤訊息
break;
}
?>


再看看如果用 IF 去處理輸入驗證時,必須將所有資料先做處理,後面再一個一個去判斷,在閱讀上很不直覺,如果中間有大量的輸入參數要處理時,會讓人找很久。

<?php
if($_GET['type']=='view'){
//其他判斷或動作...

}elseif($_GET['action']=='delete'){
//其他判斷或動作...

}elseif($_GET['action']=='add'){
//標題檢查
$title=trim($_GET['title']);/*去除頭尾空白*/
$title=htmlspecialchars($title,ENT_QUOTES);/*HTML 跳脫*/
$title = mb_substr($title, 0, 100);/*100字剪裁*/

//訊息檢查
$msg=trim($_GET['msg']);/*去除頭尾空白*/
$msg=htmlspecialchars($msg,ENT_QUOTES);/*HTML 跳脫*/
$msg = mb_substr($msg, 0, 1000);/*1000字剪裁*/

if(!$title){
// 列出錯誤訊息
}elseif(!$msg){
// 列出錯誤訊息
}else{
//其他判斷或動作...
}

break;
}else{
// 列出錯誤訊息
}
?>


參考來源:
PHP: switch - Manual