2017年6月12日月曜日

クイックソートをコーディング

Basic からC言語に移り始めた頃、quick sort に出会い、その速さとシンプルな構造に感動したものである。真のプログラマとはこのようなコードを意図も簡単に次々と書かなければいけないのかと思い、プログラマには絶対になれないと思ったりもした。しかし、その後、職業でであうコードでこのようなコードにであうことはなかった。



その仕組みを知っている現在、ふと、自分でコードを書いてみようと思った。書き終わったあと wiki などに掲載されたいるコードと比較してみると、若干無駄があることに気づいた。また、データを分割する際の中央値の選び方が、大事であることも改めて認識することとなった。



1.perl でクイックソート

#! /usr/bin/perl

for($i=0;$i<100000;$i++) {
    push(@LIST,100000-$i);
}

#&pr();
&qsort(\@LIST,0,scalar(@LIST)-1);
#&pr();

sub mid3 {
  my($x,$y,$z) = @_;

  if ($x < $y) {
    if ($y < $z) {return($y);} elsif ($z < $x) {return($x);} else {return($z);}
  } 
  else {
    if ($z < $y) {return($y);} elsif ($x < $z) {return($x);} else {return($z);}
  }
}

sub qsort {
  my($LIST,$s,$e) =@_;

#  my($target) = $$LIST[$s];
  my($target) = $$LIST[$s + int(($e-$s)/2)];
#  my($target) = &mid3($$LIST[$s],$$LIST[int($s + ($e - $s)/2)],$$LIST[$e]);
  my($sp)     = $s;
  my($ep)     = $e;

  while(1) {
    while($$LIST[$sp]<$target && ($sp+1)<$ep) {
      $sp++;
    }
    while($$LIST[$ep]>=$target && ($sp+1)<$ep) {
      $ep--;
    }
    if ($$LIST[$sp]>$$LIST[$ep]) {
      my($tmp)    = $$LIST[$ep];
      $$LIST[$ep] = $$LIST[$sp];
      $$LIST[$sp] = $tmp;
    }
    if (($sp+1) == $ep) {
      last;
    }
  }

  if ($sp - $s > 0) {
    &qsort($LIST,$s,$sp);
  }

  if ($e - $ep > 0) {
    &qsort($LIST,$ep,$e);
  }
}

sub pr {
  printf("========\n");
  foreach $no (@LIST) {
    printf("%d\n",$no);
  }
}

2.ruby でクイックソート

#! /usr/bin/ruby

def pr(list)
  printf("======================\n")
  list.each do |no|
     printf("%d\n", no)
  end
end

def mid3(x,y,z)
  if (x < y) then
    if (y < z) then return(y) elsif (z < x) then return(x) else return(z) end
  else 
    if (z < y) then return(y) elsif (x < z) then return(x) else return(z) end
  end
end

def sort(list,s,e)
#  target = list[s]
  target = list[s + (e-s)/2]
#  target = mid3(list[s],list[s + (e-s)/2],list[e])
  sp     = s
  ep     = e

  while true do
    while list[sp] < target && sp+1 < ep do
      sp += 1
    end
    
    while list[ep] >= target && sp+1 < ep do
      ep -= 1
    end

    if (list[sp] > list[ep])
      tmp      = list[ep]
      list[ep] = list[sp]
      list[sp] = tmp
    end

    if (sp + 1 == ep)
      break
    end
  end

  if ((sp - s) > 0)
    sort(list,s,sp)
  end
  if ((e - ep) > 0)
    sort(list,ep,e)
  end
end

#list = [ 10,9,8,7,6,5,4,3,2,1 ]
list = []
for no in 1..100000 do
  list.push(100000-no)
end

#pr(list)
sort(list,0,list.length-1)
#pr(list)

3.python でクイックソート

#! /usr/bin/python
import sys

def pr(list):
  print "============"
  for no in list:
    print no

def mid3(x,y,z):
  if (x < y):
    if (y < z):
      return(y)
    elif (z < x):
      return(x)
    else:
      return(z)
  else:
    if (z < y):
      return(y)
    elif (x < z):
      return(x)
    else:
      return(z)
    
def sort(list,s,e):
#  target = list[s]
  target = list[s+(e-s)/2]
#  target = mid3(list[s],list[s + (e-s)/2],list[e])
  sp     = s
  ep     = e

  while 1:
    while list[sp] < target and sp + 1 < ep:
        sp += 1

    while list[ep] >= target and sp + 1 < ep:
        ep -= 1

    if list[sp] > list[ep]:
      tmp      = list[ep]
      list[ep] = list[sp]
      list[sp] = tmp

    if sp + 1 == ep:
      break

  if sp - s > 0:
    sort(list,s,sp)

  if e - ep > 0:
    sort(list,ep,e)
    

#list = [ 10,9,8,7,6,5,4,3,2,1 ]

list = []
for no in range(0, 100000):
  list.append(100000-no)

#pr(list)
#sys.setrecursionlimit(10000)
sort(list,0,len(list)-1)
#pr(list)

4.lisp でクイックソート

#! /usr/bin/clisp

(defun pr(list max)
  (format t "============~%")
  (dotimes (no max)
    (format t "~A~%" (aref list no))))

(defun mid3(x y z)
  (if (< x y)
      (cond
       ((< y z) y)
       ((< z x) x)
       (t z))
    (cond
     ((< z y) y)
     ((< x z) x)
     (t z))))

(defun mysort(list s e)
;;  (setq target (elt list s))
    (setq target (aref list (+ s (floor (/ (- e s) 2)))))
;;  (setq target (mid3 (aref list s) (aref list (+ s (floor (/ (- e s) 2)))) (aref list e)))
  (setq sp     s)
  (setq ep     e)

  (loop
   (loop
    (if (and (< (aref list sp) target) (< (+ sp 1) ep))
 (setq sp (+ sp 1))
      (return)))
   (loop
    (if (and (>= (aref list ep) target) (< (+ sp 1) ep))
 (setq ep (- ep 1))
      (return)))

   (if (> (aref list sp) (aref list ep))
       (progn
  (setf tmp (aref list ep))
  (setf (aref list ep) (aref list sp))
  (setf (aref list sp) tmp)))

   (if (= (+ sp 1) ep)
       (progn
  (return))))

  (if (> (- sp s) 0)
      (progn
 (mysort list s sp)))

  (if (> (- e ep) 0)
      (progn
 (mysort list ep e))))

