K&R

strftime関数でフォーマット指定して日付の出力

C K&R

K&R本 付録B10printfのようなフォーマット指定子で日付の出力ができるみたいです。さっそくやってみました。 #include <stdio.h> #include <time.h> int main (void) { time_t t = time(NULL); struct tm tm; char str[81]; localtime_s(&tm,&t); strftime(str,sizeof(str),"%</time.h></stdio.h>…

strpbrk関数

C K&R

K&R本 付録B3第二引数のどれかの文字にマッチしたらそのポインタを返す。使ってみます。 #include <stdio.h> #include <string.h> int main (void) { printf("%c\n",*strpbrk("foobar","abc")); return 0; } $ main b文字検索とかで使う?のかな。</string.h></stdio.h>

strspn関数とstrcspn関数

C K&R

K&R本 付録B3 size_t strspn(cs,ct)ctに入っている文字よりなるcsの接頭辞の長さを返すsize_t strcspn(cs,ct)ctにない文字よりなるcsの接頭辞の長さを返す なんかよく意味がわからないので実際に使ってみる。 #include <stdio.h> #include <string.h> int main (void) { printf(</string.h></stdio.h>…

rewind関数

C K&R

K&R本 付録B1.6ファイルポインタの位置を先頭に戻す関数。これはfseekとclearerrの組み合わせと同じ結果になる。 fseek(fp,0,SEEK_SET); clearerr(fp); rewind(fp)で一発で書けるので先頭に戻したいときはこれ使ったほうが楽だね。

K&R本一通り読み終えて

C K&R

付録以外の1〜8章まで全て読み終わりました。基本的な部分は勉強済みだったので割とスンナリ読めました。ただ最後の最後、8.7の記憶割り当ての話はちょっと難しすぎて今の段階では良くわからなかったです。この辺の話をわかりやすく説明してる書籍やWebサイ…

低水準入出力の速度比較

C K&R

K&R本 演習8-1とりあえずファイルのオープンだけでやってみました。 #include <io.h> #include <fcntl.h> #include <stdio.h> #include "mylib.h" #define BUFSIZE 1024 void stdio_cp (void) { FILE *fp; errno_t err; char buf[BUFSIZE]; if ( (err = fopen_s(&fp,"test1.txt","r")</stdio.h></fcntl.h></io.h>…

プログラムから別のコマンドを実行する

C K&R

K&R本 7.8.4system関数を使えば、別のコマンドを実行できる。ためしに自分自身を呼び出すプログラムを書いてみる #include <stdio.h> #include <stdlib.h> int main (int argc,char *argv[]) { int i = 0; char command[100]; if ( argc < 2 ) exit(0); i = atoi(*++argv); if (</stdlib.h></stdio.h>…

入力ストリームへ一文字だけもどせるungetc関数

C K&R

K&R本 7.8.3ungetcを使うとgetchar等で取得した文字を一つだけ戻すことができます。ためしに二つ進んで一つ戻す処理を書いてみます。 #include <stdio.h> int main (void) { int c; int i = 0; while( (c = getchar()) != EOF ) { printf("%c",c); if ( (i = (i+1) % </stdio.h>…

ファイルを比べて違ってる最初の行を表示

C K&R

K&R本 演習7-6 二つのファイルを比べて、違っている最初の行を印字するプログラムを書け。 #include <stdio.h> #include <string.h> #include <stdlib.h> char *getline (FILE *fp) { char str[100]; char *p = NULL; size_t len = 0; size_t lentotal = 0; while ( fgets(str,sizeof(str)</stdlib.h></string.h></stdio.h>…

共用体に先頭要素が共通している構造体が含まれている場合

C K&R

K&R本 付録A8.3 共用体の利用を簡単にするのには、一つ特別な方法が用意されている。ある共用体に、先頭のメンバー並びが共通しているいくつかの構造体が含まれていて、しかも共用体がいまそれらの構造体の一つを保持しているときには、含まれている任意の構…

単語数算出二分木の再帰版

C K&R

K&R本 6.5前回の記事で単語算出の処理を書きました。ですがK&Rのサンプルを見ていると二分木にデータを追加する処理に再帰を使っていました。ということで僕が作ったプログラムも再帰版に書き換えてみようかと思います。 #include <stdio.h> #include <string.h> #include <stdlib.h> #inc</stdlib.h></string.h></stdio.h>…

呼ばれたコマンド名によって処理分けする

C K&R

K&R本 演習7-1 argv[0]にあるどんな名前で呼ばれたかにより、大文字を小文字に、あるいは小文字を大文字に変換するプログラムを書け。 なんだか凄いトリッキーな処理ですね。実行したときの名前によって処理分けするなんて本来ならやっちゃいけなさそうな感…

ハッシュの実装(演習版)

C K&R

K&R本 演習6-5ハッシュの実装は一度やっていますが、K&R本に載っていたハッシュ実装(チェイン法)がなかなか良さそうだったので参考にしながら自分で再実装してみます。また、演習もやってみます。 lookupとinstallによって保守されるテーブルから、名前と定…

単語をグループごとにソート表示

C K&R

K&R本 演習6-2 Cのプログラムを読み込んで、最初の6文字が同じで、その後のどこかが異なっている変数名の各グループを、アルファベット順に印字するプログラムを書け。文字列やコメントの中の単語は数えるな。6はコマンドラインからセットできるパラメータに…

オプション付きソートプログラム

C K&R

K&R本 演習5-14、演習5-15 sortを変更して分類を逆方向にすることを指示する-rというフラグを取り扱えるようにせよ。-rは-nと同時に使えなければならない 分類において、大文字と小文字の区別をなくしてしまうためのオプション-fを加えよ。これによって、大…

