Perlがくしゅう帳(Rubyも)

プログラミングの勉強会の参加記録や学んだことなど。 twitter ID : @tomcha_で活動しています。 最近は主にPerl関連の勉強会やコミュニティに参加しています。移転前のブログはこちら->http://ruby.doorblog.jp/

プログラミング言語C K&R著の演習問題を解答していく その3

C言語のバイブルと言われる、K&Rの「プログラミング言語C」を第一章から読み進めて演習問題を記録していく。

プログラミング言語C 第2版 ANSI規格準拠

プログラミング言語C 第2版 ANSI規格準拠

第1章

  • 1-16 問題文がよくわからない

  • 1-17

  • 80文字は長いので、8文字以上ある行を出力する

1-17

  • 1-18
  • 行末のブランク、タブを削除 && 空白行を削除して出力する

  • 1-19
  • 文字列を逆さまにして出力する

  • 1-20
  • 決まったタブストップで語句を区切って出力

プログラミング言語C K&R著の演習問題を解答していく その2

C言語のバイブルと言われる、K&Rの「プログラミング言語C」を第一章から読み進めて演習問題を記録していく。

プログラミング言語C 第2版 ANSI規格準拠

プログラミング言語C 第2版 ANSI規格準拠

第1章

  • 1-10
#include <stdio.h>
int main(){
  int c;
  while((c = getchar()) != EOF){
    if(c == '\t'){
      printf("\\t");
    }else if(c == '\b'){
      printf("\\b");
    }else if(c == '\\'){
      printf("\\\\");
    }else{
      putchar(c);
    }
  }
}
  • 1-11
#include <stdio.h>
#define IN  1
#define OUT 0

int main(){
  int wordcounter, nowstatus;
  int c;
  nowstatus = OUT;
  wordcounter = 0;
  while((c = getchar()) != EOF){
    if(c == '\t' || c == ' ' || c == '\n'){
      nowstatus = OUT;
    }else if(nowstatus == OUT){
      nowstatus = IN;
      ++wordcounter;
    }
  }
  printf("%d\n", wordcounter);
}
  • 1-12
#include <stdio.h>

#define IN  0
#define OUT 1

int main(){
  int nowstatus = OUT;
  int c;
  while((c = getchar()) != EOF){
    if(c == ' ' || c == '\t' || c == '\n'){
      if(nowstatus == IN){
        printf("\n");
        nowstatus = OUT;
      }
    }else{
      nowstatus = IN;
      putchar(c);
    }
  }
}
  • 1-13
#include <stdio.h>

#define IN  0
#define OUT 1
int main(){
  int wordsize[10];
  int c;
  int i,j,k,l;
  int wordstatus;
  wordstatus = OUT;
  i = 0;
  for(j = 0; j < 10; j++){
    wordsize[j] = 0;
  }
  while((c = getchar()) != EOF){
    if(c == ' ' || c == '\t' || c == '\n'){
      if(wordstatus == IN){
        if(i <= 9){
          wordsize[i] += 1;
        }else{
          wordsize[9] += 1;
        }
        wordstatus = OUT;
        i = 0;
      }
    }else{
      wordstatus = IN;
      i += 1;
    }
  }
  for(k = 0; k < 10; k++){
    l = 0;
    if(wordsize[k] != 0){
      printf("%2d:%d",k ,wordsize[k]);
      while( l < wordsize[k]){
        printf("*");
        l += 1;
      }
      printf("\n");
    }
  }
}
  • 1-13-2
#include <stdio.h>

#define IN  0
#define OUT 1
int main(){
  int wordsize[10];
  int c;
  int i,j,k,l,m;
  int wordstatus;
  wordstatus = OUT;
  i = 0;
  for(j = 0; j < 10; j++){
    wordsize[j] = 0;
  }

  while((c = getchar()) != EOF){
    if(c == ' ' || c == '\t' || c == '\n'){
      if(wordstatus == IN){
        if(i <= 9){
          wordsize[i] += 1;
        }else{
          wordsize[9] += 1;
        }
        wordstatus = OUT;
        i = 0;
      }
    }else{
      wordstatus = IN;
      i += 1;
    }
  }

  int output[50];
  for(k = 0; k < 50; k++){
    output[k] = 0;
  }

  for(l = 0; l < 10; l++){
    if(wordsize[l] >= 5){
      output[l] = 1;
    }
    if(wordsize[l] >= 4){
      output[10 + l] = 1;
    }
    if(wordsize[l] >= 3){
      output[20 + l] = 1;
    }
    if(wordsize[l] >= 2){
      output[30 + l] = 1;
    }
    if(wordsize[l] >= 1){
      output[40 + l] = 1;
    }
  }

  for(m = 0; m < 50; m++){
    if(output[m] == 1){
      printf("*");
    }else{
      printf(" ");
    }
    if((m % 10) == 9){
      printf("\n");
    }
  }
  printf("0123456789\n");
}
  • 1-14