(setq max 100000)
(setq list (make-array max))
(dotimes (no max)
  (setf (aref list no) (- max no)))

;;(pr list max)
(mysort list 0 (- (length list) 1))
;;(pr list max)

5.java でクイックソート

import java.io.*;
import java.util.*;

class sort {
  void pr(List<Integer>list) {
    System.out.printf("======\n");
      for(int no:list) {
        System.out.printf("%d\n",no);
      }
  }
    
  int mid3(int x, int y, int z) {
    if (x < y) {
      if (y < z) return y; else if (z < x) return x; else return z;
    } else {
      if (z < y) return y; else if (x < z) return x; else return z;
    }
  }

  void sort(List<Integer>list,int s,int e) {
    // int target = list.get(s);o
    int target = list.get(s+(e-s)/2);
    // int target = mid3(list.get(s),list.get(s + (e-s)/2),list.get(e));
    int sp     = s;
    int ep     = e;

    while(true) {
      while(list.get(sp) < target && sp + 1 < ep) {
        sp++;
      }
      while(list.get(ep) >= target && sp + 1 < ep) {
        ep--;
      }
      if (list.get(sp) > list.get(ep)) {
        int tmp = list.get(ep);
        list.set(ep,list.get(sp));
        list.set(sp,tmp);
      }
      if (sp + 1 == ep) {
        break;
      }
    }
    if (sp - s > 0) {
      sort(list,s,sp);
    }
    if (e - ep > 0) {
      sort(list,ep,e);
    }
  }
    
  public static void main(String args[]) {
    List<Integer>list = new ArrayList<Integer>();
    for(int i=0;i<100000;i++) {
      list.add(100000-i);
    }
    sort obj = new sort();
    // obj.pr(list);
    obj.sort(list,0,list.size()-1);
    // obj.pr(list);
  }
}

6.C でクイックソート

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

void
pr(int *list,int max)
{
  int i = 0;

  printf("========\n");
  for(i=0;i<max;i++) {
    printf("%d\n",list[i]);
  }
}

int
mid3(int x, int y, int z) {
    if (x < y) {
        if (y < z) return y; else if (z < x) return x; else return z;
    } else {
        if (z < y) return y; else if (x < z) return x; else return z;
    }
}

void
sort(int *list,int s,int e)
{
  // int target = list[s];
  int target = list[s+(e-s)/2];
  // int target = mid3(list[s], list[s + (e - s) / 2], list[e]); 
  int sp     = s;
  int ep     = e;

  
  while(1) {
    while(list[sp]<target && sp+1 < ep) {
      sp++;
    }
    while(list[ep]>=target && sp+1 < ep) {
      ep--;
    }
    if (list[sp]>list[ep]) {
      int tmp = list[ep];
      list[ep] = list[sp];
      list[sp] = tmp;
    }

    if (sp + 1 == ep) break;
  }
  if(sp - s > 0) {
    sort(list,s,sp);
  }
  if(e - ep > 0) {
    sort(list,ep,e);
  }
}

int
main(int argc,char *argv[])
{
  int max = 100000;
  int i = 0;
  int *list = calloc(sizeof(int),max);

  for(i=0;i<max;i++) {
    list[i] = max - i;
  }

  //  pr(list,max);
  sort(list,0,max-1);
  // pr(list,max);
}

7.速度比較

=== perl ===

real    0m0.408s
user    0m0.384s
sys     0m0.004s

=== ruby ===

real    0m0.201s
user    0m0.192s
sys     0m0.008s

=== python ===

real    0m0.301s
user    0m0.296s
sys     0m0.004s

=== clisp ===

real    0m4.362s
user    0m4.200s
sys     0m0.152s

=== java ===

real    0m0.288s
user    0m0.396s
sys     0m0.048s

=== C ===

real    0m0.014s
user    0m0.012s
sys     0m0.000s

2017年4月16日日曜日

分割数指定でファイル分割

ファイルを決まった個数に分割したいことはあるが、分割数を指定して分けるコマンドが見当たらず困ることがある。



例えば25行のファイルを8分割したい場合など、split で3行分割指定では3×8+1 の9分割となり、4行分割指定では4×6+1の7分割となり微妙に困る。そんな時、自前で分割数指定でわけるコマンドを持っていると楽できるかもしれない。



1.shellで分割

#! /bin/sh

if [ "$#" != 3 ]
then
    echo "Usage : split2.sh divisor input base"
    exit 1
fi

divisor=$1
input=$2
base=$3

c_start=0
c_end=0
quotient=0
toomach=0
total=0
part=0

total=`wc -l < $input`
quotient=`expr $total / $divisor`
toomuch=`expr $total % $divisor`

divisor=`expr $divisor - 1`
#printf "%d %d %d\n" $total $qutient $toomuch

for no in `seq 0 $divisor`
do
    if [ $no -lt $toomuch ]
    then
        c_start=`expr $c_end + 1`
        c_end=`expr $c_start + $quotient`
    else
        c_start=`expr $c_end + 1`
        c_end=`expr $c_start + $quotient - 1`
    fi
    file=`printf "%s%02d" $base $no`
    cmd=`echo "$cmd -e '$c_start,$c_end w $file'"`

    cnt=`expr $c_end - $c_start + 1`
    printf "Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n" `expr $no + 1` $c_start $c_end $cnt
done

sh -c "sed -n $cmd $input"

2.perlで分割

#! /usr/bin/perl

if (scalar(@ARGV) != 3) {
  printf(STDERR "Usage : split2.pl divisor input base\n");
  exit(1);
}

