總網頁瀏覽量

2012年9月9日 星期日

Make file


Make file

基本說明
#include <stdio.h>
int main(void)
{
        printf("Hello World\n");
}
gcc hello.c  =>  產生a.out   輸入./a.out即可執行
gcc –c hello.c  =>  產生 hello.o 目的檔
gcc –o hello hello.o  =>  產生 hello 可執行檔  輸入./hello即可執行

-O:最佳化參數,-Wall:會產生詳細的編譯過程

gcc sin.c -lm -L/lib -L/usr/lib
-l :是『加入某個函式庫(library)』的意思,
 m :則是 libm.so 這個函式庫,其中, lib 與副檔名(.a .so)不需要寫
-L 後面接的路徑是剛剛上面那個函式庫的搜尋目錄
Linux 預設是將函式庫放置在 /lib /usr/lib 當中
-I/path 後面接的路徑( Path )就是設定要去搜尋相關的 include 檔案的目錄


製作Makefile
標的(target): 目標檔1 目標檔2
<tab>   gcc -o 欲建立的執行檔 目標檔1 目標檔2

main: main.o haha.o sin_value.o cos_value.o
           gcc -o main main.o haha.o sin_value.o cos_value.o -lm
clean:
           rm -f main main.o haha.o sin_value.o cos_value.o

LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
CFLAGS=-Wall
main: ${OBJS}
        gcc -o main ${OBJS} ${LIBS}
clean:
        rm -f main ${OBJS}

$@:代表目前的標的(target)
gcc -o main ${OBJS} ${LIBS} 可改為gcc -o $@ ${OBJS} ${LIBS}


MakeFile

#Filename MakeFile
#this file is used for show how to use makefile
$(info start workoing)
hello: hello.c
    echo “nothing”

hello.bin: hello.c
    @echo “now make hello.bin”
    gcc hello.c –o hello.bin

.PHONY: he
    @echo “now make he”
    gcc hello.c –o hello.bin

$是函數呼叫符號, info是一個函數名稱,作用是輸出一段資訊,類似的資訊輸出還有warningerror兩個函數,不過error函數執行後會終止執行並退出
.PHONY關鍵字用於宣告一個目標,被.PHONY宣告的目標將總是執行其指定的命令,而如果不宣告的話,則僅當目標後面的條件變動後才執行
命令前面的@符號的作用是,不顯示被執行的命令,因為預設情況下,Make解譯器在執行命令時會列印出執行的命令
對於hello.bin目標,是當hello.c檔案被修改後,將會執行gcc命令重新對該c檔案編譯,並輸出hello.bin檔案

執行腳本,執行以下命令
$make  –f  Makefile  hello

-f參數用於指定要執行的指令檔案名稱,如果不指定檔案名稱,則解譯器會自動從目前的目錄下尋找名稱為Makefile的指令檔案






2012年9月4日 星期二

JAVA常遇到疑問

3-2.6 == 0.4  =>為false
因為java使用基底型別進行浮點數計算時, 會不準確
3-2.6 為0.3999999999999

使用BigDecimal進行浮點數運算來解決

BigDecimal x = new BigDecimal("3");
BigDecimal x = new BigDecimal("2.6");
BigDecimal z = z.subtract(y);
double value = z.doubleValue();
System.out.println(value == 0.4);

                                                                                                                     

9/2 = 4
9/2.0 = 4.5
整數與浮點數的運算會轉為浮點數型態再進行運算

                                                                                                                     

使用Label與break

public static void main(String[] args){
    label:
        for(int i= 1; i <= 7; i++){
           System.out.print("TEST");
           if(i =  3)
                break label;
       }
}

當i = 3時, 就會跳出label, 使用雙重迴圈也是一樣的情形


java
clone()方法複製物件
當已經存在一個A物件,現在需要一個與A物件完全相同的B物件,並對B物件的屬性值進行修改,但是A物件原有的屬性值不能改變

使用Object類別中的clone()方法,可以用來完成物件的淺複製,即被複製的物件各個屬性都是基本型態,而不是參考型態的屬性(Example)






















JNI 記錄

Java call C

Step 1: Write the Java Code
建立HelloWorld.java
//HelloWorld.java
public class HelloWorld
{
    public native void showHelloWorld();
    static {
        System.loadLibrary("hello");//呼叫libhello.so
    }
                public static void main(String[] args){
                                new HelloWorld().showHelloWorld();
                }
}

Step 2: Compile the Java Code
執行javac HelloWorld.java //編譯

Step 3: Create the .h File (
這是自動產生出的不要去編輯)
javah -jni HelloWorld //自動產生對應C標頭檔,內容中粗體為C的函式宣告:
-d選項可以指定輸出路徑
-jni 表示產生jni標頭檔案

//hello.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    showHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_showHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Step 4: Write the Native Method Implementation
建立jni.c

//hello.c
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>

JNIEXPORT void JNICALL
Java_HelloWorld_showHelloworld(JNIEnv *env, jobject obj)
{
                printf("Hello world!\n");
                return;
}


Step 5: Create a Shared Library
執行
gcc -fPIC -shared -Ijni.h 目錄> -Ijni_md.h目錄> jni.c -o libjni.so




C call Java
C訪問java不能透過函數指標 只能透過通用的參數介面
需要把想要訪問的類別名 函數名稱 參數傳遞給java引擎

訪問Java中函數的流程:

1. 取得Java對象的類別
cls = env -> GetObjectClass(jobject)

2. 取得Java函數的id
jmethodId mid = env -> GetMethodId(cls, "method_name", "([Ljava/lang/String;)V");

第二個參數為Java中的函數名稱
第三個參數為Java函數的參數和返回值