#include <stdio.h>

int main(){
  int ascii[128];
  int c;
  int count;
  int i,j,k;
  for(i = 0; i < 128; ++i){
    ascii[i] = 0;
  }

  while((c = getchar()) != EOF){
    ascii[c] += 1;
  }
  for(j = 0; j< 128; ++j){
    if(ascii[j] > 0){
      count = ascii[j];
      printf("%c:", j);
      for(k = 0; k < count; k++){
        printf("*");
      }
      printf("\n");
    }
  }
}
  • 1-15
#include <stdio.h>

float changeunit(float f);

int main(){
  float fahr, selsius;
  int lower, upper, step;

  lower = 0;
  upper = 300;
  step = 20;

  fahr = lower;
  printf("fahr-selsius conversion table\n");
  while(fahr <= upper){
    printf("%3.0f %6.1f\n", fahr, changeunit(fahr));
    fahr += step;
  }
}

float changeunit(float f){
  float v;
  v = ((5.0/9.0) * (f - 32.0));
  return v;
}

第2回 なにわPerlを開催しました。

なにわPerl主催のTomchaです。

平成27年2月21日、joe'sビジネスセンターさんの場所をお借りして、第2回なにわPerlを開催しました。

大事なこと

会場をお貸し頂いたjoe'sさんでは、VPSサービスのホスティング等、自作webアプリをインターネット上に公開する為のサーバーホスティング等をされています。オレオレserverが欲しいなぁ等、興味のある方はwebサイトにプランの説明などが書いてありますので、ご覧下さい。

なにわPerl

今回は総勢3名でもくもくしました。 内容は、

  • Perl入学式第5回で時間切れとなったTest周りの自習
  • 続・はじめてのPerlの読書
  • 第6回Perl入学式の資料作成
  • Rubyを使ってのウェブアプリ開発

などでした。何気ない会話から情報交換が出来たりするのも、もくもく会の良いところですね。
テスト関係の話で、どうやってテストを書くか、どこまで書くかなども教えてもらいました。

こんな雰囲気で開催しました

togetterにまとめてあります。 第2回 なにわPerl - Togetterまとめ

懇親会

懇親会は会場近くのお初天神の居酒屋で軽く飲みました。
個室だったのですが、料理をGetリクエストした後、レスポンスが帰るまで30min(msecじゃない)とかかかってたので、毎回店選びで迷わなくて済むように馴染みの良い店を開拓しないといけないなーと思いました。

次回なにわPerlについて

日時はまだ未定ですが、第3回もやりたいと思っています。 Perl入学式を卒業した後もPerlで何かを作ったり話したりできるので活用してください。もちろん、他の言語でも参加OKです。
DoorKeeperのコミュニティにとりあえず登録しておくと、次回開催情報がメールで受け取れますので、興味のある方は登録してみて下さいね。

なにわPerlのコミュニティはこちら↓

http://naniwaperl.doorkeeper.jp/

プログラミング言語C K&R著の演習問題を解答していく その1

昔、N88-Basicを写経して遊んだ後、チャレンジしたけれど関数とか用語で挫折したC言語に大人になってからのリベンジ。
C言語のバイブルと言われる、K&Rの「プログラミング言語C」を第一章から読み進めて演習問題を記録していく。

プログラミング言語C 第2版 ANSI規格準拠

プログラミング言語C 第2版 ANSI規格準拠

第1章

  • 1-1
#include <stdio.h>    
int main(){  
  printf("Hello,world!\n"):  
}

;を;に変えてコンパイル

1-1.c:4:27: error: expected ';' after expression
  printf("Hello,world!\n"):
                          ^
                          ;
  • 1-2
int main(){
  printf("hello,world\x");
}
1-2.c:4:22: error: \x used with no following hex digits
  printf("hello,world\x");
                     ^~
1 error generated.
  • 1-3
int main(){
  float fahr, selsius;
  int lower, upper, step;

  lower = 0;
  upper = 300;
  step = 20;

  fahr = lower;
  printf("fahr-selsius conversion table\n");
  while(fahr <= upper){
    printf("%3.0f %6.1f\n", fahr, ((5.0/9.0) * (fahr - 32.0)));
    fahr += step;
  }
}
  • 1-4
int main(){
  float selsius;
  int lower, upper, step;

  lower = 0;
  upper = 300;
  step = 20;

  selsius = lower;
  while(selsius <= upper){
    printf("%3.0f %6.1f\n", selsius, ((9.0/5.0) * selsius + 32.0));
    selsius += step;
  }
}
  • 1-5
