2015年10月25日 星期日

[C筆記]Linux底下實作fork()

前言:一個程式執行時只能夠執行一個動作,必須要生出其他執行序才能夠平行執行


 code:


main.c


補充 pid_t 是整數沒錯 但是再不同的環境下無法保證fork()傳回來的是64位元的整數還是32位  元 所以盡量以宣告pid_t類別來存pid

補充2 fork出來的子行程pid為0 if(!pid) ,在c裡  !0 ==true

fork原理生出一個跟自己一樣的程式碼差在於pid不同

另外補充execl("201502/hello","201502/hello","aa",NULL)

路徑是以自己當下為準 ,而不是程式碼位子為準


hello.c (只是拿來執行exec)





2015年9月20日 星期日

[C筆記]系統呼叫exec()

作用:在程式中呼叫其他程式來運作,將目前行程交託給下一個程式,exec()將行程交託後,原程式將不再繼續運作。


sample code:



main.c


#include <unistd.h>//exec()的宣告
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>//errno的宣告

int main(int argc, char* argv[])
{
    char *my_env[] ={"FOOD=coffee",NULL}; //環境變數name=value 並且用NULL告知程式最後項目
    if(execle("./coffee","./coffee","donuts",NULL,my_env)==-1)//如果有找到coffee.exe就會跳去執行coffee.exe 
    {
      fprintf(stderr,"cant run:%s\n",strerror(errno));//strerror(errno)為錯誤訊息種類
      return -1;
                                                              }
                                                         
    return 0;    
    
    }


coffee.c


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

int main(int argc,char* argv[])
{
    char *w = getenv("EXTRA");
    if(!w)
       w=getenv("FOOD");   //getenv("FOOD")抓取環境變數的值coffee
    if(!w)
       w = argv[argc -1];
     char *c = getenv("EXTRA");
     if(!c)
      c= argv[argc -1];//讀取argv[1]
      printf("%s with %s\n",c,w);
      
    return 0;
    }
    
    

補充:1

參照execle("./coffee","./coffee","donuts",NULL,my_env)
argc =2         argv[0] ="./coffee"     argv[1]="donuts"


補充:2

exec種類

execl 接受引數串列

execv接受引數陣列

execl p 根據 路徑尋找程式

execl pe 使用環境字串的陣列

補充:3

errno 為錯誤編號 
strerror(錯誤編號)回傳字串告知何種錯誤

補充:4

 if(execle("./coffee","./coffee","donuts",NULL,my_env)==-1)
系統呼叫出問題時通常回傳-1 (但不總是-1)

執行結果





2015年8月30日 星期日

[C筆記]系統呼叫system()

前言: C語言幾乎仰賴著作業系統,system call 存在於核心,是C與OS溝通             的橋梁。


system()使用範例遇到的問題:

我嘗試了無數次cmd指令  echo %s %s >> reports.log
最後發現在我的%s裡面存在著\n換行字元導致我一直只有echo出前面的%s
剛好fgets這方法尾巴會加上換行字元 以及now()的回傳字串也有

sample code:


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

char* now()
{
      time_t t;
      time(&t);
      return asctime(localtime(&t));//結尾會自動加上\n導致echo指令出錯
      }
      
      int main()
      {
          
          char comment[80];
          char cmd[120]; 
          fgets(comment,80,stdin); //fgets結尾會自動加上\n導致echo指令出錯
          if(comment[strlen(comment)-1] =='\n')
             comment[strlen(comment)-1] ='\0';//將\n用字串結尾取代
 
            char x[strlen(now())];
            int i;
            for(i=0;i<strlen(now());i++)
            {
              x[i]= *(now()+i); //*now存在記憶體的實字字串(不能修改)所以先丟到陣列進行修改
                                        }
          if(x[strlen(x)-4]=='\n')
             x[strlen(x)-4]='\0';
   
          sprintf(cmd,"echo %s %s >> reports.log",x,comment);
          system(cmd);
          return 0;
          }

輸出結果



          

2015年7月24日 星期五

[java筆記]連結mysql



sample code


 public void start(Stage stage) throws ClassNotFoundException, SQLException {
     
         Class.forName("com.mysql.jdbc.Driver"); //jdbc驅動先載入 要加入mysql-connector-java-5.1.15-bin.jar不然會出錯
         String url = "jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=Big5";//我的資料庫url
        try {
           conn = DriverManager.getConnection(url,"root","1234");//帳號密碼
        } catch (SQLException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);//例外處理
        }
        Statement stmt = null;
        try {
            stmt = conn.createStatement();
            ResultSet result = stmt.executeQuery("SELECT * FROM qq WHERE name LIKE '%aa%'"); //qq               是資料表名子 name是欄位
            while (result.next()) { // ResultSet 為"集合" 一定要配合迴圈使用!
            String Name = result.getString("name");//在這裡我找到了2筆一筆內容 aa 另一筆內容 bbaabb
           
             }
        } catch (SQLException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }finally {
        if (stmt != null) { stmt.close(); }//關閉  Statement
    }

    }

我的資料庫介紹


程式碼執行記錄

我利用中斷點來看每一圈收到的值

第一圈找到 aa!!

第二圈找到 bbaabb!!


另外補充
當妳想確認SQL語法是否正確
可以在http://localhost/phpMyAdmin/ 測試






結果呢(這代表法語法正確)
可以直接回上一頁複製語法
貼近去java 這行裡面
      ResultSet result = stmt.executeQuery("SELECT * FROM qq WHERE name LIKE '%aa%'");