Java提供javap工具 可以查看Java函數的輸入 返回參數
javap -s com/android/HelloWorld

-s的含義是簽名(Signature) 因為Java允許函數重載 所以不同的參數 返回值代表著不同的函數

3. 找到函數後 就可以使用該函數
env -> CallXXXMethod(jobject, mid, ret);

訪問Java中變數的流程:

1. cls = env -> GetObjectClass(jobject)

取得變數的id
2. jfieldId fid = env -> GetFiledId(cls, "filed_name", "I");

field_nameJava變數的名稱
第三個參數為變數的類型

3. 取得變數值
value = env -> GetXXXField(env, jobject, fid)





JNIEnv 表示Java環境, jobject 指向呼叫的物件
java: int, long, byte, boolean, char, short, float, double, object
c中表示類型前面加一個j來表示

jclass取得:   
jclass FindClass(const char*, clsName);
jclass GetObjectClass(jobject obj);
jclass GetSuperClass(jclass obj);

jclass cls_string = env -> FindClass("java/lang/String") 取得string類型方式

取得方法名:
GetFieldID/GetMethodID
GetStaticFieldID/GetStaticMethodID

Java類型
native類型
boolean
Z
byte
B
char
C
double
D
float
F
int
I
long
L
Object
‘L’+’package’+’;’
short
S

object ---> Ljava/lang/Sting;
Array ---> [Ljava/lang/object;



























2012年9月2日 星期日

Java版本 處理字幕檔

由於 java對中文的編碼有不同的格式, 處理字幕檔有些麻煩, 需先判斷編碼內容, 再去做處理, 輸出也不好處理, 最好找到一樣格式的srt檔案, 否則要先轉檔後再做擷取會比較好實作

程式內容:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;


public class Subtitle {
    public static void main(String []args)throws IOException{
        GetSubtitle mGetSubtitle = new GetSubtitle();
        mGetSubtitle.startOperation();
        mGetSubtitle.stopOperation();
    }
}

class GetSubtitle{
    public File fileEng;


        
    public File fileCht;
    public InputStreamReader readEng;
    public InputStreamReader readCht;
    
    public BufferedReader brEng;
    public BufferedReader brCht;
    public StringBuilder sbEng;
    public StringBuilder sbCht;
    public String strEng, strCht;
    
    GetSubtitle() throws IOException{
        initial();
    }

    public void initial() throws IOException{
        fileEng = new File("C:\\Documents and Settings\\kent\\eclipse_work\\Subtitle\\Mission.Impossible_eng.txt");
        fileCht = new File("C:\\Documents and Settings\\kent\\eclipse_work\\Subtitle\\Mission.Impossible_cht.txt");
        readEng = new InputStreamReader (new FileInputStream(fileEng),"utf-8");
        brEng = new BufferedReader(readEng);
    }
    
    public void startOperation() throws IOException{
        while((strEng = brEng.readLine()) != null ){
            if(strEng.contains(":")){
                repeatReadCht();
            }
        }
    }
    public void repeatReadCht() throws IOException{
        readCht = new InputStreamReader (new FileInputStream(fileCht),"utf-8");
        brCht = new BufferedReader(readCht);
        while((strCht = brCht.readLine()) != null){
            if(strEng.equals(strCht)){
                outputData();
                break;
            }
        }
    }
    public void outputData() throws IOException{
        while(strEng.length() != 0){
            if((strEng = brEng.readLine()) != null){
                System.out.print(strEng + " ");
            }else{
                break;
            }
        }
        System.out.print("\r\n");
        while(strCht.length() != 0 ){
            if((strCht = brCht.readLine()) != null){
                System.out.println(strCht);
            }else{
                break;
            }
        }
    }
    
    public void stopOperation() throws IOException{
        brEng.close();
        brCht.close();
    }
}




網路上判斷編碼的方法:

class Convert{
    Convert(){  
    }
    public String convertCodeAndGetText() {
        File file = new File("C:\\Documents and Settings\\kent\\eclipse_work\\Subtitle\\Avengers_cht.txt");
        BufferedReader reader;
        String text = "";
        try{
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream in = new BufferedInputStream(fis);
        in.mark(4);
        byte[] first3bytes = new byte[3];
        in.read(first3bytes);//找到文字檔的前三個字節並自動判斷文字檔類型
        in.reset();
        if(first3bytes[0] == (byte) 0xEF && first3bytes[1] == (byte) 0xBB && first3bytes[2] == (byte) 0xBF) {// utf-8
            reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
            System.out.println("utf-8");
        }else if(first3bytes[0] == (byte) 0xFF && first3bytes[1] == (byte) 0xFE) {
            reader = new BufferedReader(new InputStreamReader(in, "unicode"));
            System.out.println("unicode");
        }else if(first3bytes[0] == (byte) 0xFE && first3bytes[1] == (byte) 0xFF) {
            reader = new BufferedReader(new InputStreamReader(in,"utf-16be"));
            System.out.println("utf-16be");
        }else if(first3bytes[0] == (byte) 0xFF && first3bytes[1] == (byte) 0xFF) {
            reader = new BufferedReader(new InputStreamReader(in, "utf-16le"));
            System.out.println("utf-16le");
        }else{
            reader = new BufferedReader(new InputStreamReader(in, "GBK"));
            System.out.println("GBK");
        }
        String str = reader.readLine();
        while(str != null){
            text = text + str + "\n";
            str = reader.readLine();
        }
        reader.close();
        }catch(FileNotFoundException e) {
        e.printStackTrace();
        }catch(IOException e) {
                e.printStackTrace();
        }
        return text;
    }
}