int main(){
  float fahr;
  for(fahr = 300; fahr >= 0; fahr = fahr - 20){
    printf("%3.0f %6.1f\n", fahr, ((5.0 / 9.0) * (fahr - 32.0)));
  }
}
  • 1-6
int main(){
  int c;
  printf("%d",(c = getchar()) != EOF);
}
  • 1-7
int main(){
  printf("%d", EOF);
}
  • 1-8
int main(){
  int ns, nt, nnl;
  int c;
  ns = nt = nnl = 0;
  while((c = getchar()) != EOF){
    //getchar()はエンターが入力される度実行される。
    if(c == ' '){
      ++ns;
    }else if(c == '\t'){
      ++nt;
    }else if(c == '\n'){
      ++nnl;
    }else{
    }
  }
  printf("space => %d, tab => %d, newline => %d\n",ns, nt, nnl);
}
  • 1-9
int main(){
  int c;
  while((c = getchar()) != EOF){
    if(c == ' '){
      while(c == ' '){
        c = getchar();
      }
      putchar(' ');
    }
    putchar(c);
  }
}

第1回hommachi.rbに行ってきました

トークしました

第1回 hommachi.rbに行って、「はじめてのプログラミング」というテーマでトークしてきました。

トークの対象者は、プログラミングに興味があるけれども、プログラミングをした事がないビギナー向けの話です。hommachi.rbは初心者向けRubyの勉強会ですが、この初心者の定義2つ
- 「プログラミングをしたことが全く無い」 - 「何らかの言語でプログラミング経験はあるが、Rubyを使ったことが無い」 のうち、前者の方をターゲットにして話をしました。

今後も、第2回、第3回と続いていくと思いますが、もしまたトークをする機会があれば、この前者をターゲットにした何かを発表できたらなと思っています。

Railsのトーク

本日のメイントークは@ogomorさんによる「Ruby on Rails を環境構築からスタートして最終的には1つのwebサービスを完成させる」発表のレッスン1でした。

https://github.com/hommachirb/rails-example/blob/master/doc/lesson/001.md
今後も継続して参加すれば、階段を1ステップずつ上がるようにRuby on Rails の使い方がマスターできそうです。
Githubに手順1つずつに対応した変更履歴を上げられてますので、これをみながら予習復習するのも分かりやすくて良いですね。

自分用の今日のRailsの講義メモです。

  • Ruby ob Rails には設計の哲学思想があり、DRY(同じことを繰り返さない)とCoC(設定よりも規約)という2つがテーマ。この思想を理解した上でRailsを使うと、ただ書き写すよりも理解度が上がる。
  • CoC は今回作成したviewのテンプレートの命名で、navbarというナビゲーションバーの部品はページのhtml.erbからnavbarの呼び出しで組み込むことができる。''の付し方ルール(規約)だけでテンプレートの組み込みを実現していた。
  • config/routes.rb にアクセスした時の一番トップの挙動を書く。
  • コーディング作業は、rails server で立てておき、localhost:3000/rails/info/routes を見ながらすると捗る。

最後に

スタッフの皆さん、発表者のみなさん、おつかれさまでした。また次回よろしくお願いします。


*スライドでYAPC::ASIA 2015の宣伝をして、ヤプシー成功祈願活動もちょこっとだけしました

Perlのmapについて

Perl入学式in大阪第5回「map関数」についての補足事項です。

講義中に自分でテストコードを書いて試してからツイートをしたのですが、mapの話が懇親会で話題にあがり、@azumakuniyukiさんより、「mapは破壊的関数ちゃうのん?」と指摘があり、 その後にもう少し突っ込んでサンプルコードを試したところ、ツイートの「mapは、元のデータを書き換えるのではなく」は誤っていました。すみませんでした。

結論

map関数は「破壊的関数」であり、元の配列のデータは更新(上書き)されるケースがあります。

更新されるケースとは?

こういう事はコードを書いて実験するのが一番です。
4つのパターンのmap関数使用例を書いてみました。

mapのテスト

講義中にササッと書いてテストしたのはコード14行目の"a"のパターンです。
この使い方だと、確かに元の配列@aの中身は変更されず、別の配列@bに代入された結果だけが'.bak'を付加されているので、一見、「map関数は元の配列データを更新しない」様に見えます。

しかし、本当にそうだったのでしょうか? コード17行目"c"のパターン、コード18行目"d"のパターンともに元の配列@aaのデータは正規表現の条件式に当てはまるデータは".bak"を付加され、データが更新されていました。