$divisor  = shift(@ARGV);
$input    = shift(@ARGV);
$base     = shift(@ARGV);

$c_start  = 0;
$c_end    = 0;
$quotient = 0;
$toomach  = 0; 
$total    = 0; 
$part     = 0; 

if (!open(FD,$input)) {
  printf(STDERR "Can't open file[%s]\n",$input);
  exit(1);
}
while(<FD>) {$total++}
close(FD);

$quotient = int($total / $divisor);
$toomuch  = int($total % $divisor);

foreach $no (0..($divisor-1)) {
  my($file) = sprintf("%s%02d",$base,$no);
  if (!open(${$file},">$file")) {
    printf(STDERR "Can't open file[%s]\n",$file);
    exit(1);
  }
}

if (!open(FD,$input)) {
  printf(STDERR "Can't open file[%s]\n",$input);
  exit(1);
}
my($cnt) = 0;
while(<FD>) {
  $cnt++;
  if ($cnt > $c_end) {
    if($part < $toomuch)  {
      $c_start = $c_end + 1;
      $c_end   = $c_start + $quotient;
    }
    else {
      $c_start = $c_end + 1;
      $c_end   = $c_start + $quotient - 1;
    }
    printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
           $part + 1,$c_start,$c_end,$c_end - $c_start + 1); 
    $part++;
  }
  my($file) = sprintf("%s%02d",$base,$part-1);
  printf({${$file}} "%s",$_);
}

close(FD);

foreach $no (0..($divisor-1)) {
  my($file) = sprintf("%s%02d",$base,$no);
  close(${$file});
}


3.rubyで分割

#! /usr/bin/ruby

if (ARGV.length != 3)
  printf("Usage : split2.rb divisor input base\n")
  exit(1)
end

divisor  = ARGV[0].to_i
input    = ARGV[1]
base     = ARGV[2]

c_start  = 0
c_end    = 0
quotient = 0
toomuch  = 0
total    = 0
part     = 0
fplist   = []

f = File.open(input,"r");
f.each_line do |line|
  total += 1
end
f.close()

divisor.times do |no|
  fplist[no] = open("%s%02d"%[base,no],"w")  
end

quotient = (total / divisor).to_i
toomuch  = (total % divisor).to_i

cnt = 0
f = File.open(input,"r");
f.each_line do |line|
  cnt += 1
  if (cnt > c_end)
    if (part < toomuch) 
      c_start = c_end + 1
      c_end   = c_start + quotient
    else
      c_start = c_end + 1
      c_end   = c_start + quotient - 1
    end
    printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
           part + 1,c_start,c_end,c_end - c_start + 1)
    part += 1
  end
  fplist[part-1].printf("%s",line)
end
f.close()

divisor.times do |no|
  fplist[no].close
end

4.pythonで分割

#! /usr/bin/python

import sys

if len(sys.argv) != 4:
  print "Usage : split2.py divisor input base"
  sys.exit(1)

divisor  = int(sys.argv[1])
input    = sys.argv[2]
base     = sys.argv[3]

c_start  = 0
c_end    = 0
quotient = 0
toomuch  = 0
total    = 0
part     = 0
fplist   = []

f = open(input,"r")
for line in f:
  total += 1
f.close()

quotient = total / divisor
toomuch  = total % divisor

for no in range(0, divisor):
  f = open("%s%02d"%(base,no),"w")
  fplist.append(f)

cnt = 0
f = open(input,"r")
for line in f:
  cnt += 1
  if cnt > c_end:
    if part < toomuch:
      c_start = c_end + 1
      c_end   = c_start + quotient
    else:
      c_start = c_end + 1
      c_end   = c_start + quotient - 1
    print "Part[%d] Start[%08d] End[%08d] Cnt[%08d]" \
          %(part+1,c_start,c_end,c_end - c_start + 1)
    part += 1
  fplist[part-1].write("%s"%line)
f.close()

for out in fplist:
  out.close()

5.lispで分割

#! /usr/bin/clisp

(if (not (equal (length *args*) 3))
    (progn
      (format t "Usage split.lisp divisor input base")
      (exit 1)))

(setq divisor (parse-integer (car *args*)))
(setq input   (car (cdr *args*)))
(setq base    (caddr *args*))

(setq c_start  0)
(setq c_end    0)
(setq total    0)
(setq quotient 0)
(setq toomuch  0)
(setq part     0)
(setq fplist  '())

(let ((in (open input :direction :input)))
  (loop for line = (read-line in nil)
 while line do (setq total (+ total 1)))
  (close in))

(setq quotient (floor (/ total divisor)))
(setq toomuch  (floor (mod total divisor)))

;;
(dotimes (no divisor)
  (let ((out (open (format nil "~A~2,'0D" base no) :direction :output)))
    (push out fplist)))
;;    (format t "~A~2,'0D~%" base no)))
(nreverse fplist)

(let
    ((in (open input :direction :input))
     (cnt 0)
     (line ""))
  (loop
   (setq line (read-line in nil))
   (if (null line)
       (quit))
   (setq cnt (+ cnt 1))
   (if (> cnt c_end)
       (progn
  (if (< part toomuch)
      (progn
        (setq c_start (+ c_end 1))
        (setq c_end   (+ c_start quotient)))
    (progn
      (setq c_start (+ c_end 1))
      (setq c_end   (+ c_start quotient -1))))
  (setq part (+ part 1))
  (format t "Part[~D] Start[~8,'0D] End[~8,'0D] Cnt[~8,'0D]~%"
   part c_start c_end (+ (- c_end c_start) 1))))
   (format (elt fplist (- part 1)) "~A~%" line))
   (close in))
;;
(dotimes (no divisor)
  (close (pop fplist)))

6.javaで分割

import java.io.*;
import java.util.*;

