golangのインストール

環境:ubuntu 16.04

手順は、公式サイトに書いてあります。
まず、公式サイトからtar.gzをダウンロードします。
ダウンロードしたファイルのあるフォルダに移動して、

sudo tar -C /usr/local -xzf go1.8.linux-amd64.tar.gz

を実行。
次に

export PATH=$PATH:/usr/local/go/bin

を実行して、

sudo ln /usr/local/go/bin/go /usr/local/bin/go

を実行する。
これで、シェルからgoコマンドが使えるようになる。

Cでコメントを取り除くプログラムを書いた

 
アスキー出版のC言語入門に下記のようなサンプルコードがありました。

#include <stdio.h>

struct table_entry
    {
    void (*prtptr)();    //出力用関数のポインタ
    int next_state;      //次の移るべき状態
    };

int main(int argc, char *argv[]){
    int c, col, row;
    void charptr(), noptr(), slsh();
    static struct table_entry table[][3] =
    {
        {{noptr, 2}, {charptr, 0}, {charptr, 0}},
        {{noptr, 1}, {noptr, 3}, {noptr, 1}},
        {{slsh, 0}, {noptr, 1},{slsh, 0}},
        {{noptr, 0}, {noptr, 1}, {noptr, 1}}
    };

    row = 0;
    while((c = getchar()) != EOF)
    {
        //入力された文字に一致する列を見つける
        if(c == '/')
            col = 0;
        else if(c == '*')
            col = 1;
        else
            col = 2;
        (*table[row][col].prtptr)(c);      //該当する出力関数を実行
        row = table[row][col].next_state;  //次の状態を調べる
    }
    return 0;
}

void noptr(c)
char c;
{}    //何もしない

void charptr(c)
char c;
{
    putchar(c);    //文字を出力する
}

 
この状態では人が端末に入力しないと使えないので、ちょっと不便。
さらに出力も端末に出力されるだけなので、不便。

そこで、このコードを元にファイル指定して、結果を指定したファイルに保存できるようにしてみました。

#include <stdio.h>

struct table_entry
    {
    void (*prtptr)();    //出力用関数のポインタ
    int next_state;      //次の移るべき状態
    };

int main(int argc, char *argv[]){
    int col, row;
    char c;
    FILE *readfile, *writefile;
    void charptr(), noptr(), slsh();
    static struct table_entry table[][3] =
    {
        {{noptr, 2}, {charptr, 0}, {charptr, 0}},
        {{noptr, 1}, {noptr, 3}, {noptr, 1}},
        {{slsh, 0}, {noptr, 1},{slsh, 0}},
        {{noptr, 0}, {noptr, 1}, {noptr, 1}}
    };
    //引数のチェックをする
    if(argc > 2){
        row = 0;
        if(readfile = fopen(argv[1], "r")){        //ファイルを開く
            writefile = fopen(argv[2], "w");       //結果を出力するファイルを開く
            while((c = getc(readfile)) != EOF)
            {
                //入力された文字に一致する列を見つける
                if(c == '/')
                    col = 0;
                else if(c == '*')
                    col = 1;
                else
                    col = 2;
                (*table[row][col].prtptr)(c, writefile);    //該当する出力関数を実行
                row = table[row][col].next_state;           //次の状態を調べる
            }
            fclose(readfile);    //ファイルを閉じる
            fclose(writefile);   //結果を出力するファイルを閉じる
        }else{
            printf("Can't open file(%s).\n", argv[1]);
        }
    }else{
    printf("More than one argument is required.\n");
    }
    return 0;
}

void noptr(c, writefile)
char c;
FILE *writefile;
{}    //何もしない

void charptr(c, writefile)
char c;
FILE *writefile;
{
    putc(c, writefile);    //文字を出力する
}

void slsh(c, writefile)
char c;
FILE *writefile;
{
    putc('/', writefile);    // /を出力し、文字を出力する
    putc(c, writefile);
}

 
ちょっとだけ解説をします。

if(argc > 2)

 
で引数の数が足りているかチェックしています。
引数が足りない場合はファイルを開く操作を中止し、引数が足りないことを知らせます。