"c"、"d"は正規表現の置換のコードです。$の値が置換されますね。それに対して"a"のパターンは$の値を”参照”はしているものの、代入する表現は含まれていません。代入をするパターンとして、コード15行目を試してみると、何と@aは元の配列のデータが更新されました。

この実験コードのテストから、$_は元の配列の個々のデータを参照しているので、当然書き換えれば元の配列のデータは書き換わることが分かります。ということは、「mapは破壊的関数で元のデータを更新する」という事ですね。

ただし、パターン"a"の様な、配列のデータを参照にとどめている場合は自動で更新されません。
なので、「mapは破壊的関数で元のデータを更新するが、中の式によって更新しないケースもあるので、ケースに応じて意図した通りに元の配列が更新されるか(又は更新されないか)を注意する必要がある」という事ですね。

結論その2

という事で、この話題も懇親会で色々講義の内容をワイワイ話した結果得られた知見でした。
懇親会、大事ですね。ざっくばらんに質問したり、話をしたりできる場ですので、講義だけでは聞けなかった事や、間違って解釈してしまっていた事が分かる場でもあります。また、サポーター陣も完全では無いので、今回のように間違いを発見できる場でもありました。

f:id:tomcha0079:20150117181044j:plain

f:id:tomcha0079:20150117195013j:plain

懇親会、大事。

Rubyでwebアプリひな形作成CLIツールを作ってみた

Rubyを書いてるの人の大半の目的はRailsの利用だと思うのですが、自分はRails newを試した位しか、した事がありません。
まあ、今のところ趣味で作るサイトやwebアプリにはRailsは多機能過ぎて、もっぱらSinatraHamlで挙動を確認しながら色々試しています。良い点として、自分で必要なGemを吟味して追加する必要があるので、それぞれどの部分が何をしているかが把握できる点ですね。
また、Sinatraを使ったwebアプリの作り方は

Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)

Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)

で1から手取り足取り解説されてて、この本を写経してやり方を覚えればwebアプリが作れるようになります。非常に良い本でおすすめです。

本題

で、いくつかのwebアプリを作っては捨て、作っては捨てをしていると、初期ファイルを書くのが非常に面倒になってきました。
Rails newでひな形を自動でガガガーっと作ってくれるみたいな、自分用のツールが欲しい!と思ったので、CLIツール「Sinatras(名前は超適当)」の作成にチャレンジしてみました。
パーフェクトRubyの第15章を参考に(というか、ほとんど写経)して、何とか完成。

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)

今のところnewコマンドしかありませんが、

sinatras new <appname>

で、appnameで指定したアプリ名でディレクトリを作成し、

  • 各ディレクトリをよしなに作成
  • Gemfile作成
  • config.ru作成
  • アプリ名.rb作成
  • ビュー用テンプレindex.haml,layout.haml作成
  • git initの実行

等をしてくれます。
実際に実行した様子はこんな感じ

f:id:tomcha0079:20150110200423p:plain

作成されたファイルは・・・

f:id:tomcha0079:20150110200435p:plain

※ 追記
ファイルが作成されたら、もちろんrackupできます。 127.0.0.1:9292 でブラウザからこの画面が出るはず。

f:id:tomcha0079:20150110221147p:plain

f:id:tomcha0079:20150110221152p:plain

あとはviewsの中のhamlファイルをいじれば、簡単なwebページが作れます。cssを作った時はpublicフォルダへ保存しましょう。

パーフェクトRubyを読んで

まだ、頭から読み進めてる途中ですが、CLIツールは第15章に書かれている通りに読み進めていけば簡単にGemファイルを作る事ができました。
作ったGemファイルをインストールする事により、どこでも「コマンド」として実行できます。
今回勉強になったのは、前のブログで書いたモジュールやクラスの機能分離方法の実例が学べた点です。作る過程で体験できるので非常に良いです。

また、この本は「たのしいRuby

Rubyに入門した次に、脱初学者向けとして読むのが丁度良いと思います。
気をつける点は、若干ソースコードに誤植があるのと、おそらくスペースの都合上、コードの一部を省略している点です。
どの部分のコードなのかは、出版元サイトから掲載されているコードがダウンロード出来るので、それを直接見るのがベストです。

エンジニアリングとは

プログラミングの醍醐味は、モノ作りをして完成した時の達成感や動いた時の感動ですが、もうひとつ大事な事として、エンジニアリングによる作業の短縮効果でしょうか。実用的なアプリを作ることによって、今までとはまた違った喜びの体験ができました。

とにかく、rails newみたいにSinatraのアプリが作れる様になりました!やった!
ソースコードGithubにあります。

https://github.com/tomcha/sinatras

アドバイス等があれば、お手柔らかによろしくお願いします。