総称ポインタを使ったswap関数

C K&R

K&R本 5-11今までswap関数として以下のものを使っていました void swap (int *a, int *b) { int work = *a; *a = *b; *b = work; } しかし、これだと別の型の場合に同じような別の関数を作らなくてはいけないので面倒でした。これに対するK&R本に一つの解が…

単語数算出を二分木でやる

C K&R

K&R本 6.5単語数の算出処理に二分木の話が出てきたので復習がてら実装してみる。 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define WORDMAX 100 struct NODE { char *word; int count; struct NODE *left; struct NODE *right; }; typedef struct NODE NODE</ctype.h></stdlib.h></string.h></stdio.h>…

int (*p[])()ってなんだ?

C K&R

K&R本 5.12複雑な宣言で出てきたこれ int (*p[])(); 所見なんだこりゃってなったけど少し考えてわかった。これはつまり関数ポインタの配列ってことね。関数プロトタイプを宣言してないので一瞬なんだろうと迷ってしまった。これは多分正しく書くなら int (*p…

入力の最後のn行を表示するtailの実装

C K&R

K&R本 演習5-13 入力の最後のn行を印字するプログラムtailを書け。nの省略時仮定値は10であるが、これは省略可能な引数によって変更できるようにし、 tail -nで最後のn行を印字するようにせよ。 難しそうですね。 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #</ctype.h></stdlib.h></string.h></stdio.h>…

タブをスペースに変換するdetab

C K&R

K&R本 演習5-11 プログラムentabとdetabを書き直して、タブストップの並びを引数として受け取るようにせよ。引数がないときは通常のタブ設定を使用せよ。 なんか問題文がややこしいな・・・。とりあえず今回はdetabだけやります。要はタブを4スペースに変換…

正しいポインタの操作

C K&R

K&R本 5.4箇条書きでまとめてみる 同じ型のポインタの代入 ポインタと整数との加算、減算 同じ配列のメンバーに対する二つのポインタの引算と比較 ゼロの代入やゼロとの比較 (void *)の代入 これらがすなわち正しいポインタの操作方法となる。これ以外の操作…

0とNULLの関係

C K&R

K&R本 5.4 Cでは、データを正しく指すポインタは0にならないことを保証しているから、0という戻り値は、異常事態の発生を知らせるのに使うことが出来る。ポインタと整数は相互交換可能ではない。ゼロは唯一の例外である。定数ゼロはポインタへ代入してよく、…

逆ポーランド式を計算するプログラム

C K&R

K&R本 演習5-10 コマンド行からの逆ポーランド式を計算するプログラムexprを書け。各演算子あるいは被演算数は引数として分離されているものとする。例えば expr 2 3 4 + *なら2×(3+4)を計算するようにせよ。 これはかなりプログラムらしい演習ですね。やっ…

strncpy、strncat、strncmpを自作する

C K&R

K&R本 演習5-5 その引数である文字列の最初の最大 n 文字を扱うライブラリ関数strncpy、strncat、strncmpを書け。例えば、strncpy(s,t,n)はtの最大n文字をsにコピーするものにせよ。 まずはstrncpy関数 #include <stdio.h> char *mystrncpy(char *s,char *t,int n) { </stdio.h>…

文字列の終りと比較するstrend関数

C K&R

K&R本 演習5-4 文字列tが文字列sの終りにあるときには1を、そうでないときにはゼロを返す関数strend(s,t)を書け。 #include <stdio.h> #include <string.h> int strend(char *s,char *t) { size_t slen = strlen(s); size_t tlen = strlen(t); if ( slen < tlen ) { return 0; }</string.h></stdio.h>…

atof関数を自作する

C K&R

K&R本 演習4-2 atofを拡張して、次のような科学記法を扱えるようにせよ。 123.45e-6ここで、浮動小数点のうしろには、eやEと符号の付きうる指数部が続いてもよいとする。 #include <stdio.h> #include <ctype.h> #include <math.h> double myatof(char *s) { double type = 1; double e</math.h></ctype.h></stdio.h>…

空の引数リストではなくvoidを使う

C K&R

K&R本 4.2 double atof() のように、関数の宣言が引数を含まないときには、このatofの引数については何も仮定しないものと受け取られ、すべてのパラメータ・チェック機能はオフにされる。空の引数リストが許される特別な理由は、古いCプログラムを新しいコン…

itoa関数の再帰版の実装

C K&R

K&R本 演習4-12 printdのアイデアを使ってitoaの再帰版を書け。すなわち、再帰ルーチンを呼ぶことによって整数を文字列に変換せよ。 再帰を使って変換ですか。面白そうですね。 #include <stdio.h> void myitoa (int n,char *s) { if(n){ int i = 0; int l = n; while</stdio.h>…

文字列から文字群が見つかった位置を返す

C K&R

K&R本 演習2-5 文字列s2の任意の文字と等しい文字列s1の最初の文字位置を返す関数any(s1,s2)を書け。ただし一致する文字がなければ-1を返す。 今度は誤読しないよう。 #include <stdio.h> int any(const char *s1,const char *s2) { const char *s = s2; int i,j; int</stdio.h>…

文字列中のある文字列を除去する

C K&R

K&R本 演習2-4 文字列s2中の任意の文字に等しい文字をs1から除去するような形のsqueeze(s1,s2)を書け。 #include <stdio.h> void squeeze (char *s, char *del) { char *p = del; int len = 0; int i,j,k; while(*del++) { len++; } for(j=i=0;s[i];++i){ if ( s[i] =</stdio.h>…