パスワードを忘れた? アカウント作成
78854 journal

crowzの日記: C言語を業務でつかってみる 1

日記 by crowz

仕事が忙しくカナリ間が空いてしまったが、C言語習得への道をあきらめたわけではない。
忙しい中でチャンスを見つけていつかC言語を仕事に使ってやろうと思っていたのだが、とうとうチャンスが来たようだ。

今回作成しなければならないものは(別にC言語じゃなくていいんだけど)サーバとの通信を行うプログラムだ。
なんかいきなり敷居がぐっと上がってしまったような気がしない事もないが、せっかくなのでチャレンジしてみたいと思う。

とりあえず、サーバとの通信プロトコルはPerlで作った似たようなプログラムで把握済み。
後は、C言語でも同じような事をやればいいだけだという事はわかっているが、
今までの少なすぎるC言語の経験から行くとそれさえも想像がつかない。

とりあえず、簡易的な通信プログラムを作って接続->コマンド発行->結果取得->終了を目指す。

65938 journal

crowzの日記: 引数の取り扱いと型変換にハマる5日目 2

日記 by crowz

前回のソースで、とりあえず決め打ちの日付を出すことには成功したが、課題が2個あった。
1.年月の指定
2.フォーマットが決め打ちなのがダサい。
3.ソースコードが美しくない。

(3は置いておいて)とりあえず1について解決したのでハマった個所を備忘録代わりに。
まず、引数の取り扱いについてだが、それを簡単に行う事のできる関数を発見。
最初はargv[n]で第n+1番目の引数を取っていたのだけども
(n=0のときはプログラムそのものの名前が入るので+1してる)
それでは、引数の順番がバラバラの場合に対応できない。
しかし以下のように書くことによって引数を自動的に解釈してくれた。すごい便利。

  // 引数の解析
  while(-1!=(option = getopt(argc, argv, "m:y:"))){
    switch( option ){
    case 'm' : month = atoi(optarg); break;
    case 'y' : year = atoi(optarg); break;
    }
  }

引数を順番に舐めて、-mと-yの直後の値をoptargと言うのに代入してくれるそうだ。
このoptargってどっから来たんだろう?と思って調べてみるとexternと言う型で
"どこかで定義されている変数"であるらしい。一応ファイル先頭で

extern char *optarg;

こう書いておく方がわかりやすくでいいかもしれない。

次にハマったのがこの関数で取得するのはどんな値だろうが文字列として扱われる事。
しかも出力した時に'169321156'見たいな感じで数字が表示されているのでなんのことかわからなかった。
結局、型が違っている事に気付いたがキャストの方法がわからず悩んだもののatoiと言う関数で一発でできた。

とりあえずこれで指定した日付のカレンダーは表示されるようになった。
次はエスケープシーケンスを駆使したカレンダーのフォーマットかな。

65007 journal

crowzの日記: いきなりカレンダーの完成した4日目

日記 by crowz

前回からいきなり飛んだような気がするがノってきたので一気に書き上げてしまった。
汚いけどそのまま掲載。

#include <stdio.h>
#include <time.h>
 
struct tm *date, *now, makeTime;; /* 日付の構造体 */
 
void calendarHeader(void); // プロトタイプ
void calendar(int month, int year); // プロトタイプ
void nowDate(void); // プロトタイプ
void getLastDay(int month, int year);
 
int main(int argc, char* argv[]){
 
  nowDate();
 
  // 指定した日付のカレンダーを出力
  //  getLastDay(2, 2009);
 
  calendarHeader();
  calendar(2, 2009);
}
 
// 現在を取得
void nowDate() {
  time_t nowdate;
  int mon, year;
  time(&nowdate);
  now = localtime(&nowdate);
  mon = now->tm_mon + 1;
  year = now->tm_year + (1900);
  getLastDay(mon, year);
 
}
 