class split2 {
  void split(int divisor, String input, String base) throws Exception {
    BufferedReader br = null;
    List<PrintWriter>fplist = null;
    String line = "";
    int total = 0;
    int c_start = 0;
    int c_end = 0;
    int part = 0;
    int quotient = 0;
    int toomuch = 0;
    int cnt =0;

    br = new BufferedReader(new FileReader(input));
    while((line=br.readLine())!=null) {
      total++;
    }
    br.close();

    fplist = new ArrayList<PrintWriter>();
    for(int no=0;no<divisor;no++) {
      String file = String.format("%s%02d",base,no);
      PrintWriter pw = new PrintWriter(
                           new BufferedWriter(new FileWriter(file)));
      fplist.add(pw);
    }

    quotient = total / divisor;
    toomuch  = total % divisor;

    cnt = 0;
    br = new BufferedReader(new FileReader(input));
    while((line=br.readLine())!=null) {
      cnt++;
      if (cnt > c_end) {
        if (part < toomuch) {
          c_start = c_end + 1;
          c_end   = c_start + quotient;
        } 
        else {
          c_start = c_end + 1;
          c_end   = c_start + quotient - 1;
        }
        System.out.printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
                          part+1,c_start,c_end,c_end-c_start+1);
        part++;
      }
      fplist.get(part-1).printf("%s\n",line);
    }
    br.close();

    for(int no=0;no<divisor;no++) {
      fplist.get(no).close();
    }
  } 
  
  public static void main(String args[]) throws Exception {
    if (args.length != 3) {
      System.out.printf("Usage : split2 divisor input base\n");
      System.exit(1);
    }

    int    divisor = Integer.parseInt(args[0]);
    String input   = args[1];
    String base    = args[2];

    split2 obj = new split2();
    obj.split(divisor,input,base);
  }
}

7.C言語で分割

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

int
split(int divisor, char *input, char *base)
{
    FILE **fplist   = NULL;
    FILE  *fp       = NULL;
    int    c_start  = 0;
    int    c_end    = 0;
    int    quotient = 0;
    int    toomuch  = 0;
    int    total    = 0;
    int    part     = 0;
    int    cnt      = 0;
    int    no       = 0;
    char   buf[2048];

    fplist = calloc(sizeof(FILE *),divisor);
    if (!fplist) {
        fprintf(stderr,"calloc error!\n");
        return(1);
    }

    fp = fopen(input,"r");
    if (!fp) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }
    while(fgets(buf, sizeof(buf), fp)) {
        total++;
    }
    if (fclose(fp)) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }

    quotient = total / divisor;
    toomuch  = total % divisor;

    for(no=0;no<divisor;no++) {
        char file[128];
        sprintf(file,"%s%02d",base,no);
        fp = fopen(file,"w");
        if (!fp) {
            fprintf(stderr,"Can't open file[%s]\n",file);
            return(1);
        }
        fplist[no] = fp;
    }

    fp = fopen(input,"r");
    if (!fp) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }
    cnt = 0;
    while(fgets(buf, sizeof(buf), fp)) {
        cnt++;
        if (cnt > c_end) {
            if (part < toomuch) {
                c_start = c_end + 1;
                c_end   = c_start + quotient;
            }
            else {
                c_start = c_end + 1;
                c_end   = c_start + quotient - 1;
            }
            printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
                   part+1, c_start, c_end, c_end-c_start+1);
            part++;
        }
        if (!fprintf(fplist[part-1],"%s",buf)) {
            fprintf(stderr,"part [%d] write error\n",part);
            return(1);
        }
    }
    if (fclose(fp)) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }
    
    for(no=0;no<divisor;no++) {
        char file[128];
        sprintf(file,"%s%02d",base,no);
        if (fclose(fplist[no])) {
            fprintf(stderr,"Can't open file[%s]\n",file);
            return(1);
        }
    }
    
    return(0);
} 

int
main(int argc, char *argv[]) 
{
    int   divisor = 0;
    char *p       = NULL;
    char  input[128];
    char  base[128];

    if (argc != 4) {
        fprintf(stderr,"Usage : split2 divisor input base\n");
        exit(1);
    }
 
    for(p=argv[1];(*p)!='\0';p++) {
        if (!isdigit(*p)) {
            fprintf(stderr,"not a number! [%s]\n",argv[1]);
            exit(1);
        }
    }

    divisor = atoi(argv[1]);
    strcpy(input, argv[2]);
    strcpy(base, argv[3]);

    split(divisor, input, base);
}

8.速度比較

=== sh ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.696s
user    0m0.460s
sys     0m2.140s

=== perl ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.122s
user    0m1.736s
sys     0m0.216s

=== ruby ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.510s
user    0m2.048s
sys     0m0.256s

=== python ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m1.199s
user    0m0.832s
sys     0m0.228s

=== lisp ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m24.201s
user    0m21.632s
sys     0m2.012s

=== java ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.631s
user    0m2.936s
sys     0m0.468s

=== c ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m0.484s
user    0m0.236s
sys     0m0.224s

2017年4月15日土曜日

tree コマンドの作成

ubuntu などでは最初からインストールされないコマンドで使いたくなるのが tree コマンドである。 たが、開発環境の制約から自由にプログラムを追加できない場合も多い。