if(readfile = fopen(argv[1], "r"))

 
ファイルが開きます。
fopen()はファイルが開けなかった場合EOFを返すので、その場合は条件が偽となります。
開けなかった場合はファイルが開けなかったことを知らせます。

while((c = getc(readfile)) != EOF)

 
でファイルの終わりまで一文字ずつ読み込んで行きます。
getc()はファイルの終わりに到達するか、ファイルが開けなかった場合にEOFを返すので、その場合は条件が真となります。

void noptr(c, writefile)
void charptr(c, writefile)
void slsh(c, writefile)

 
関数ポインタで呼び出す関数で使用する引数writefileを追加しています。
writefileは出力するファイルのポインタで、putc()でファイルに書き込む際に利用します。

使い方ですが、コメントを取り除きたいファイルを用意します。ここではsample.cとしておきます。
このコードをビルドして、

./a.out sample.c result.c

 
でsample.cのコメントを取り除いたファイルがresult.cとして出力されます。
ここでは取り除くのが/* */しか対応してませんが、特定の文字列を取り除く場合はswitch caseの使用と構造体tableの変更で対応できます(4行x3列のテーブルを変更する)。

ここにseparate.cがあるじゃろ?

( ^ω^) 
⊃  ⊂ 

これを
( ^ω^) 
⊃)  (⊂ 

( ^ω^) 
≡⊃⊂≡ 
gcc -o separate separate.c

 

こうじゃ…

( ^ω^)
⊃ .. ⊂   
‘∵   
‘:’;

_人人人人人人人_ 
>separateの誕生< 
 ̄^Y^Y^Y^Y^Y^Y ̄

uniteからdeniteに移行中

とりあえずuniteのsourceがdeniteで使えるらしいので試してみました。
おもむろに以下のようなコードを用意し、

#include <stdio.h>

int main(int argc, char *argv[]){
    printf("hello world")
    return 0;
    }
:QuickRun

を実行すると、printf()のあとに;がないので、エラーになります。

||  ^~~~~~
||  return 0;
test1.c|5 col 2| error: expected ‘;’ before ‘return’                            
|| /home/raiden/Projects/test1.c: In function ‘main’:

バッチリdeniteに出力され、test1.cを選択してエンターでジャンプしました。

vimfilerがuniteなしでは動かない模様なので移行しきれない…。
Vimfiler will support denite? #379
らしいので、気長に待ちます。

vimrc読書会でvimrcを読んでもらった

12月3日のvimrc読書会で私のvimrcを読んでもらいました。
私の知識不足が露呈しましたが、理解せずにコピペして使っていた設定をあれこれ言って教えてもらえたので有意義な時間でした。

C言語で処理時間を短縮する

C言語で処理時間を短縮する方法として、記憶クラスregisterを使用するというのがあります。
registerはCPUのレジスタに変数の値を格納する領域を確保できれば確保するため、メモリ上に確保する通常の変数宣言と比べて高速に変数にアクセスできるようになります。

#include <stdio.h>
#include <time.h>

int main(int argc, char *argv[]){
	register int a;
	int b;
	a = 0;
	b = 0;
	clock_t start,end;
	start = clock();
	while(b < 10000000)
	{
		++b;
	}
	end =clock();
	printf("running time:%d[us]\n", (end - start));
	start = clock();
	while(a < 10000000)
	{
		++a;
	}
	end = clock();
	printf("running time:%d[us]\n", (end - start));
	return 0;
}

このプログラムを実行すると、

running time:18509[us]
running time:2637[us]

およそ7倍速い結果が得られました。

CPUのレジスタには限りがあるため、レジスタに変数を格納できなければ同等のスピードになります。
また、全ての変数にレジスタが用意できるわけではないので、何でもかんでもレジスタにするのではなく、頻繁にアクセスする変数に限って宣言しなければ、十分な結果を得られません。(コンパイラは上から順番にレジスタを準備していくため)
さらに、コンパイラによってはregisterをサポートしていないこともあるらしいので、注意しましょう。

記憶クラスregisterを使用して処理時間を短縮する場合はレジスタについて十分理解して利用しましょう。

参考文献 アスキー出版 C言語入門