// 指定した月の末尾を構造体で取得する
void getLastDay(int month, int year) {
 
  //  struct tm makeTime; // 日付のデータを格納する構造体
  time_t at2k;
 
  //  makeTime.tm_sec = 0;
  //  makeTime.tm_min = 0;
  //  makeTime.tm_hour = 0;
  //  makeTime.tm_wday = 0;
  makeTime.tm_mday = 0;
  makeTime.tm_mon = 2;
  makeTime.tm_year = 109;
 
  at2k = mktime(&makeTime); // パラメタからデータを作成(UNIXTIME)
 
  date = localtime(&at2k); // 生成したUNIXTIMEから時間の構造体を作成してグローバル変数に保存
 
}
 
void calendar(int month, int year) {
  int i;
  for(i = 1; i <= date->tm_mday; i++) {
    printf("%2d ", i);
    if(i % 7 == 0) {
      printf("\n");
    }
  }
      printf("\n\n");
}
 
// カレンダ見出し
void calendarHeader() {
  char str[256];
  strftime(str, 255, "%Y年 %m月", date); // グローバル変数の日付が格納された構造体をフォーマットしてstrに代入
  printf("     %s     \n", str); // それを出力
 
  printf("日 月 火 水 木 金 土\n");
}

とりあえずはまったけど、当日のカレンダーは出るようになった。
本当は*.hファイルに分けたりとかした方がかっこいいのかもしれないが。
ダサい部分は、カレンダ部分の見出し部分の見た目が決め打ちでフォーマットしてある部分と
なんか無駄に関数を分けちゃっている点。ソースが美しくないのは仕方ないかな。

後は、当日の反転・表示月を可変にすること・3か月表示などこっちは
表示に関してはエスケープシーケンスを使ってフォーマットすべきなのかもしれない。
その他はC言語の引数の扱いについて実装しなければならないかな。

64238 journal

crowzの日記: 構造体の取り扱いを学ぶ3日目 1

日記 by crowz

さて前回Hello Worldをお約束的に作ってみたわけだが、
あくまで文字出力したにすぎないので今回は何かしらのデータを表示しようと思う。

とりあえず目標としてはカレンダーの出力なわけだが、
C言語による日付の扱いを見ているとどうやら「構造体」なる物が必修のようだ。
構造体とは要するに値の集まった集合体のようなものらしい。
で、今回なぜこれが必要かと言うと時間を取ってくる関数が時間の情報を構造体で返してくるというのだ。
なので構造体を理解しなければならないよう。

ざっくりと資料を読む限りはデータの構造の塊の変数。
厳密には違うのかもしれないが、要はPerlの連想配列のもっと型が決まってる版みたいなものだろうか。

とりあえず現在の年を表示してみた。なんにも考えずにちょっとアレンジして書き写し。
# main関数に関しては、コメントで指摘いただいたので修正しました。多謝!
コード

#include <stdio.h>
#include <time.h>
struct tm *date; /* 日付の構造体 */
time_t now; /*時間の格納*/
int main(int argc, char* argv[]){
  time(&now); // 現在のシステム時刻を取得
  date = localtime(&now); // 現在の日付情報の構造体を取得
  printf("%d 年\n", date->tm_year + 1900); // 今年を出力
}

結果

2009 年

おお。出た出た。
注意点としては
time.hをインクルードしなければならないという事。
で、その中に定義されている構造体"tm"と言うのがあってそこでは以下の用に定義されているらしい。

struct tm
{
  int tm_sec;      // 秒
  int tm_min;      // 分
  int tm_hour;     // 時
  int tm_mday;     // 日
  int tm_mon;      // 月
  int tm_year;     // 年
  int tm_wday;     // 曜日
  int tm_yday;     // 1月1日からの日数
  int tm_isdst;    // サマータイムの有無
};

で、time_t型ってなんぞやと思って調べると説明しているサイトを見つけた

次に、time_t型を紹介します。これはtypedefで定義された型の別名です。一般的に次のように定義されています。
 
typedef long int time_t;
 
time_t型は、暦時間(カレンダー時間)を表現するために使われます。暦時間は、現在の時刻を何らかの方法で数値化した情報で、<strong>どんな形式かははっきり定義されていません。</strong>