2015年7月19日 星期日

[C筆記]靜態程式庫(共用.h檔與共用.o檔)

前言:之前有提過為了不寫出臃腫不堪的程式碼,我們應該講每個功能(方法)分散寫到不同的.c檔(利用.h檔來共用方法),這裡記錄該如何在gcc下將不同目錄的.h及.o連結到一起!


main.c檔案的位置


checksum.h檔案位置


encrypt.h檔案位置



checksum.o及encrypt.o的位置


main.c code


#include <stdio.h>
#include <stdlib.h>
#include "encrypt.h"
#include "checksum.h"

int main(int argc, char *argv[])
{
  char s[]="speak sumthing";
  encrypt(s);
  printf("encrypt is %s\n",s);
  printf("checksum is %i\n",checksum(s));
  
   encrypt(s);
  printf("encrypt is %s\n",s);
  printf("checksum is %i\n",checksum(s));

  return 0;
}

checksum.c code


#include "checksum.h"

int checksum(char *s)
{
    int sum =0;
    while(*s)
    {
      sum= sum +*s;
      s++;
      }
      return sum;
 }

encrypt.c code


#include "encrypt.h"

void encrypt(char *s)
{
     while(*s)
     {
              *s=*s^31;
              s++;
      }
     
 }


gcc指令 與 執行結果



-I 告知.h檔的位置(folder  folder2  2個位置都存在.h檔)
-o檔直接告知my_object_file/encrypt.o
                        my_object_file/checksum.o



將.o收集到收藏檔(.a檔)裡面

建立收藏檔指令 ar rcs libfilename.a  file1.o file2.o <----要收藏的.o檔

建立.a檔開頭一定要lib

執行gcc main.c -L . -lfilename -o try 

-L .  <---注意 當收藏檔放在自己的目錄下一定要用-L告知 .當下目錄的意思


此範例用.a檔實作:


題外話在linux底下gcc指令  有關路徑的話必須先加上/

例如-I /folder    -L/where

2015年7月11日 星期六

[C筆記]彈性可變式函式

前言:這裡想做一個有彈性函式,彈性的意思是我想要在函式輸入參數的部分,不想限制使用者輸入固定的參數數量,例如 printf("%i%i%i%i%i%i%i%i%i",1,2,3,4,5,6,7,8,9),這個常用的輸出方法不並沒有限制使用者只能輸出幾個參數。


提醒:
#include <stdarg.h> 使用裡面的
類別 va_list                   //記錄使用者輸入的所有參數
方法 va_start(ap,args) //告訴程式從哪個參數之後才開始抓
方法 va_arg(ap,int)      //拿回使用者的參數  並且必須告知使用者參數的類別方法va_end(ap)            //結束參數串列


sample code:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void total(int args,char *x, ...)
{
     va_list ap;
     va_start(ap,x); //從x 參數之後才開始抓參數
     int i;
     for(i=0;i<args;i++)
     {
       printf("%i\n",va_arg(ap,int));                                        
     }
     va_end(ap);
}

int main(int argc, char *argv[])
{
  total(4,"after_char_*x",4,3,2,1);//不算"after_char_*x",只輸出4個參數

  system("PAUSE");   return 0;
}

輸出結果



2015年7月9日 星期四

[C筆記]函式指標陣列配合enum當陣列索引值

前言:函式本身就是指標,這裡利用宣告指標陣列來將函式放進陣列裡,利用迴圈將函式通通跑一遍(優點是程式碼看起來精簡,容易擴充其他函式)。

通常會先去判斷enum item
if(enum item ==??)

{  

 再決定要帶入哪一個函式   但是這樣寫未免太複雜

}

...

...

...

...

if(enum item ==??)

{   

每新增一個函式   就外加一段 if 寫下來造成程式的冗長,容易混亂!!

}

這裡利用下列方法改良! 

enum item{AFUNCTION,BFUNCTION,CFUNCTION,DFUNCTION,NEWFUNCTION};  

enum可當索引值AFUNCTION=0,BFUNCTION=1,CFUNCTION=2,DFUNCTION=3

response r[] ={{"chou", AFUNCTION},{"yi", BFUNCTION},{"ming", CFUNCTION},{"pig",DFUNCTION},{"new", NEWFUNCTION}}; 

function[r[i].type](r[i]);  //這行不變


smaple code:

#include <stdio.h>
#include <stdlib.h>
 enum item{AFUNCTION,BFUNCTION,CFUNCTION,DFUNCTION};
//enum 設定 symbol AFUNCTION=0,BFUNCTION=1,CFUNCTION=2,DFUNCTION=3
 typedef struct{
         char *name;
         enum item type;
         }response;
void afunction(response r)
 {
      printf("%s\n",r.name);
      }
       
 void bfunction(response r)
 {
      printf("%s\n",r.name);
      }
       
 void cfunction(response r)
 {
      printf("%s\n",r.name);
      }
       
 void dfunction(response r)
 {
      printf("%s\n",r.name);
      }
int main(int argc, char *argv[])
{
  response r[] ={{"chou",AFUNCTION},{"yi",BFUNCTION},{"ming",CFUNCTION},{"pig",DFUNCTION}};
  
  void (*function[])(response) ={afunction,bfunction,cfunction,dfunction};
//將函釋放入 函式指標陣列裡!
  int i;
  for(i=0;i<4;i++)
  {
   function[r[i].type](r[i]);  
                  } 
  system("PAUSE");
  return 0;
}

執行結果: