chevron_left

メインカテゴリーを選択しなおす

cancel
thisdesu
フォロー
住所
未設定
出身
未設定
ブログ村参加

2017/06/16

arrow_drop_down
  • 可変引数

    関数を使ってると引数の個数を可変にしたいなーって思う時があります。これまた難しいのですが、よく使う関数printf系が可変なので身近で使っているから簡単に出来そうなんて思う今日この頃。 可変長引数はコンパイラなど環境依存と言いますがお行儀依存しますので、今回のサンプルが使えないのは覚悟です。はい。 関数定義は、[...]と点を3つほど書けば以後引数は可変ですって事です。 int _myprint(char *name, ...); 取り出し方 va_list : 可変引数の構造体 va_start : 開始位置を構造体へ設定 va_arg : 値を取り出し va_end : 終了宣言 ■サンプ…

  • 配列の個数

    静的に定義した構造体の配列の個数を後で知りたいときに便利です。 仕組み的にはアドレス辺りで説明しましたが、静的にとられた値は全体の領域がsizeofで取れるので、構造体1つのsizeofで割れば良いだけです。これはマクロなんかで用意しておく定番ですね。 ■サンプルコード #include <stdio.h> // 構造体 typedef struct _user { int no; char *name; char *post; char *addrress; } USER; int main() { USER user[] = { {1, "first", "001-0001", "Toky…

  • 実践編:リスト2

    前回のリスト形式の拡張で、特定の値から前の値に手繰れるように拡張します。 前回は新たに作成した時に、一つ前の情報に次の情報を保存しましたが、今回は、作成した情報に1つ前の構造体のアドレスを保存しておく事により、特定の情報を見れれば、前の情報へ手繰れるっと言う仕組みです。 ■サンプルコード #include <stdio.h> #include <stdlib.h> #include <memory.h> // 特定の情報 typedef struct _item { int val; struct _item *prev; struct _item *next; } ITEM; // 情報の追…

  • 実践編:リスト

    そろそろC言語の言語から良く使う手法等のステップアップして実践編へ進みます。(と言うより言語ネタは尽きてきた) 特定の値をリスト形式にしたい場合に、特定の値の中に次の値に辿れる様にする事があります。この特定の値とは構造体で好きな形として定義してやり、この構造体の中に同じ構造体のポインタを保存出来るようにしてあげます。一つの情報を作成したら、次が出来た時点で次の構造体のアドレスを保存してあげる事により、特定の情報を見れれば、次の情報へ手繰れるっと言う仕組みです。 ■サンプルコード #include <stdio.h> #include <stdlib.h> #include <memory.h>…

  • 関数ポインタ

    状態により実行する関数を変えたい!動的に変えたい!などの場合に、実行する箇所で関数ポインタを元に実態の関数を呼ぶようにします。 qsortのブログでもサラッと利用しててスルッと説明を簡略しましたが、目的は同じです。 例:四則演算の関数をポインタを変えて実行します。 #include <stdio.h> int _plus(int a, int b) { return (a+b); } int _minus(int a, int b) { return (a-b); } int _multi(int a, int b) { return (a*b); } int _divi(int a, int…

  • ビットシフト

    名前のとおりビット単位で全bitをシフトします。右(小さく)へシフトさせる場合に[>>]を、左(大きく)へシフトさせる場合には[<<]を指定します。 ビット幅を超えたbitはなくなります。逆に出現したら(逆側から出てきたbit)0です。 #include <stdio.h> void _print(unsigned char val) { unsigned char msk = 128; // 10000000 for( ; msk; msk >>= 1) { if ( val & msk ) putchar('1'); else putchar('0'); } } int main() { …

  • ビット計算2

    ビットを扱うときに、0と1で表示したいなーと誰もが思うはず。たぶん。きっと。かな。。 ここで良くググると見つかる、2進数を表示する関数を書いてみました。 関数[_print]です。1byte(8bit)限定ですです。 予め8bit目が1の値(msk)を用意して(10進数で128)。指定値(val)とmskと論理積(AND)すると、1になるか0になるかを判断して結果をprintfします。 そしてmskの値を1bitつづシフト(>>)して全ビット(8bit)分繰り返します。 #include <stdio.h> void _print(unsigned char val) { unsigned c…

  • マスク計算

    真偽だけのフラグを良く使うことがありますが、さらに種類を設けて1つの値で表現する時などに使います。 例えば、ログ出力用に値を設けて、更に、デバック用・警告用・エラー用・通知用など、場合によって指定したものだけ出したい時に、1つの値で表現できたら便利でしょう。別々にフラグを作るのも大変だし指定するのも至難の業です。 例:値debugに、intの各ビットをフラグとして利用し、各値を1つの値で指定する。 1bit目:デバック用 2bit目:警告用 3bit目:エラー用 4bit目:通知用 指定は各ビットのフラグを設定後の値を指定(分かりやすいので10進で指定しています) #include <stdi…

  • ビット計算

    パソコンの扱う値は突き詰めれば0と1(2進数)です。char型の値も1byteで8bitですから、8個のビットが並んでいます。 これらビットを計算で数式がなりたっています。予め2進数を覚えておきましょう。 00000000 (10進数で0です) 00000001(10進数で1です) 00000010(10進数で2です) ■論理積(AND) どちらも1の場合1になる 00000101 00000011 ---------------------- 00000001 ■論理和(OR) どちらかが1の場合1になる 00000101 00000011 ---------------------- 00…

  • 反転っす!

    ifなので真(1以上)か偽(0)を判定する場合に、結果を入れ替えて解釈して欲しいことがあります。 これは単に反対の判定文すれば良いんですが、関数の結果で0を真として扱いたい、とか反対で判定すると、他の判定とことなり意味的に真なのか偽なのか統一感がなくなってバグを作り出す原因にもなります。あくまでもコーディングとしては変わりないのですが、、、値の前に[!]をつけることにより反転されます。 #include <stdio.h> int main() { int a; a =1; printf("%d\n",a); if ( a ) { printf("test %d\n",a); } printf…

  • マクロ

    プログラムを長く書き始めると、決まった値や簡単な書式を繰り返し書くのが面倒になったり、変えたい時に全部を変えなければいけなくて1つ忘れたら大変なことに。。。this is バグ. そんな時に定義(define)してしまいましょう。 使い方は同じですけど、一般的には値などは定数と呼び。計算式などマクロと呼んでます。※もしかしたら方言かもしれません。あしからず #define 名前 値など #define 名前(a) いろいろ(a) プリプロで名前が値に置き換わるだけですので、コンパイルエラーには出てきませんので要注意 #include <stdio.h> #define SHOHIZEI 8 #…

  • 設定(イコール)

    いまさらだけど、設定って[=]で左辺に右辺の値を同じにする事ですが、書式的に連続しても同じになります。 int main() { int a; int b; int c; a = c = b = 10; printf("a:%d\n",a); printf("b:%d\n",b); printf("c:%d\n",c); } ■実行結果 $ gcc main.c $ ./a.out a:10 b:10 c:10

  • 実用:並び替え(qsort)

    そろそろプログラム的な事も混ぜてきしょう。っでソート。 良くある実用事例で、沢山有るデータを何らかの基準を設けて並べる(ソート関数)を使ってみましょう。もちろん自分でソート関数も作ることは出来ますが、ここままず、標準である二分岐ソート(qsort)を使ってみます。 void qsort(void *base, size_t nmemb, size_t size,int(*compar)(const void *, const void *)); さて、いきなり関数が第4引数にある例ですが、この関数は自分で基準を指定する所なので、構造体の一部を指定したりして色々な昇順降順を決定することが出来ます…

  • 型作っちゃうぞ

    構造体や列挙体などいちいち宣言するのが長いものや、既存の型を、ちょっと分かりやすく名称をしたい場合に利用します。 作る場合の宣言として[typedef]を利用します。ちなみに、本当に新しい型を作れるものでないので要注意。てかC言語は未知の型は作れませんです。既存の型と同じなのでCASTしなくても大丈夫です。 例 integer と言うint型の型を作成する。 typedef int integer; int main() { int a; integer b; a=10; b=a; printf("[%d][%d]\n",a,b); } $ gcc main.c $ ./a.out [10][…

  • 列挙型(emun)

    列挙型とはちょっと分かり難いけど、実値にこだわらず沢山の定数が必要な時に便利です。実値はユニークが保障されているし列挙した順に1から順に振ってくれます。 enum TODOU { HOKKAIDO, AOMORI, IWATE } ; int main() { enum TODOU admin; printf("[%d]\n", HOKKAIDO ); printf("[%d]\n", AOMORI ); printf("[%d]\n", IWATE ); } 実行 $ gcc main.c $ ./a.out 1 2 3 でも、番号を指定したいなーっと思ったら=で設定して下さい。以後はその値…

  • 構造体(struct)

    沢山の変数を扱うときに決まった並びや、それを繰り返し利用する際に、この体系を定義するのを構造体と言います。 名前は何でもよいです。(予約名は除く)例えばint,int,char[10]の変数の並びの構造体を、kata と言う名前として定義も可能です。 struct kata { int first; int second; char third[10]; }; 宣言する時は普通の変数の時と同じで、配列も出来ますしポインターとしても出来ます。 int main { struct kata nor; struct kata arr[10]; struct kata *ptr; } この構造体の中の…

  • ちょっと一息(include)

    インクルード(include)とは、#include と書いた位置に指定したファイルを埋め込みます。同じ記述を使いたい場合にはincludeで読み込みましょう。どんな感じに読まれるのはコンパイラのプリプロのブログ参照してください。 よく使うのはヘッダファイルと言われる拡張子[.h]のファイル。これってただの作法です。ファイル名なので何でもいいです。 main.c #include <stdio.h> #include "this.desu" int main(){ printf("%s\n",FOO); return; } this.desu #define FOO "bar" $ gcc m…

  • 文字区切りstrtok

    文字列を特定の文字ごとに区切りたい時など便利か関数=strtokです。例えば"123-456-78-9-0A"の文字列が在った時に、-で区切って簡単に取得したいときに便利です。 が、、、、この関数には2つの悪魔が住んでるので要注意。後から説明します ■サンプル #include <stdio.h> #include <string.h> int main() { char string[] ="123-456-78-9-0A"; char *p; p = strtok(string,"-"); while( p != 0x00 ) { printf("[%s]\n",p); p = strto…

  • printf

    C言語では最もよく使う関数でしょう(派生も含め)。この関数は色んな型の値を指定した書式で表示(標準出力)してくれる関数ですが、この指定の仕方が沢山あって覚えるのが大変なのですが、基本的なものは覚えましょう。 ■printf書式 printf("フォーマット",値1,値2,,,,); フォーマットは固定の文字も含む事が出来て、このフォーマットの中に値の書式を指定します。書式は[%]から始まる記号で構造の値の数だけ指定でき、左から値の順に指定することになります。 ただし、値の型と指定した書式と形式が有っていないと意図しない結果や落ちますので要注意。 ■指定書式 %c :1文字を表示しますchar型…

  • 四則演算

    すこし基本に戻って四則演算を頑張ってみる。 基本的には数式と変わり有りませんが、ちょっと記号が異なるので要注意。 + :足し算 - :引き算 * :掛け算 / :割り算 % :余り ■サンプル(intの例) #include <stdio.h> int main() { int s; int d; s = 11; d = 5; printf("%d\n", ( s + d ) ); printf("%d\n", ( s - d ) ); printf("%d\n", ( s * d ) ); printf("%d\n", ( s / d ) ); printf("%d\n", ( s % d …

  • メモリー

    C言語で通なければならない関門のメモリ。使ってるメモリが状態がどうなってて、何をどう使ってるのを把握しておかないとnull pointerでスタックトレースなんて生温い結果じゃなくて、segmentation fault。はい終了。原因なんて教えてくれれやしない。プログラム終了。「落ちた」なんて連呼されることになります。 メモリは静的メモリと動的メモリの2種類があります。静的メモリとは変数を宣言したら勝手に確保してくれるお手軽メモリ。「 char a[10] 」でsize(char*10)分のメモリが自動で確保されます。しかし、動的メモリは自分で確保してから変数に割り当ててあげなければなりませ…

  • キャスト(型変換)

    値を設定する際に=を挟んで、左辺と右辺の型が違う場合にキャストを行います。明示的にキャストをする場合と、暗黙的に行われる2つがあります。 暗黙的に行われる場合とは、型の相違が有った場合にキャスト指定が無い場合には優先順を元に自動で変換されます。 優先: char < int < long < float < double 明示的に変換する場合には、設定元の値(右辺)に対して「(型)」を使って指定すると変換されます。 例題:暗黙変換と明示変換 int main(){ float a; // 暗黙に右辺の(int)型キャストされ設定 // int型(精度無し)なので小数点以下が落ちている a = …

  • アドレスとポインタ

    C言語はメモリ空間を直接感じれる言語です。Javaとかスクリプト系の言語では余り感じられないと思います。あえて隠していますが。 メモリ空間を直接扱うのはとっても早いのですが、ひとつ間違うだけでエラー発生プログラム終了!高確率でフリーズ。下手するとOSクラッシュなんてことも有りますので心してかかりましょう。 アドレスとはメモリ空間の番地でまさしくメモリの住所の事を指します。プログラムがメモリ上で関数も変数も静的な値も全てメモリに書かれていて、書かれている場所には全てアドレスが付いています。アドレスは実行する度に変わりますので固定ではありません。 ポインタとは、名前のとおりアドレスを指す仕組みです…

  • 参考書

    C言語を覚える時に、まず参考書を買う人は多いでしょう。最近はインターネットで調べることも多くなりましたが、やっぱり手元で開いて何度も読み返しながら勉強するのは学生の時からの性なのでしょうか。もちろん私もです。 昔から知ってる書籍をあげてみます。参考までに 「プログラミング言語C」共立出版 ANSI規格準拠 B.W.カーニハン/D.M.リッチー(著) 「CユーザのためのANSI C言語大辞典」パーソナルメディア マーク・ウィリアムズ社(著,編集) 「C言語による最新アルゴリズム事典」技術評論社 奥村晴彦(著) 「C実践プログラミング」O'Reilly Steve Oualline(著) 「標準C…

  • 低水準や高水準関数とは

    C言語の本や説明の中に、よく低水準関数とか高水準関数とかの言葉が出てきます。これは用意されている関数が、OS(オペレーションシステム)に依存するような関数なのかどうか、明確な境界線はありませんが、OSに近い(OSが違ったら動かないかもしれなさそう)関数を低水準関数といい、OS依存が少ない汎用性が高い関数を高水準関数と言います。低水準は速度が速いとか細かく操作が出来るなど利点が有りますが、同じプログラムがOSが変わると動かなかったり、そもその関数が用意されていない事も有ります。高水準は汎用的な作りにしていて速度が遅かったり細かな所に手が届かなかったりと欠点は有りますが、移植性が高く生産性などメリ…

  • ファイル操作(fopen,fgets,fputs,feof,fclose)

    ファイルのやり取りする関数を使ってみましょう。ファイルを扱うには基本的な作法があります。まず最初にファイルを開く(open)しなければなりません。そして開いたファイルに対して読み込み(read)や書き込み(write)が行えます。またファイルを開く際には、読み込みをするのか、書き込みするのかなど指定しておく必要があります。最後にファイルを閉じ(close)ます。これをしないと他でファイルが開けなくてエラーが発生しますので必ず行いましょう。 今回は例として、テキストファイルのコピーする例です。また高水準関数(*1)を使ってお手軽簡易版コピーです。 ■流れ 1. コピー元ファイルを読み込み指定で開…

  • コーヒーブレイク(IOCCC)

    プログラミングとスパゲッティは密接で、タコ足のコンセントなんか目じゃないほど、絡まりに絡まったソースプログラムは人の手を介す度に解かれず放置されたのか見て見ぬふりと言うか触らぬ神に祟り無しなのか、、、完全にブラックボックスと化したプログラムに出会ったしまったら、、僕もきっと解読する勇気よりクライアントに”作り直しましょう”と言う理由を模索し始めるでしょう。 ただセキュリティーの風潮なのかリバースエンジニアリング防止なのか、そのまま利用できるスクリプト系のプログラムやHTMLなどにおいては、あえて難読化して動きを見せなくする・盗用させなくする様な事も行われています。特にgoogleなんで検索結果…

  • 関数って、、

    関数とは処理を一まとめにした塊を、いろんな所で使いたい!使いまわししたい時に、「関数」って枠組みで作っておくと、色々なところから使えるようになります。この「関数」を使うには作法というかルールがあり、そのルールの事を関数インタフェース仕様とかリファレンスとか呼ばれます。ルールには大きく2つあります。1つ目は関数にデータを与えるルール。後に出てきますが”引数”と呼ばれる部分です。2つ目は関数から渡されるルール。これも後に出てきますが”戻り値”と呼ばれる部分です。このように関数に”何”を渡して、”何”が返ってくるかのルールを知ることで、関数を使えたり、関数を作れたりします。 この2つ特徴として、”引…

  • コピー

    プログラムで良く使うのが、変数に値を設定する事です。ここでは値の型によって設定する方法が異なったり、便利な関数を使ったりする方法をご紹介です。値の設定の基本は、"="を挟んで右から左に値をコピーします。あと同じ型同士でないとコンパイルの時にひどく怒られます。無理やり入れたい場合は右側の型を変化(cast)させる手も有りますが初めの内は避けたほうが良いかも ■=でのコピー #include <stdio.h> int main(int argc,char **argv) { int a; int aa; char b; char c[3]; a = 10; // aに10を設定 aa = a; …

  • 文字列(string)の闇

    C言語の型として1文字の「文字」(char)は有りますが、連続した文字の「文字列」という型は存在しません。しかしC言語を使ってシステムを作成するには文字列を避けて通れません。数字のみの学術系なら別ですが。 この文字列を表現するのに、連続した文字(char)の領域を利用し、先頭から文字を設定し終わり表す値(0x00)別名ヌル(null)を設定し、先頭からnullまでの連続した領域を文字列として表現しています。注意点は文字列の終わりがnullとしているだけで領域の終わりを指していません。またnullを設定する領域も必要です。ここ勘違いするとstringの闇にはまります。 ちなみにヌルは、ただの0で…

arrow_drop_down

ブログリーダー」を活用して、thisdesuさんをフォローしませんか?

ハンドル名
thisdesuさん
ブログタイトル
C言語はじめました
フォロー
C言語はじめました

にほんブログ村 カテゴリー一覧

商用