どんな形式かはっきり定義されていません。って言われてるのでまぁ なんでも入るんだろうというくらいの認識で今はいよう。
要するに上のコードでは、time関数にtime_t型の変数nowを参照渡しでデータを受け取り、
そのあとlocaltime関数でそのデータを時間の構造体tmに変換。
その後構造体の値tm_yearに1900足して(これはPerlと同じで年は-1900された状態で取得されるので)出力した。

日付を扱うことで一歩カレンダーに近づいたが、今度は自分で指定した時間の構造体を作れるようにしなければ。

60249 journal

crowzの日記: C言語で基本的な事を学ぶ2日目 1

日記 by crowz

だいぶ間が空いてしまったが、C言語でカレンダーを実装する作業はすすんでいる。
# とはいえ、作業と呼べるには程遠いが

とりあえず、カレンダーと言えばカギは「日付」と「ループ」と「文字列のフォーマット」だと勝手に思ってる。
それを言語的に順番に考えて見ようと思ったが、C言語の作法的なものとコンパイルの仕方が先だな。

まず、C言語では関数が絶対であるという事。
そしてmainという関数が必ず必要でこれが一番最初に始まるようだ。
(当然ながら)スクリプト言語の用にファイルの先頭から始まるわけでは無く、この関数をまず実行するというのが作法のようだ。
なので絶対にプログラムにはmain関数が存在する。

void main(){
}

関数名の頭のvoidは返り値が無いという意味らしい。
関数の見た目は他の言語と一緒なので特に問題は無い。(他の言語がCを真似しているのだろうけども)

次に文字列の出力。これは

printf("%s", "Hello World\n");

これもどこかで見た事のある関数なので全然問題ない。
これを踏まえたうえでHelloWorldは

void main(){
    printf("%s", "Hello World\n");
}

こんな感じだろう。

次にgccでのコンパイル。
cygwinで作業をしているが、特にGNU/Linux上でも差は無いと思う。
コンパイルの作業は今のところこんな感じ

gcc -o .exe .c

Windows なので exeをつけているが、別につけなくても問題は無かろう。
たぶん-o = outputのファイル名指定 ということだろう
ソースファイル名も.cという拡張子になっているがCのソースであれば別になんでもいいんだろうな。

これでHello worldは完成。

55286 journal

crowzの日記: C言語への理解を深める1日目 1

日記 by crowz

散々御託を並べた後、仕事の合間をぬってC言語を勉強。
C言語は歴史がある事と、色々な幅広い分野で使われているため情報が多いので
とりあえずは本を買って勉強しなくてもよさそうだ。
現在はこのサイトを参考に順番に勉強していっている。
プログラム未経験というわけではないので基本的なところは理解しているつもりだが、
初心に帰って疑問に思った事は調べていこうと思う。

早速順番に読んでいくとプログラムは何かとかそういう基本的なところから入る。
今まで当たり前のように思っていたところを説明してもらうと非常に勉強になる。
(それが実際プログラミングを行うに当たって必要な知識なのかどうかは別かもしれないが)

このサイトによると「C言語は高級言語」とある。ずっと低級言語だと思ってた。
そう思ってWikipediaを見てみるとどうやら中級言語と呼ばれる時もあるみたいなので
微妙なトコロもあるみたいだ。

あと、ANSIの言語仕様に準拠とあるが良く効くANSIってなんだろうと調べてみる。
またまたWikipediaによるとアメリカのJISのようなものだそうだ。
脱線気味だが、ANSIやJISはISOに加盟していると言われてたら、
ANSIはISOじゃないの?とか思ってしまうのだがたぶん理解が浅いためだろう。
# そもそも趣旨が違うのでこれ以上はやめておこう

52253 journal

crowzの日記: C言語を勉強し始めた

日記 by crowz

先日の日記でC言語をやってみようと思い立ったので、まずはもう一つアドバイスをいただいた、
「既に他言語であるアプリケーションの移植」をやってみようと思う。