そんな場合に利用可能な言語で自前のツールとして用意しておくと助かる場合もある。以下は、シンボリックリンクや日本語のソート(sjisコード順)には対応せず、単純なソートと再帰呼び出しの組み合わせである。

  • perl で tree コマンド作成
  • ruby で tree コマンド作成
  • python で tree コマンド作成
  • clisp で tree コマンド作成
  • java で tree コマンド作成
  • C言語 で tree コマンド作成
  • 速度比較

    1.perl で tree コマンド作成


    #! /usr/bin/perl
    use utf8;
    #use Encode qw/encode decode/;
    use Encode;
    
    if (scalar(@ARGV) == 0) {
      $root_dir = "."
    }
    else {
      $root_dir = shift(@ARGV);
    }
    printf("%s\n",$root_dir);
    &tree("",$root_dir);
    
    sub tree {
      my($depth,$dir) = @_;
    
      if (!opendir(FD,$dir)) {
        printf("Can't open dir[%s]\n",$dir);
        exit(1);
      }
    
      my(@list) = ();
      foreach $file (readdir(FD)) {
        if ($file =~ /^[.]$/ || $file =~ /^[.][.]$/) {
          next;
        }
    #    $file = decode('UTF-8', $file);
    #    $file = encode('Shift_JIS', $file);
        push(@list,$file)
      }
      close(fd);
    
      my($cnt) = 0;
      foreach $file (sort @list) {
        $cnt++;
    
    #    $file = decode('Shift_JIS', $file);
    #    $file = encode('UTF-8', $file);
        my($fullpath) = $dir . "/" . $file;
        if ( -d $fullpath ) {
          if (scalar(@list) == $cnt) {
            printf("%s`-- %s\n",$depth,$file);
            tree($depth . "    ",$fullpath);
          }
          else {
            printf("%s|-- %s\n",$depth,$file);
            tree($depth . "|   ",$fullpath);
          }
        }
        else {
          if (scalar(@list) == $cnt) {
            printf("%s`-- %s\n",$depth,$file);
          }
          else {
            printf("%s|-- %s\n",$depth,$file);
          }
        }
      }
    }
    

    2.ruby で tree コマンド作成


    #! /usr/bin/ruby
    
    def tree(depth,dir)
      f =  Dir.open(dir);
      list = []
      f.each{ |file|
        if (file =~ /^[.]$/ || file =~ /^[.][.]$/)
          next
        end
    #    file = file.encode("Shift_JIS", :undef => :replace, :replace => "*")
        list.push(file)
      }
    
      cnt = 0
      list.sort.each {|file|
    #    file = file.encode("UTF-8")
        cnt = cnt +1
    
        fullpath = dir + "/" + file
    
        if (File.ftype(fullpath) == "directory")
          if (list.length == cnt)
            printf("%s`-- %s\n",depth,file)
            tree(depth + "    ",fullpath)
          else
            printf("%s|-- %s\n",depth,file)
            tree(depth + "|   ",fullpath)
          end
        else
          if (list.length == cnt)
            printf("%s`-- %s\n",depth,file)
          else
            printf("%s|-- %s\n",depth,file)
          end
        end
     }
    end
    
    if (ARGV.size() == 0)
      root_dir = "."
    else
      root_dir = ARGV[0]
    end
    printf("%s\n",root_dir)
    tree("",root_dir)
    

    3.python で tree コマンド作成


    #! /usr/bin/python
    
    import os
    import sys
    
    def tree(depth,dir):
      files = sorted(os.listdir(dir))
      cnt = 0
    
      for file in files:
        fullpath =  dir + "/" + file
        cnt = cnt + 1
    
        if os.path.isdir(fullpath):
          if len(files) == cnt:
            print "%s`-- %s"%(depth,file)
            tree(depth + "    " ,fullpath)
          else:
            print "%s|-- %s"%(depth,file)
            tree(depth + "|   " ,fullpath)
        else:
          if len(files) == cnt:
            print "%s`-- %s"%(depth,file)
          else:
            print "%s|-- %s"%(depth,file)
    
    root_dir = "."
    if len(sys.argv) > 1:
      root_dir = sys.argv[1]
    
    print root_dir
    tree("",root_dir)
    

    4.clisp で tree コマンド作成


    #! /usr/bin/clisp
    
    (defun fname-chop(tfile)
      ;;
      (let ((buf (namestring tfile)))
           (setq ch (subseq buf (- (length buf) 1) (length buf)))
           (if (equal ch "/")
               (subseq buf 0 (- (length buf) 1))
               (subseq buf 0 (length buf)))))
    
    (defun tree(depth dir)
      
      (let (
        (list (concatenate 
               'list
               (directory (concatenate 'String dir "*/"))
               (directory (concatenate 'String dir "*"))))
        (tmp "")
        (cnt 0))
    
        (sort list #'string< :key #'fname-chop)
    
        (dolist (file list)
          (progn 
            (incf cnt)
            (setq tfile (namestring file))
            (setq tfile (subseq tfile 0 (- (length tfile) 1)))
    
            (if (equal (file-namestring file) "")
              (if (equal (length list) cnt)
                (progn 
                  (format t "~A`-- ~A~%" depth (file-namestring tfile))
                  (tree (concatenate 'String depth "    ") (namestring file))
                  )
                (progn 
                  (format t "~A|-- ~A~%" depth (file-namestring tfile))
                  (tree (concatenate 'String depth "|   ") (namestring file))
                  ))
              (if (equal (length list) cnt)
                (progn 
                  (format t "~A`-- ~A~%" depth (file-namestring file))
                  )
                (progn 
                  (format t "~A|-- ~A~%" depth (file-namestring file))
                  )))))))
    
    (let 
      ((root_dir ""))
      (if (equal (length *args*) 0)
        (setq root_dir "./")
        (setq root_dir (car *args*)))
      (if (not (equal (subseq root_dir (- (length root_dir) 1) (length root_dir)) "/")) 
        (format t "test01 [dir]"))
      (format t "~A~%" root_dir)
      (tree "" root_dir))
    

    5.java で tree コマンド作成


    import java.io.*;
    import java.util.*;
    
    class tree {
      void tree(String depth,File dir) {
        File[] files = dir.listFiles();
        int cnt = 0; 
    
        Arrays.sort(files);
    
        if (files == null) {
          return;
        }
        for(File file: files) {
          cnt++;
          if (file.isDirectory()) {
            if (files.length == cnt) {
              System.out.printf("%s`-- %s\n",depth,file.getName());
              tree(depth + "    ",new File(file.getAbsolutePath())); 
            }
            else {
              System.out.printf("%s|-- %s\n",depth,file.getName());
              tree(depth + "|   ",new File(file.getAbsolutePath())); 
            }
          }
          else {
            if (files.length == cnt) {
              System.out.printf("%s`-- %s\n",depth,file.getName());
            }
            else {
              System.out.printf("%s|-- %s\n",depth,file.getName());
            }
          }
        }
      }
    
      public static void main(String args[]) {
        String root_dir = ".";
    
        if (args.length != 0) {
          root_dir = args[0];
        }
        System.out.printf("%s\n",root_dir);
    
        tree obj = new tree();
        obj.tree("",new File(root_dir));
      }
    }
    

    6.C言語 で tree コマンド作成


    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <string.h>
    #include <unistd.h>
    
    typedef struct dirent DENT;
    typedef struct {
      int   cnt;
      DENT *list;
    } DENT_B;
    
    int
    comp(src,dst) 
    DENT *src;
    DENT *dst;
    {
        return(strcmp(src->d_name,dst->d_name));
    }
    
    int
    list_alloc(base)
    DENT_B *base;
    {
        if (!base->list) {
            base->list = malloc(sizeof(DENT)*base->cnt);
            if (!base->list) {
                return(1);
            }
        }
        else {
            base->list = realloc(base->list, sizeof(DENT)*base->cnt);
        } 
    
        return(0);
    }
    
    int
    mklist(base,dir) 
    DENT_B *base;
    char   *dir;
    {
        DIR  *dp   = NULL;
        int   cnt  = 0;
        DENT *dent = NULL;
    
        dp=opendir(dir);
        if (!dp) {
            fprintf(stderr,"Can't open directory(%s)\n",dir);
            return(1);
        }
    
        base->cnt = 0;
        while(dent = readdir(dp)) {
            if (dent == (struct dirent *)-1) {
                fprintf(stderr,"Can't read directory(%s)\n",dir);
                return(1);
            }
    
            if (!strcmp(dent->d_name,".") ||
                !strcmp(dent->d_name,"..")) {
                continue;
            }
            
            base->cnt++;
            if (list_alloc(base)) {
                fprintf(stderr,"Can't alloc memory\n");
                return(1);
            }
    
            memcpy(&base->list[base->cnt-1],dent,sizeof(DENT));
        }
    
        if (closedir(dp)) {
            fprintf(stderr,"Can't close directory(%s)\n",dir);
            return(1);
        }
    
        return(0);
    }
    
    int
    tree(depth, dir)
    char *depth;
    char *dir;
    {
        DENT_B  base;
        int     cnt;
        char    fullpath[512];
        char    depth_tmp[512];
        struct stat dstat;
    
        memset(&base,0x00,sizeof(base));
    
        if (mklist(&base,dir)) {
            fprintf(stderr,"mklist error(%s)\n",dir);
            return(1);
        }
    
        qsort(base.list,base.cnt,sizeof(DENT),comp);
    
        for(cnt=0;cnt<base.cnt;cnt++) {
            sprintf(fullpath,"%s/%s",dir,base.list[cnt].d_name);
            if (stat(fullpath,&dstat)) {
                fprintf(stderr,"stat error(%s)\n",fullpath);
                return(1);
            }
            if (dstat.st_mode & S_IFDIR) {
                if (cnt+1 == base.cnt) {
                    printf("%s`-- %s\n",depth,base.list[cnt].d_name);
                    sprintf(depth_tmp,"%s    ",depth);
                    tree(depth_tmp,fullpath);
                }
                else {
                    printf("%s|-- %s\n",depth,base.list[cnt].d_name);
                    sprintf(depth_tmp,"%s|   ",depth);
                    tree(depth_tmp,fullpath);
                }
            }
            else {
                if (cnt+1 == base.cnt) {
                    printf("%s`-- %s\n",depth,base.list[cnt].d_name);
                }
                else {
                    printf("%s|-- %s\n",depth,base.list[cnt].d_name);
                }
            }
        }
    
        free(base.list);
    
        return(0);
    }
    
    int
    main(argc,argv)
    int argc;
    char *argv[];
    {
        char *root_dir = NULL;
    
        root_dir = ".";
        if (argc > 1) {
            root_dir = argv[1];
        }
        printf("%s\n",root_dir);
        if (tree("",root_dir)!=0) {
           exit(1);
        }
        exit(0);
    }
    

    7.速度比較(2455 directories, 22931 files)


    == perl ==
    
    real    0m0.202s
    user    0m0.112s
    sys     0m0.088s
    
    == ruby ==
    
    real    0m0.333s
    user    0m0.196s
    sys     0m0.112s
    
    == python ==
    
    real    0m0.234s
    user    0m0.116s
    sys     0m0.112s
    
    == lisp ==
    
    real    0m2.564s
    user    0m1.736s
    sys     0m0.792s
    
    == java ==
    
    real    0m1.050s
    user    0m1.472s
    sys     0m0.432s
    
    == C ==
    
    real    0m0.101s
    user    0m0.020s
    sys     0m0.080s
    
    

  • 2017年4月9日日曜日

    ubuntu に oracle client をインストール

    ubuntu にオラクルクライアントをインストールし、リモートのオラクルデータベースに接続する。




    1.事前準備として以下の構成のディレクトリを作成
     /mnt/vbox/share/oracle12c 
     |-- database : linuxx64_12201_client.zip を展開
     `-- inst12c : 以下、スクリプト client.sh を作成
    

    ※ client.sh
    #! /bin/sh
    
    # 
    PKG="$PKG libaio1"
    PKG="$PKG libaio-dev"
    PKG="$PKG default-jre"
    #
    #
    apt-get install $PKG
    #
    ##
    ln -s  /usr/bin/awk /bin/awk
    #
    ##
    groupadd -g 54321 oinstall
    
    useradd -u 1200          \
            -g oinstall      \
            -d /home/oracle  \
            -m oracle
    
    #
    mkdir -p /u01/app/oracle
    chown -R oracle:oinstall /u01/app
    chmod -R 775 /u01
    


    2.client.sh を実行後、オラクルクライアントのインストールを行う。
    # cd /mnt/vbox/share/oracle12c/inst12c
    $ sudo -s 
    # ./client.sh
    # su - oracle
    # cd /mnt/vobx/share/oracle12c/client
    # ./runInstaller -jreloc /usr/lib/jvm/default-java
    

    3..profile に以下の環境変数を設定
    export ORACLE_BASE=/u01/app/oracle
    export ORACLE_HOME=$ORACLE_BASE/product/12.2.0/client_1
    export ORACLE_SID=orcl
    export PATH=$ORACLE_HOME:$PATH
    export NLS_LANG=JAPANESE_JAPAN.UTF8
    export LD_LIBRARY_PATH=$ORACLE_HOME
    

    4.接続確認
     1) コンテナ形式のデータベースに接続
    $ source ~/.profile
    $ sqlplus system/passwd@IPaddress:1521/orcl.oracle.com  (CDBに接続)
    $ sqlplus scott/tiger@IPaddress:1521/orclpdb.oracle.com (PDBに接続)
    

     2) 従来型のデータベースに接続
    $ source ~/.profile
    $ sqlplus scott/tiger@IPaddress:1521/orcl.oracle.com
    

    5.tnsnames.ora を定義してサービス名で接続
     $ORACLE_HOME/network/admin/tnsname.ora にサービス名を定義し、その名称で接続
    $ cat $ORACLE_HOME/network/admin/tnsnames.ora
    SRV_PDB = 
     ( DESCRIPTION= 
        ( ADDRESS=(PROTOCOL = TCP)(HOST = 192.168.11.101)(PORT = 1521))
        ( CONNECT_DATA= (SERVICE_NAME=orclpdb.oracle.com))
     )
    $ sqlplus scott/tiger@srv_pdb
    

    2017年4月8日土曜日

    VirtualBox でホストマシンのディレクトリ参照(共有)

    インストールパッケージなどをホストマシンで解凍し、仮想環境から参照すると便利である。
    vboxsf グループに利用ユーザを加入しないと参照できなので注意が必要である。




    1.「共有フォルダー」を選択


    2.「+」でフォルダー追加


    3.フォルダーのプルダウン選択


    4.フォルダーを指定


    5.フォルダーの自動マウントを指定


    6.自動マウントで指定のフォルダが追加されているのを確認

    7.利用ユーザを vboxsf グループに加入
    # su - oracle
    $ id
    uid=1200(oracle) gid=54321(oinstall) groups=54321(oinstall),54322(dba),54323(oper),54324(backupdba),54325(dgdba),54326(kmdba),54327(racdba)
    $ ls -l /media/sf_share/
    ls: ディレクトリ '/media/sf_share/' を開くことが出来ません: 許可がありません
    $ exit
    ログアウト
    # cp /etc/group /etc/group.bk
    # gpasswd -a oracle vboxsf
    ユーザ oracle をグループ vboxsf に追加
    # diff /etc/group.bk /etc/group
    73c73
    < vboxsf:x:999:inst12c
    ---
    > vboxsf:x:999:inst12c,oracle
    # su - oracle
    oracle@vbox-win10:~$ ls -l /media/sf_share/
    合計 0
    drwxrwx--- 1 root vboxsf 0  4月  2 02:41 oracle12c
    

    ubuntu 上の oracle 12cにjava で接続確認

    ubuntu 上のoracle12c へ java プログラムから接続確認する。




    1.サンプルプログラム
    import java.sql.*;
    
    class sample01 {
      public void tblslt() throws Exception {
        String user = "scott";
        String pass = "tiger";
        String server = "localhost";
        String sid = "orcl";
    
        Connection conn = null;
        Statement  stmt = null;
        ResultSet  rset = null;
    
        Class.forName("oracle.jdbc.driver.OracleDriver");
        conn = DriverManager.getConnection(
               "jdbc:oracle:thin:@" + server + ":1521:" + sid,user,pass);
        stmt = conn.createStatement();
        rset = stmt.executeQuery("select deptno,dname,loc from dept");
        while(rset.next()) {
          System.out.printf("deptno = [%s]\n",rset.getString(1));
          System.out.printf("dname  = [%s]\n",rset.getString(2));
          System.out.printf("loc    = [%s]\n",rset.getString(3));
        }
        conn.close();
      }
    
      public static void main(String args[]) throws Exception {
        sample01 obj = new sample01();
        obj.tblslt();
      }
    }
    
    2.コンパイルと実行
    $ ls -l
    合計 8
    -rw-rw-r-- 1 inst12c inst12c 902  3月 29 16:03 sample01.java
    $ javac sample01.java 
    $ ls -l
    合計 16
    -rw-r--r-- 1 inst12c ibst12c 1763  3月 29 16:04 sample01.class
    -rw-rw-r-- 1 ibst12c ibst12c  902  3月 29 16:03 sample01.java
    $ java -classpath $ORACLE_HOME/jdbc/lib/ojdbc6.jar:. sample01
    deptno = [10]
    dname  = [ACCOUNTING]
    loc    = [NEW YORK]
    deptno = [20]
    dname  = [RESEARCH]
    loc    = [DALLAS]
    deptno = [30]
    dname  = [SALES]
    loc    = [CHICAGO]
    deptno = [40]
    dname  = [OPERATIONS]
    loc    = [BOSTON]
    

    ubuntu 上の oracle 12cで Pro*c コンパイル

    ubuntuにoracle をインストールした直後の状態から Pro*c のコンパイルを通すには幾つか設定が必要である。




    1.動作確認のために使用したPrco*Cプログラム
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sqlca.h>
    /*
    SQL> desc dept
     名前                                    NULL?    型
     ----------------------------------------- -------- ----------------------------
     DEPTNO                                    NOT NULL NUMBER(2)
     DNAME                                              VARCHAR2(14)
     LOC                                                VARCHAR2(13)
    */
    struct {
      char deptno[2+1];
      char dname[14+1];
      char loc[13+1];
    } rec;
    
    void
    main(argc,argv)
    int argc;
    char *argv[];
    {
      char *sp_uid = "scott/tiger";
    
      EXEC SQL CONNECT :sp_uid;
    
      EXEC SQL DECLARE CUR_SCOTT CURSOR FOR
      SELECT DEPTNO,DNAME,LOC FROM DEPT;
      EXEC SQL OPEN CUR_SCOTT;
    
      while(1) {
        EXEC SQL FETCH CUR_SCOTT INTO :rec;
    
        if (sqlca.sqlcode == 1403) {
          break;
        }
    
        printf("DEPTNO = [%s]\n",rec.deptno);
        printf("DNAME  = [%s]\n",rec.dname);
        printf("LOC    = [%s]\n",rec.loc);
      }
    }
    

    2.$ORACLE_HOME/precomp/admin/pcscfg.cfg を環境に合わせて調整
      
    $ vi $ORACLE_HOME/precomp/admin/pcscfg.cfg
    =======================================================================
    diff pcscfg.cfg.org pcscfg.cfg
    1c1
    < sys_include=($ORACLE_HOME/precomp/public,/usr/include,/usr/lib/gcc-lib/x86_64-redhat-linux/3.2.3/include,/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include,/usr/lib64/gcc/x86_64-suse-linux/4.1.0/include,/usr/lib64/gcc/x86_64-suse-linux/4.3/include)
    ---
    > sys_include=($ORACLE_HOME/precomp/public,/usr/include,/usr/include/x86_64-linux-gnu,/usr/lib/gcc/x86_64-linux-gnu/6.2.0/include)
    =======================================================================
    

    3.LD_LIBRARY_PATHを設定
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib
    
    • $ORACLE_HOME/lib配下には、ubuntu のデフォルトライブラリと重複するライブラリがあるため、 ウインドウマネージャを使用するアカウントや、ライブラリ更新などを行うアカウントの .profile などに登録すると干渉起こす場合がある。オラクル関連のアプリをコンパイル、起動する際に 設定するか、専用のアカウントで使用するのがよいと思われる。

    4.コンパイル用Makefile (procオプションのコード生成は"ANSI_C"とする)
    PROGRAM = sample01
    OBJS    = sample01.o
    CC      = gcc
    PROC    = proc
    PFLAGS  = include=$(ORACLE_HOME)/precomp/public
    PFLAGS += include=$(ORACLE_HOME)/rdbms/public
    PFLAGS += include=.
    PFLAGS += CODE=ANSI_C
    #PFLAGS += CODE=CPP
    
    CFLAGS  = -O3 -trigraphs -fPIC -DPRECOMP
    CFLAGS += -I$(ORACLE_HOME)/precomp/public
    CFLAGS += -I$(ORACLE_HOME)/rdbms/public
    CFLAGS += -I$(ORACLE_HOME)/plsql/public
    CFLAGS += -I$(ORACLE_HOME)/network/public
    CFLAGS += -I.
    CFLAGS += -DLINUX -DORAX86_64 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1
    CFLAGS += -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT
    CFLAGS += -DNS_THREADS -DLONG_IS_64 -DSS_64BIT_SERVER -DLDAP_CM -m64
    LDFLAGS = -L$(ORACLE_HOME)/lib -lclntsh -lsql12 -L $(ORACLE_HOME)/precomp/lib -lproc2 -lm
    
    .SUFFIXES: .c .o
    .SUFFIXES: .pc .c
    
    $(PROGRAM):$(OBJS)
     $(CC) $^ -o $@ $(LDFLAGS)
    
    .c.o:
     $(CC) $(CFLAGS) -c $<
    
    .pc.c:
     $(PROC) iname=$* $(PFLAGS)
    
    clean:
    

    5.コンパイルと実行
    $ ls -l
    合計 16
    -rw-r--r-- 1 naoki naoki 904  3月 29 15:24 Makefile
    -rw-r--r-- 1 naoki naoki 854  3月 29 15:24 sample01.pc
    $ make
    proc iname=sample01 include=/u01/app/oracle/product/11.2.0/dbhome_1/precomp/public include=/u01/app/oracle/product/11.2.0/dbhome_1/rdbms/public include=. CODE=ANSI_C
    
    Pro*C/C++: Release 11.2.0.1.0 - Production on 水 3月 29 15:33:04 2017
    
    Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
    
    システムのデフォルト・オプション値: /u01/app/oracle/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg
    
    gcc -O3 -trigraphs -fPIC -DPRECOMP -I/u01/app/oracle/product/11.2.0/dbhome_1/precomp/public -I/u01/app/oracle/product/11.2.0/dbhome_1/rdbms/public -I/u01/app/oracle/product/11.2.0/dbhome_1/plsql/public -I/u01/app/oracle/product/11.2.0/dbhome_1/network/public -I. -DLINUX -DORAX86_64 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS -DLONG_IS_64 -DSS_64BIT_SERVER -DLDAP_CM -m64 -c sample01.c
    gcc sample01.o -o sample01 -L/u01/app/oracle/product/11.2.0/dbhome_1/lib -lclntsh -lsql11 -L /u01/app/oracle/product/11.2.0/dbhome_1/precomp/lib -lproc2 -lm
    rm sample01.c
    $ ls -l
    合計 48
    -rw-r--r-- 1 inst12c inst12c   904  3月 29 15:24 Makefile
    -rwxr-xr-x 1 inst12c inst12c 12928  3月 29 15:33 sample01
    -rw-r--r-- 1 inst12c inst12c     0  3月 29 15:33 sample01.lis
    -rw-r--r-- 1 inst12c inst12c  4552  3月 29 15:33 sample01.o
    -rw-r--r-- 1 inst12c inst12c   854  3月 29 15:24 sample01.pc
    $ sample01
    DEPTNO = [10]
    DNAME  = [ACCOUNTING    ]
    LOC    = [NEW YORK     ]
    DEPTNO = [20]
    DNAME  = [RESEARCH      ]
    LOC    = [DALLAS       ]
    DEPTNO = [30]
    DNAME  = [SALES         ]
    LOC    = [CHICAGO      ]
    DEPTNO = [40]
    DNAME  = [OPERATIONS    ]
    LOC    = [BOSTON       ]