サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
デスク環境を整える
www1.cts.ne.jp/~clab
[書式付き出力と書式指定子]←このソース→[関数の戻り値] /* limits.hに色々なタイプのCの整数の最大値と、最小値が文字定数として定義されています。文字定数は伝統的に大文字で記述する習慣になっています。今日のプログラムは、その値を表示します。今日のソースプログラムは、説明のいらない程簡単です。実行結果にも注目して下さい。 */ /* ここからソースプログラム */ #include <stdio.h> #include <limits.h> /* 文字定数が定義されている */ void main(void); void main(void) { printf("char のサイズ: %d bit\n", CHAR_BIT); printf("char の最大値: %u\n", CHAR_MAX); printf("char の最小値: %d\n", CHAR_MIN); pri
ファイルに関する豆知識 標準出力(stdout)と標準エラー出力(stderr)の違いについては、バッファリング有り無しを参照のこと。 printf( )はstdoutに文字を書き込みます。printf("あれ\n");とfprintf(stdout, "これ\n");は同じです。 scanf( )はstdinから文字を読み取ります。 stdio.hの中に、"#define FOPEN_MAX 15"と記述されていたら、1度に開くことのできるファイルの数は15です。 ファイルはEOFという、特別な値で終了します。stdio.hの中に、"#define EOF (-1)"と記述されているはずです。 ファイル操作に関わる関数には、低水準ファイル入出力関数(レベル1)と、高水準ファイル入出力関数(レベル2)があります。低水準ファイル入出力関数は、バファリングその他のサービスをしない、よりOSに近
[整数の内部表現]←このソース→[NDEBUGマクロとassert( )] /* limits.h の中の記号定数 */ /* 今日は、printf( ) で整数を表示する際に、変数が書式指定子の範囲を超えていたら、どうなるかについて実験します。 整数の取り得る範囲については、limits.h の中で記号定数を使って、次のように記述されています。 CHAR_BIT 8 // char 型は8ビット CHAR_MAX UCHAR_MAX // char 型とunsigned char 型の最大値は同じ CHAR_MIN 0 // char 型の最小値 INT_MAX +32767 // int 型の最大値 INT_MIN -32768 // int 型の最小値 LONG_MAX +2147483647L // long 型の最大値 LONG_MIN -2147483648L // long
[エラーメッセージ]←このソース→[バブルソート] /* 悪質なバグ */ /* 注意:このソースプログラムには、悪質なバグがあります。コンパイルして実行すると、画面に異常な文字が表示されたり、最悪の場合、システムがクラッシュして、暴走します。もし、実行するなら、下の説明文を充分読んでからにして下さい。 Cのコンパイラは、特に、ポインタに対しては、文法チェックが甘くできています。このため、コンパイルをうまく通り抜け、実行時にエラーとなることがあります。その中でも、特に悪質なのは、バグのあるステップが実行されても、一見正常に動作したり、しばらくしてから動作が異常になったり、最悪の場合システムがクラッシュするバグです。バグのあるステップと異常の現れるステップが、別の箇所なのでバグの発見が困難です。 今日は、4つの関数が出てきますが、最後の関数の中にこの種のバグがあります。これらの関数は全て、s
[ビンソート]←このソース→[クイックソート] /* ヒープソート */ /* 今日は2分木 ( ヒープ ) というデータ構造のうち、半順序木を使って行う、高速なソートのアルゴリズムであるヒープソートについて学びます。 2分木というデータ構造については、既に、学んでいますが、復習します。下記の node[ ] という配列の添字 0 は使いませんので、それは無視して下さい。数字を斜めの線で結んでいませんが、1と 2、1 と 3、2 と 4、2 と 5、3 と 6、3 と 7 が、線で結ばれているものとします。 int node[ ] = {0, 1, 2, 3, 4, 5, 6, 7, }; このようなデータ構造を、枝が一度に二つに分かれる木に見立てて、2分木といいます。一つ下の二つの要素を子、一つ上の要素を親といいます。一番上の要素を根といいます。つまり、2分木は逆さに生えている木です。
サイトマップ / C言語講座>出入り口>総目次>目次:再帰>フィボナッチ数列を表示する関数(動的計画法版) フィボナッチ数列を表示する関数(動的計画法版) [フィボナッチ数列(再帰改良版)]←このソース→[ファイル操作の基本] /* ソースプログラムの説明 今回もフィボナッチ数を求める関数を作ります。前回、前々回は再帰的呼び出しを使ってフィボナッチ数を求めました。今回は、違う方法で、しかも、もっと高速に求めます。まず、フィボナッチ数の定義にもう一度戻ります。フィボナッチ数とは、 i = 1 の時 Fibo(1) = 1 i = 2 の時 Fibo(2) = 1 i = 3 の時 Fibo(3) = 2 i = 4 の時 Fibo(4) = 3 i = 5 の時 Fibo(5) = 5 - - - - - - i = n の時 Fibo(n) = Fibo(n - 1) + Fibo(n -
[キーボードから1行入力]←このソース→[書式付き入力と書式指定子] /* 今日は、標準ライブラリ関数gets( )の問題点と、fgets( )による問題解決の話です。 #include <stdio.h> char *gets(char *s); 使用例:gets(s); 実行結 戻り値 成功 s 失敗 NULL gets( )は、標準入力(stdin:キーボード)から1行を読み込みsにしまいます。改行コード(\n)または EOF に出会うと、s に ヌル文字(\0)を追加して戻ります。次のプログラムを検討して見て下さい。重大な問題点があります。 #include <stdio.h> void main(void); void main(void) { char name[21]; printf("お名前を入力して下さい\t"); gets(name); printf("\nあなたのお名
サイトマップ / C言語講座>出入り口>総目次>目次:ヒープ領域 目次:ヒープ領域 [ソート]←ヒープ領域 ヒープ領域にメモリを確保する方法や、様々なデータ構造について学びます。 C言語講座>出入り口>総目次>目次:ヒープ領域>ソース(1)||ソース(2) C言語講座>出入り口>総目次>目次:ヒープ領域>ソース(1)||ソース(2) 上記は柱の見本です。”分割コンパイル”と”双方向リスト”には複数のソースがあります。トグルスイッチになっています。グレーの部分をクリックするとそのページへ移動します。
[読み込みモードで開く]←このソース→[印字可能な文字の数を数える] /* ソースプログラムの説明 */ /* 今日もファイルを読み込みモードで開き、各行に行番号を付けて標準出力に出力します。まず最初にこのファイルを開いて下さい。このページのソースプログラムをコンパイルしてできたexeファイルと、このファイルを同じディレクトリにおいて実行して下さい。その際、このファイルの名前を必ず、”LTest.c”にして下さい。また、このファイルをコピーアンドペーストするときは、必ず最後のリターンコードまでコピーして下さい。そうしないと、正常に動作しません。読者の方、ご指摘ありがとうございました。 前回は、ファイルから1文字読み込むライブラリ関数、getc( ) と、標準出力に1文字出力する関数、putchar( ) を、使いました。今回は、行単位で文字列を読み込む関数と、書き込む関数、fgets( )
[ポインタの配列(2)]←このソース→[関数や変数のメモリ配置] /* 複数の値を返す関数は既出の変数の値を交換で扱っています。復習を兼ね、複数の値を返す関数についてより深く学習します。 複数の値を返す関数 関数の戻り値は1つです。複数の値を戻り値として必要な場合もあります。一般に、2つ以上の値を返す関数はポインタを使います。ポインタを使わない場合は、グローバル変数(外部変数)を使うことになります。安易にグローバル変数を使うのはプログラムの保守上好ましくありません。 ソースプログラムの説明 今日は、数字を入力するとその値の2乗と3乗を返す関数を作ります。関数の名前をPower( )とします。 Power( )は3つの引数を取ります。最初の引数は入力された値です。これはdouble型の浮動小数点数です。後の2つは、double型のポインタです。関数の中では、受け取った値を2乗と3乗して、ポイ
[特定の文字の現れる位置]←このソース→[変数の値を交換] /* ソースプログラムの説明 標準ライブラリ関数に英小文字であれば大文字を、そうでなければその文字をそのまま返す関数と、英大文字であれば小文字を、そうでなければその文字をそのまま返す関数があります。下記を参照して下さい。 #include <ctype.h> int toupper(int c); 例:toupper(c); 戻り値 c が英小文字であれば大文字、 そうでなければcをそのまま返す #include <ctype.h> int tolower(int c); 例:tolower(c); 戻り値 c が英大文字であれば小文字、 そうでなければcをそのまま返す 大文字と小文字についてはすでに文字列を比較で扱いました。今日は、文字列の各文字に対して同様の操作をする関数を作ります。関数は文字列へのポインタを引数にとり、文字列
[現在時刻と年月日と曜日を表示]←このソース→[ビットシフト] /* 今回も時間の話です。西暦 2000 年1月1日からの秒数を計算して、表示します。 */ /* mktime( ) */ /* 今回使う標準ライブラリ関数は、mktime( ) と difftime( ) です。mktime( ) は localtime( ) の逆の働きをします。つまり時間を表す構造体 struct tm を、西暦 1970 年1月1日からの経過秒数に変換します。 #include <time.h> time_t mktime(struct tm *timeptr); 例:time = mktime(&date); 時間を表す構造体 struct tm は前回も示しましたが、もう一度下記に示します。 struct tm { int tm_sec; // 秒 int tm_min; // 分 int tm_
上記の表に関して ・バイト数および取りうる値の範囲は、ハードウエアによって違うことがあり。 ・char は character(文字)の略。 ・int は integer(整数)の略。 ・unsigned は符号なし。 ・float は浮動小数点数。 ・doubleは倍精度浮動小数点数。 ・long doubleを使える処理系もあり。 浮動小数点数を表すfloat型は計算する時double型に変換してから行われます。次いで計算結果をfloat型に戻します。このため、double型の計算より余分に時間がかかります。メモリが貴重だった過去の時代の遺物です。実際に使う可能性はありません。 今すぐ全てのデータ型を覚える必要はありませんが、学習が進むと上記のデータ型が出てきます。 今日のソースプログラムでは、幾つかのデータ型の局所変数を宣言し、それを初期化し、その値を printf( )で表示します
[三項演算子(2)]←このソース→[gotoとlabel] /* マクロ処理 */ /* マクロ処理について学びます。ソースプログラムがコンパイルされる前にプリプロセッサが働きます。マクロ処理とは、マクロ名で指定した文字列をプリプロセッサによって置き換えることをいいます。具体例を挙げます。 #define abs(a) ((a) < 0 ? - (a) : (a)) abs(a)の後ろに、スペースが一つ入っています。マクロ処理はつぎの形式で指定します。 #define マクロ名 パターン 上記の例では、マクロ名は abs(a)です。パターンは ((a) < 0 ? - (a) : (a)) です。マクロ名とパターンの間にはスペースかタブが必要です。 重要:マクロ名の中にスペースやタブを入れてはならない。 ソースプログラムの中にこの1行があると、以後、指定したマクロ名があるとパターンに置き換
[NDEBUGマクロとassert( )]←このソース→[悪質なバグの例] /* エラーを示すグローバル変数 */ /* errno はエラーを示すグローバル変数です。プログラム起動時に、0に初期化されます。標準ライブラリ関数のあるものは、エラーを検出すると、エラーの種類に応じて、error.h に定義されているエラー番号をerrno にセットします。 エラーを検出するには、既に呼ばれた他の関数によって、エラー番号がセットされている可能性があるので、関数を呼び出す直前に errno を0に再初期化して置き、関数を呼び出した直後に errno の値を調べます。 今回は、平方根を返すライブラリ関数を例にして、エラーの検出について学びます。平方根を返すライブラリ関数を下記に示します。 #include <math.h> double sqrt(double x); 例:y = sqrt(x);
[sizeof( )演算子]←このソース→[平均と標準偏差] /* トークン */ /* コンパイラはソースプログラムを分解してからそれを解析します。分解の最小単位をトークン(token)といいます。文字列をトークンに分解するには、標準ライブラリ関数strtok( )を使います。 #include <string.h> char *strtok(char *s, const char *t); 例:p = strtok(s, t); 実行結果 戻り値 成功 トークンへのポインタ 失敗 NULL strtok( )は最初の引数で指定された文字列を、2番目の引数で指定された区切り文字をもとに、トークンに分解します。区切り文字は複数指定できます。2度目以降のstrtok( )の呼び出しは、最初の引数をNULLポインタにします。 ポインタについては後の学習で詳しく説明しますが、戻り値がトークンへの
サイトマップ / C言語講座>出入り口>総目次>目次:ヒープ領域>リスト型のデータ構造 リスト型のデータ構造 [分割コンパイル]←このソース→[ハッシュテーブル] /* プログラムが起動するとメモリアドレスの小さい方から順に、コードセグメント、データセグメント、そしてプログラム実行時に必要に応じて、動的にメモリが確保されるヒープ領域が取られます。 ヒープ領域にメモリが確保されるのは、例えば、calloc( ) や malloc( ) の呼び出し時です。 */ /* スタック */ /* これとは別に、上記のメモリと不連続に、上位のメモリから下位のメモリに向けて、スタックという領域がとられます。関数を呼び出すと、スタックに戻り場所や変数の値を ( 引数 ) を積んで制御が関数に移ります。呼ばれた関数はスタックから値を取り込みます ( Call by value )。 関数の再帰的呼び出しでは
サイトマップ / C言語講座>出入り口>総目次>目次:ソート 目次:ソート [バグ対策]←ソート→[ヒープ領域] 低速なものから高速なものまで、様々なソート(並び替え)のアルゴリズムについて学びます。
サイトマップ / C言語講座>出入り口>総目次>目次:流れの制御>switch - case文による分岐 switch - case文による分岐 [if ( ) - else文(2)]←このソース→[三項演算子(1)] /* switch - case文 */ /* 今日は、switch - case文について学びます。一般的な形式を下に示します。 switch (c) { case A: 処理 A; break; case B: 処理 B; break; case C:処理 C; break; - - - - - - - - - - - - - - - - - - default:処理 N; } c には、int型の変数が入ります。c の値が A なら、処理Aが行われます。以下同様です。default:は、オプションです。"オプションです" という表現は"なくても良い"と同義です。 もし
[書式付き入力と書式指定子]←このソース→[色々なデータ型の最大値、最小値] /* 書式指定子の詳細説明 */ /* 今日は、書式付き出力で使用される書式指定子について詳しく学びます。書式付き出力を行う標準ライブラリ関数には次のものがあります。 prinft( ), fprintf( ), sprintf( ), vprintf( ), vfprintf( ), vsprintf( ) 書式付き出力で使われる書式指定子は次の形をしています。 %[フラグ][フィールドサイズ][.[精度]][引数サイズ] 変換文字 フラグ:指定子を修飾。いくつ付けても良い。
[二分木探索(バイナリサーチ)]←このソース→[起動後の経過時間] /* バッファリング */ /* 標準ライブラリ関数 setbuf( ) について学びます。 ストリームとは、ソフトウエアが文字を読み書きする対象のことです。ストリームは、ファイルか、キーボードかコンソールになります。setbuf( ) は、ストリームに対し、バッファリングするかしないか指定します。バッファリングしないと、ストリームに対し、文字を一字づつ読み込みまたは書き込みます。バッファリングすると、書き込みに対しては、文字を受け取り、バッファが満杯になると書き込みます。読み込みに対しては、文字を渡し、バッファが空になると、満たします。 fopen( ) は、ファイルを開いて、このファイルのストリームにバッファを、自動的に割り当て、バッファリングした状態に設定します。バッファのサイズは、記号定数BUFSIZE と見なされ
[現在の年月日と時刻]←このソース→[ある時刻からの経過時間] /* #include <time.h> time_t time(time_t *timer); 例:time(&timer); 前回は、上記に示す時間に関する標準ライブラリ関数 time( ) を使って、グリニッジ標準時1970年1月1日0時0分0秒からの経過時間を得て、自前で、年月日と時間を割り出しました。しかし、標準ライブラリ関数の中にそれをやってくれる関数があります。 */ /* 年月日と時間を表示する関数 */ /* localtime( ) ですが、この関数を呼び出す前に time( ) を呼び出して、timer に経過時間を入れておく必要があります。 #include <time.h> struct tm *localtime(const time_t *timer); 例:time(&timer); date
~3 の第 0 ビットを立てたものが、- 3 です。つまり、ビットを反転して、1 を加えれば、マイナスの数になります。この操作のことを、「 2 の補数を求める」といいます。コンピュータはこのような方法で、マイナスの値を内部表現しています。 符号付きの整数は最上位ビット ( MSB ) が1ならばマイナスの値です。符号なし整数は最上位ビットも数を表すのに使います。 ビット毎の排他的論理和 前回はビット毎の論理和と論理積について学びました。これ以外にも、ビット毎の排他的論理和 ( XOR 演算記号:^)があります。ビット毎の排他的論理和とは、1 と 1 なら 0 に、1 と 0 なら 1 に、0 と 0 なら 0 になります。今回のソースプログラムでは、ビットを 0 にするのに使っています。 ソースプログラムの説明 今回のソースプログラムで、ビットパターンを表示する関数がでてきます。短い関数で
[gotoとlabel]←このソース[キーボードから1行入力] /* getchar( ) と putchar( ) */ /* 今回は標準ライブラリ関数 getchar( )とputchar( )について少し詳しく説明します。getchar( ) は、'stdio.h'をインクルードして使います。 #include <stdio.h> int getchar(void); 例:c = getchar( ); 実行結果 戻り値 成功 入力した1文字 失敗 EOF getchar( )は標準入力(キーボード)から1文字入力して、上の例では c に代入します。getchar( )は関数ではなく、マクロとして定義されています。 #define getchar( ) getc(stdin) 上記コードの意味は「もし、ソースプログラム中に'getchar( )'があれば、プリプロセッサは'getc(
10 進数で 1 2 4 8 16 32 64 128 のビットパターンにに注目して下さい。数字が 2 倍になると、1 が 1 ビット左へ移動しています。このことを 1 ビット左へシフトするといいます。数字が 1 / 2 になると 1 ビット右へシフトします。2 ビット右へシフトさせれば、1 / 4 になります。 ビット演算子 ビットを直接操作する演算子があります。ビット演算子といいます。'<<' は左シフト、'>>' は右シフトさせるビット演算子です。この演算子のことを、シフト演算子と呼びます。 算術演算子を使って 2 倍したり、 1 / 2 倍するのに比較すると、はるかに高速です。 c が unsigned int 型の整数とすると、この演算子は下記のように使います。 c = c << 1; // 1 ビット左へシフト c = c >> 2; // 2 ビット右へシフト 今回のソースプ
[トップページへ][戻る] C言語講座>サイトマップ>アルゴリズム研究室 アルゴリズム研究室 アルゴリズム研究室−初級 文字'c'が英小文字か大文字か数字か調べる 16進文字列を10進数に変換 絶対値を返す関数 二つの数字のうち大きい方の数を返す関数 偶数か奇数か調べる関数 英小文字を大文字に変換 マクロ処理で絶対値を求める マクロ処理で2乗を求める マクロ処理で大きい方の値を返す マクロ処理で小さい方の値を返す 入力を c に代入し、'EOF' でない間、ループする 二つの整数の平均を返す関数 指定した範囲の整数の乱数を発生させる 偶数ならTRUEを奇数ならFALSEを返す 文字列を浮動小数点数に変換 文字列からトークンを取り出す 標準偏差を求める 16進文字列を10進数に変換する 二つの複素数の和を返す 二つの複素数の積を返す 整数かどうか調べる ポアッソン分布の計算 階乗の計算 クラ
サイトマップ / C言語講座>出入り口>総目次>目次:バグ対策>NDEBUGマクロとassert( ) NDEBUGマクロとassert( ) [整数の取り得る範囲]←このソース→[エラーメッセージ] /* assert( ) と abort( ) */ /* 今日は、assert( ) と abort( ) について学びます。 #include <assert.h> void assert(int expression) ; 例:assert(expression); 戻り値:なし assert( ) は、assert.h の中で、マクロとして宣言されています。assert( ) は与えられた条件が、成立しているか調べ、expression の値が0ならば、標準エラー出力( stderr )にメッセージを表示して、abort( ) を呼び出し、プログラムを異常終了させますexpressi
[ヒープソート]←このソース→[メモリの割り付] /* クイックソート */ /* 今日は一連のソートのアルゴリズムの学習の総仕上げとして、クイックソートについて学びます。クイックソートは、名前の通り高速なソートです。クイックソートのアルゴリズムについて説明します。 int 型の配列 x[ ] をソートするとします。 配列の中央付近の要素の値を基準にします。 配列の添字の小さい方から基準値に向かって、 基準値より大きい値を探します。 配列の添字の大きい方から基準値に向かって、 基準値より小さい値を探します。 見つかったら、双方を交換します。 これを両者が衝突するまで行います。 その結果基準値より小さな値が、基準値の左に、大きな値が右にきます。 次いで、基準値の左の配列と右の配列に対して、同じ操作をします。 配列の要素が 1 になるまで、上記の操作を行えば、ソートが完了します。 具体例を下記
[研究室][初級(1)][初級(2)][中級(1)][中級(2)][上級][ソート] このサイトで公開している教材へのリンクを貼って作っただけの研究室です。 ”アルゴリズム”とは あまりなじみのある言葉ではありませんが、日本語では”算法”ということもあります。問題を解決するための手順のことです。 プログラムを作るということは、ある問題を解決することです。解決するためには、その問題を機能ごとに分解していき、最終的に最小の機能まで分解します。それぞれの最小の機能を解決するための手順を作って、今度は最小の機能を組み立てていきます。先人により考え出された優れたアルゴリズムを学ぶことにより、よりよいソースプログラムを書くことができるようになるかも知れません。また、論理的思考回路が強化され、新たによりよいアルゴリズムを考え出せるようになるかも知れません。 良いアルゴリズム、悪いアルゴリズム 良いアルゴ
次のページ
このページを最初にブックマークしてみませんか?
『www1.cts.ne.jp』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く