色々といただいているアドバイスを見ている限りではとりあえず最初はGUIなアプリケーションは
敷居が高そうなので、コンソールアプリケーションを作ってみよう。

さて、何を移植するか?だが、今まで人に僭越ながらもプログラム言語を教えるときは
カレンダーを作ると色々勉強になるよなんて事をよく言っていたので
まずは、コンソールでカレンダーを作ってみる事にする。
機能はとりあえずEmacsのcalendarと同じように3カ月分横に出すだけにしようと思う。
# calコマンドがあるので移植じゃないな。。。
# でも参考になるかも。

そして環境はgcc。 一応Cygwinのgccでやってみる事にするが、linux環境もあるので
両方でコンパイルできてキャキャー言ってみようと思う。

とりあえずC言語を思いっきり楽しみたいと思います。

ところで、言語が決まったのでトピックを「プログラミング」から「C言語」に
変えようと思ったのだけどそんなトピックないのね。

51175 journal

crowzの日記: 新しいプログラミング言語を気合い入れて覚えてみることにする 7

日記 by crowz

昨日の日記にてただの日記にも関わらず多数の有意義なご意見をいただいたので
考え方を改めて新しいプログラム言語の勉強をしてみようと思う。

正直なところ背中を押してもらったようですごくうれしかった。

さて何言語を習得しようか?
大前提として仕事で使い分けではないので(参考書はともかく)なるべくお金はかけたくない。
# とはいえ現在ではお金をかけないと扱えない言語はすごい少ないと思うけど。
あと、できればプラットホームに依存したくない。

ちなみに恥ずかしながら今まで多少なり経験がある言語は
・C++(wxWidgets)簡単なGUIアプリを作った程度(linuxとwindows両方で動いて感動したなぁ)
・lisp (elisp) Emacsな人のため困らない程度に
・PHP
・Smalltalk (squeak) 諸事情により(謎
・Perl
・Ruby 簡単なコンソールRSSリーダを作った程度
・VB
・C# 何個か簡単なアプリを作った。

これら多少なりの経験ではwxWidgets(やってた当時は違う名前だったけど忘れた。。。)
はすごく楽しかったしクロスプラットホームという点でもポイントは高い。
# 言語を覚えるという趣旨とは違っているような気がしないこともないが。

なぜ続けなかったかを思い起こすと、仕事の空き時間にチマチマ書いてたら
職場の同僚に「これ以上のC++はC覚えてないと難しいと思うよ」と言われて
じゃあCやらないとなーとか思ってたらデスマーチに放り込まれたのだった。

C言語は覚えておいてすごく為になる言語だと思うし、プログラマの端くれとして覚えたいというのがある。
それ以上にC言語を覚えれば何でもできる気がする(というかしてきた)
C++の為というのもあるかもしれないがまずは、C言語を扱えるようになってみようと思う。

50574 journal

crowzの日記: 新しいプログラミング言語を覚える為にはどうしたらいいだろうか? 7

日記 by crowz

今までプログラマとして多くのシステムに関わってきたけども
ある程度この業界にいるとプログラム言語を新たに覚えるよりも
今までの経験を生かした(既に習得済みの)プログラム言語での仕事を求められることが多い。

今はプログラマじゃなくてシステム管理業務を主に担っているが
暇を見つけては新しい言語を習得しようとするもなかなか身につかない。

たとえばrubyを覚えようと思ってもPHPやPerlで事足りることが多く、
CやC++を覚えようと思ってもプログラミング初心者の本はあれど、
ある程度CやC++の利点を生かしたプログラミングを習得できる術がない。

CやC++等はOSSプロジェクトからソースを落として勉強すれば良いとよく言われるが
いきなりは敷居が高すぎて全くわからない。

誰でもかける"Hello world"から始まらないプログラム習得方法という選択肢は無いものだろうか?

typodupeerror

開いた括弧は必ず閉じる -- あるプログラマー

読み込み中...