TPY ENGINEERING VLOG

TPY ENGINEERING VLOG(C,JAVA)

*C言語* 〜51時限目〜 組み込みマクロを使う・・・

〜目次〜

 

 

 

組み込みマクロを使う

デバッグ作業において便利な機能をもう一つ学びます。

C言語の環境には、

以下のような標準的なマクロが定義されています。

f:id:YuyaTerayama:20180919055517p:plain

これらのマクロは、

ソースファイルに関する情報をあらわすものです。

#defineを使って定義しなくても、

コード中で使うことができるようになっています。

上で紹介した、

マクロをいくつか使ってコードを入力してみます。

sample118.c

f:id:YuyaTerayama:20180919060054p:plainーsample118の実行画面ー

ソースファイル名:sample118.c

作成日付:Sep 19 2018

作成時刻:06:03:05

1~5までの合計値は15です。

組み込みマクロを使うことで、

色々な情報を得ることができるようになります。

条件付きコンパイルと組み合わせることで、

デバッグを行う際に役立てることができます。

 

以上にて、

C言語の基礎からの学びを終了します。

一回学んだからといって、

実際に使えるレベルにはならないと思います。

なので、

復習をしっかりやります。

そして、

自分の提案したプログラムを書く練習をこれからしていきましょう。

51時限という長さのブログでのアウトプットに、

お付き合いいただきありがとうございました。

 

これからはRuby on Railsについて、

また学んだことを書いていこうと思います。

駆け出しプログラマーTPYがエンジニアを目指す!!

 

〜END〜

*C言語* 〜50時限目〜 様々なデバッグ機能について・・・

〜目次〜

 

 

 

デバッグの仕組みについて

今までで、数多くのコードを入力してきました。

しかし、

コードを作成していく中で、

様々な誤りをおかしてしまう可能性は誰にでもあります。

例えば、

C言語の文法を誤ったために、

コンパイルがでいないことがあるかもしれません。

または、

コンパイルが成功し実行はできるが、

実行結果が期待通りにならない場合もあります。

プログラム中の誤りのことを、

バグ(bug)

と呼びます。

プログラムを完成させるためには、

そのバグを無くさなくてはいけません。

コード中のバグを探して訂正する作業のことを、

デバッグ(debug)

と呼びます。

C言語の環境は、

デバッグ作業を行うために、

いくつか便利な機能が備わっています。

これからC言語デバッグ機能について学んでいきます。

 

条件付きコンパイルの仕組みについて

デバッグ作業の1つとして、

変数の中身がどのような値を取っているかを確認することがあります。

プログラムの中には、

実行することができたとしても、

期待通りの結果にならないことがあります。

この時、

変数の中身を画面などに出力するコードを入力しておき、

おかしな値が格納されていないかを確認する作業を行うのです。

しかし、

バグを訂正した後に、

この画面表示のコードは不要なものになります。

ユーザーに配布する最終的なプログラムをコンパイルする段階では、

デバッグ用のコードは不要になるのです。

そこで、

C言語プリプロセッサは、

状況に応じてコンパイルをする指定を用意しています。

このことを、

条件付きコンパイル(conditional compilation)

と呼びます。

以下のコードを入力してください。

sample117.c

f:id:YuyaTerayama:20180918154240p:plainーsample117の実行画面ー

変数sumの中身は0です。

変数sumの中身は1です。

変数sumの中身は3です。

変数sumの中身は6です。

変数sumの中身は10です。

1~5までの合計値は15です。

#ifdef〜#endifという指示は、

条件に応じてコンパイルするコードを変える機能を持っています。

まず2行目で「DEBUG」というマクロを定義しています。

このマクロには置き換える文字列を指定していません。

ですが、

これもマクロ定義です。

10行目の#ifdefでは、

DEBUGマクロが定義されているかどうかを調べています。

DEBUGマクロが定義されていれば、

#ifdefから#endifまでの間の文がコンパイルされます。

2行目で定義したマクロを削除して、

もう一度コンパイル・実行をしてみてください。

そうするとエラーは起きずに実行結果だけが変わります。

尚、ここで変数の中身を表示するために、

fprintf( )関数を使っています。

最初の引数であるstderrは、

標準エラー出力と呼ばれる装置に結び付けられているストリームです。

標準エラー出力とは、

デバッグ情報などを表示するための装置のことをさします。

ここでは標準出力と同じ画面装置となっていますが、

実行環境によっては違う場所である場合もあります。

その際には、

標準エラー出力として指定されている場所に、

変数の内容が表示されることになります。

条件付きコンパイルには以下のような種類があります。

1.マクロが定義されていた場合にコンパイルする

#ifdef マクロ

  文;

  ・・・

#endif

2.マクロが定義されていない場合にコンパイルする

#ifndef マクロ

  文;

  ・・・

#endif

3.式の真偽でコンパイルする

#if 式1

  文;

  ・・・

#elif 式2

  文;

  ・・・

#else

  文;

  ・・・

#endif

 

次回は組み込みマクロから学んでいきます。

 

〜END〜

*C言語* 〜49時限目〜 ファイルへのアクセス方法&コマンドライン引数について・・・・

〜目次〜

 

 

 

 

ランダムアクセスをする

ファイルへのアクセス方法について学んでいきます。

これまでのファイルでは、

ファイルの先頭から順番にデータを読み書きしていました。

このように先頭から順番にファイルを扱う方法のことを、

シーケンシャルアクセス(sequential access

と呼びます。

ランダムアクセスをするには、

ファイル中のどの位置からデータを読み書きするのかを、

指定する必要があります。

このためには、

データを読み書きしている「現在位置」の概念が必要です。

この位置のことを、

ファイルポジション

と呼びます。

ファイルを任意の場所から読み書きする方法のことを、

ランダムアクセス(random access

と呼びます。

実際にランダムアクセスを行うコードを入力します。

48時限目で作成した、test113.binファイルを使います。

このファイルについて、指定された部分のデータだけ読み込みます。

sample115.c

f:id:YuyaTerayama:20180918020508p:plainーsample115の実行画面ー

ファイルをオープンしました。

何番目のデータを読み込みますか?

2

2番目のデータは70です。

ファイルをクローズしました。

ランダムアクセスをするには、

fseek( )関数

という関数を使います。

fseekの2番目の引数は、

移動するサイズを指定します。

fseekの3番目の引数は、

開始位置を指定します。

よって、

3番目の引数で指定した開始位置から、

2番目の引数で指定したサイズ分だけ移動することになります。

開始位置には以下の3つの定義済みのマクロがあります。

  1. SEEK_SET   →ファイルの先頭
  2. SEEK_CUR   →現在位置
  3. SEEK_END   →ファイルの末尾

移動したら、その位置からint型のデータを1つ読み取るので、

fread( )関数を使って読み込みます。

 

コマンドライン引数を使う

これまでのコードでは、

読み書きするファイルは全て、

あらかじめ決められたファイル名でした。

プログラムを実行する際に、

読み書きするファイル名をユーザーが指定できれば、

より便利なプログラムになります。

C言語では、

ユーザーが指定した文字列を実行じに受け取る仕組みとして、

コマンドライン引数(command line argument)

という機能を使うことができます。

コマンドライン引数は、

以下のようなmain( )関数の引数の形で文字列を受け取るものです。

int main(int argc, char *argv[ ]){

  ・・・

}

上のコードを実行することで、

1番目の引数であるargcには、

ユーザーが入力した文字列の個数が格納されます。

また、

2番目の引数である配列argv[ ]には、

ユーザーが入力した文字列へのポインタが格納されます。

プログラムを実行する際に、

1番目に入力するのはそのプログラム名です。

そのあと、

スペースで区切って2番目、3番目・・・と文字列を続けて入力すると、

それらがmain( )関数の引数として渡されます。

これらの文字列は、

char *argv[ ]という文字列ポインタの配列として扱われます。

実際にこの機能を使ったコードを入力してみます。

以下のようなファイルを1つ作成してください。

f:id:YuyaTerayama:20180918022150p:plainこのファイルは、コンパイル・リンク後に作成された、

実行プログラム(.exeファイル)と同じディレクトリに用意してください。

sample116.c

f:id:YuyaTerayama:20180918024034p:plainーsample116の実行方法ー

sample116 myF116.txt

ーsample116の実行画面ー

Hello. How are you?

I'm fine thank you!

sample116を実行する際に、

読み書きするファイル名をプログラム名に続けて入力します。

まず引数argcを調べて、

正しい数の引数(文字列)が入力されたかを、

チェックしています。

今回は2つの引数が入力されているべきです。

その後で引数argv[1](ファイル名をあらわす文字列へのポインタ)を

使って今までと同じようにファイルをオープンしています。

このため、

読み込むファイル名が違くても、

プログラムを作成し直さないで済みます。

コマンドライン引数を使うことで、

ユーザーがプログラム実行時に、

情報を与えるプログラムを作成することができるのです。

こうして指定したファイルの内容を、

1文字ずつ読み出すプログラムを作成することができます。

尚、ファイルの1文字の入出力には、

fgetc( )関数、fputc( )関数

を使うことができます。

 

次回はデバッグの仕組みから学んでいきます。

 

〜END〜

*C言語* 〜48時限目〜 バイナリファイルの書き込み&読み込み・・・

〜目次〜

 

 

 

バイナリファイルに書き込む

この時限まで読み書きをしてきたファイルは、

全てテキストエディタで読み書きができるファイルでした。

このようなファイルのことを、

テキストファイル(text file)

と呼びます。

テキストファイルは人間がテキストエディタで読み書きができるため、

大変便利です。

しかし、

内容によってはファイルサイズが大きくなったり、

処理速度が遅くなる場合があります。

このような時に、

バイナリファイル(binary file)

と呼ばれるファイルを使うことで、

便利になります。

バイナリファイルは、

コンピュータの内部で扱われるテータ形式のまま保存されたファイルです。

実際に、

バイナリファイルを使ったコードを入力して見ます。

sample113.c

f:id:YuyaTerayama:20180918011606p:plainーsample113の実行画面ー

ファイルをオープンしました。

ファイルに書き込みました。

ファイルをクローズしました。

sample113を実行することで、

test113.binというバイナリファイルが作成されます。

バイナリファイルを扱う方法も、

これまでの操作とほとんど同じです。

バイナリファイルを扱うには、

ファイルをオープンする際に"b"を追加します。

sample113では書き込み用なので、

wと組み合わせて"wb"と指定しています。

このバイナリファイルは、

fwrite( )関数

というものを使うことで、

書き込むことができます。

この関数は、

書き込む要素へのポインタ(要素のアドレス)と、

書き込むデータサイズを指定します。

sample113では配列の要素を1つずつ書き込むことにしています。

指定する順番は以下の通りです。

fwrite(

書き込む要素へのポインタ,

書き込むデータサイズ,

書き込む個数,

ファイルポインタ

)

 

バイナリファイルを読み込む

上で作成したバイナリファイルを、

テキストエディタで開いても読めないデータになっています。

しかし、

このバイナリファイルから、

先ほど書き込んだデータを読み込んで画面に出力することができます。

使うバイナリファイルは上で作成した、

test113.binファイルを使います。

以下のようなコードを入力してください。

sample114.c

f:id:YuyaTerayama:20180918013735p:plain

ーsample114の実行画面ー

ファイルをオープンしました。

99点

70点

77点

13点

56点

ファイルをクローズしました。

sample114では、

バイナリファイルに書き込まれているデータを、

読み込んで画面に出力しています。

バイナリファイルを読み込む際には、

オープンモードとして、"rb"を指定します。

データの読み込みには、

fread( )関数

という関数を使います。

 

今回はバイナリファイルへの、

書き込みと読み込みを学びました。

次回はファイルへのアクセス方法についてから、

学んでいきます。

 

〜END〜

*C言語* 〜47時限目〜 大量のデータを入力する・・・

〜目次〜

 

 

 

ファイルに書式付きで出力する

今回は、キーボードから入力した大学生のテストの点数を、

ファイルに読み込みます。

これを行う際にfputs( )関数のように、

そのまま書き出すのではなく、

出力幅を指定してファイルにデータを書き込むようにします。

以下のコードを入力してください。

sample110.c

f:id:YuyaTerayama:20180917230030p:plainーsample110の実行画面ー

ファイルをオープンしました。

5人のテストの点数を入力してください。

99

70

77

13

56

ファイルに書き込みました。

ファイルをクローズしました。

sample110ではファイルに書き込む際に、

fputs( )関数ではなく、

fprintf( )関数

という関数を使っています。

この関数はprintf( )関数と似たもので、

ファイルに結び付けられているストリームに対して、

書式付きの出力ができるようになっています。

この関数はprintf( )関数と同じ変換仕様を使って書式を指定できます。

test110.txtファイルの中身は以下のようになります。

f:id:YuyaTerayama:20180917230407p:plain

 

ファイルから1行入力する

データを読み込むコードを入力してみます。

46時限目で作成した、test109.txtファイルを使います。

このファイルの内容を画面に出力するコードを入力します。

sample111.c

f:id:YuyaTerayama:20180917231149p:plainーsample111の実行画面ー

ファイルをオープンしました。

ファイルに書き込まれている文字列は、

Hello.

Thankyou!

ファイルをクローズしました。

sample111では、

ファイルに書き込まれている2つの文字列を読み込んで、

それを画面に出力しています。

読み込みを行う場合には、

オープンモードとして読み込み用の、"r"を指定します。

オープンしたファイルからデータを読み込むには、

fgets( )関数

などを使うことができます。

この関数はfputs( )関数と逆の処理を行います。

改行までの1行を読み取って、

改行文字ごと格納します。

 

大量のデータを入力する

ファイルを使うことで大変便利になることがあります。

何人分ものテストの点数を1人ずつ入力するのは大変です。

しかし、

あらかじめテストのデータをファイルとして用意しておくことで、

大量のデータを読み込んで、

柔軟なコードを記述することができるようになります。

まず、

以下のようなファイルをテキストエディタなどで作成してください。

test112.txt

f:id:YuyaTerayama:20180917232415p:plain

これは8人の大学生のテストの点数のデータです。

このデータを読み込んで成績処理を行うプログラムを作成します。

sample112.c

f:id:YuyaTerayama:20180917233257p:plainーsample112の実行画面ー

ファイルをオープンしました。

No.1     99点

No.2     70点

No.3     77点

No.4     13点

No.5     56点

No.6     63点

No.7     100点

No.8     21点

最高点は100点です。

最低点は13点です。

ファイルをクローズしました。

sample112では、

あらかじめ保存しておいたファイルから、

データを読み込んで最高点と最低点を出力しています。

データの読み込みには、

scanf( )関数に似た、

fscanf( )関数を使いました。

このようにファイルを使うことで、

データを大量に入力できるので、

様々なデータを扱うファイルを作成することができます。

 

次回はバイナリファイルに書き込むということから、

学んでいきます。

 

〜END〜

*C言語* 〜46時限目〜 ファイルの仕組みについて・・・

〜目次〜

 

 

 

ファイルの仕組みについて

標準ライブラリ関数を使うと、

画面やキーボードへの入出力をすることができました。

さらにデータを長く保存したり、大量に読み込んだりするには、

ファイルを使ってデータを管理することが欠かせません。

C言語では、

ファイルを使ってデータの読み書きするコードも、

これまでの入出力のコードとほとんど同じような方式で作成できます。

ファイルへの書き込みは「出力」、

ファイルからの読み込みは「入力」、

の作業にあたります。

ファイルによる入出力の基本操作について学んでいきます。

コード上でファイルの処理を行うには、

以下のような順序で操作を行います。

f:id:YuyaTerayama:20180916141515p:plain

ファイルの「オープン」や「クローズ」とは、

操作を始める前に入出力に使われるストリームの概念と、

実際のファイルを結びつけ、

操作が終わった後に切り離す処理のことをいいます。

ファイルを使う際には、

最初にオープン、最後にクローズの作業が必要となります。

手順にしたがって、ファイルを扱うコードを作成してみます。

sample108.c

f:id:YuyaTerayama:20180916142416p:plainーsample108の実行画面ー

ファイルをオープンしました。

ファイルをクローズしました。

sample108を実行すると、

test108.txtという空のファイルが作業中のフォルダ内に作成されます。

このコードでは、

ファイルのオープンとクローズだけを行なっています。

ファイルのオープンは、

fopen( )関数

を使って行います。

この関数には、

ファイル名

オープンモード

という2つの引数を渡します。

ここでは"w"という、

オープンモードを指定しています。

すると、

ファイルがオープンされ、

ファイルをさし示すポインタ(FILE *型)が返されます。

これを、

ファイルポインタまたはストリームポインタ

と呼びます。

尚、何らかの理由でファイルがオープンできずにエラーとなった場合には、

fopen( )関数から「NULL」という、

マクロで定義されたポインタが返されることになっています。

sample108の最後では、

ファイルをクローズする処理を行う、

fclose( )関数

を呼び出しています。

この操作を行わないと、

ファイルに問題が起こる場合があるので、

忘れずに行なってください。

ファイルのオープンとクローズの構文は以下の通りです。

FILE *ファイルポインタ = fopen("ファイル名", "オープンモード");

fclose(ファイルポインタ);

尚、オープンする際に指定できる

オープンモードは以下のような種類が存在します。

f:id:YuyaTerayama:20180916144233p:plain

 

ファイルを1行出力する

空のファイルに処理を追加して、

実際にデータをファイルに書き込んでみます。

以下のコードを入力してください。

sample109.c

f:id:YuyaTerayama:20180916144746p:plainーsample109の実行画面ー

ファイルをオープンしました。

ファイルに書き込みました。

ファイルをクローズしました。

sample109ではファイルをオープンした後に、

ファイルにデータを書き込む処理を追加しています。

ファイルに1行ずつ出力する際には、

fputs( )関数

などを使います。

この関数は、指定したファイルポインタがさすファイルに、

文字列を1行書き出す処理を行います。

ただし、

この関数を使うと、

自動的に改行されませんので、

改行を行う場合には、¥nをつける必要があります。

実際にtest109.txtのファイルを開くと、

2つの文字列が書き出されていることが確認できます。

 

次回はファイルに書式付きで出力する方法から学んでいきます。

 

〜END〜

*C言語* 〜45時限目〜 10進数以外で出力する・・・

〜目次〜

 

 

 

10進数以外で出力する

8進数、16進数での出力方法について学びます。

変換仕様を使うことで、

10進数以外の表記で数値を出力することもできます。

実際に以下のコードを入力してください。

sample104.c

f:id:YuyaTerayama:20180916115415p:plainーsample104の実行画面ー

10を10進数で表記すると10です。

10を8進数で表記すると12です。

10を16進数で表記するとaです。

いままでよく使っていた%dという変換仕様は、

10進数として整数を出力する指定です。

8進数として出力する場合には%o

16進数として出力する場合には%x

を使うことができます。

 

1行の入出力をする

これまで文字列などを入力する場合には、

scanf( )関数を使っていました。

しかし、

scanf( )関数を使うと問題が起きてしまう場合があります。

以下のコードを入力してみてください。

sample105.c

f:id:YuyaTerayama:20180916120424p:plainーsample105の実行画面ー

文字列を入力してください。

This is C language.

入力した文字列はThisです。

scanf( )関数で文字列を入力すると、

空白を格納できないということが、

実行画面から確認できます。

このため、

空白をもつ文字列を読み込みたい場合には、

別の入力用関数を使わなくてはいけません。

このような関数として、

標準入力から1行の入力を受け取る、

gets( )関数

があります。

実際にgets( )関数を以下のコードで使ってみます。

sample106.c

f:id:YuyaTerayama:20180916120909p:plainーsample106の実行画面ー

文字列を入力してください。

This is C language.

入力した文字列はThis is C language.です。

sample106では、

scanf( )関数をgets( )関数に変えています。

実行画面をみてわかる通り、

空白の部分も読み込まれています。

読み込まれた文字列は、

改行のところで¥0が付けられて配列に格納されるようになっています。

また、

gets( )関数と対になった1行の出力を行う関数として、

puts( )関数

というものがあります。

puts( )関数は文字列をそのまま出力する場合に使えるので、

gets( )関数と合わせて覚えておきましょう。

尚、puts( )関数ではprintf( )関数のように書式をつけることができません。

また、¥n記号がなくても、

最後に改行されるという違いがあります。

 

1文字の入出力をする

C言語ではさらに、

1行入力の代わりに、

標準出力から1文字ずつ入出力する関数もあります。

これが、

putchar( )関数

getchar( )関数

の2つです。

実際に上の2つの関数を使ったコードを入力します。

sample107.c

f:id:YuyaTerayama:20180916122013p:plainーsample107の実行画面ー

文字を続けて入力してください。

This is C language.

This is C language.

Hello World!

Hello World!

Ctrl+Z     (終了します)

EOFという名前のマクロで、

定義されている値が返されるまで、

繰り返し処理を行うようになっています。

WIndowsコマンドプロンプト)では、Ctrl+Z、

UNIXなどでは、Ctrl+D、

をキーボードから入力することでEOFが返されます。

ただし、

この1文字入出力を行うコードは、

通常は1文字ずつ入出力が画面で確認できるわけではありません。

ハードディスクなどに入力を行う際には、

バッファリング(buuffering)

と呼ばれる処理が行われています。

これは、

文字を1文字ずつ入出力せずに、

まとめて入出力をする機能のことです。

尚、通常EOFは-1という整数値であらわされることが多いため、

戻りを受け取る変数は、char型ではなくint型を使います。

 

次回はファイルの仕組みから学んでいきます。

 

〜END〜 

*C言語* 〜44時限目〜 ストリームの仕組みについて・・・

〜目次〜

 

 

 

ストリームの仕組みついて

今までの時限で入力したプログラムの中には、

画面に文字や数値を出力したり、

キーボードから入力する処理などがありました。

入出力は画面やキーボード、それにファイルに対して行われます。

これらの装置は一見異なるものですが、

C言語では様々な装置に対する、

入出力を統一的な方法で扱うことができます。

この入出力機能を支える概念のことを、

ストリーム(stream)

と呼びます。

ストリームは様々な異なる装置を、

同じように扱うための抽象的な仕組みです。

これから様々な入出力を行うプログラムを作成しています。

 

書式付きの入出力を行う

C言語の標準ライブラリ関数には、

入出力を行うための関数が多く添付されています。

これまでに使っていた、

printf( )関数や、scanf( )関数

についてもこの関数のうちの一つです。

これらの標準的な入出力関数は、

stdio.h

というファイルをインクルードすることで使えます。

まず、printf( )関数とscanf( )関数を使ったコードについて、

復習をしていきます。

printf( )関数は標準出力に文字列を出力する関数でした。

そして、

scanf( )関数は標準入力からの入力を変数などに読み込む関数です。

以下のコードをみてください。

sample101.c

f:id:YuyaTerayama:20180915221414p:plainーsample101の実行画面ー

整数値を入力してください。

7

小数値を入力してください。

12.3

文字列を入力してください。

Hello

入力した整数値は7です。

入力した小数値は12.300000です。

入力した文字列はHelloです。

sample101で使った、2つの関数は、

標準出力・入力に対して、

一定の書式を付けて入出力を行う関数です。

変換仕様を使って、2番目以降の引数をどのような書式で、

入出力するのか指定することになっています。

特に、scanf( )関数は2番目以降の引数として、

ポインタを渡す

ということになっています。

このため、scanf( )関数を使うときには、

入力を受け取る変数名の前に&演算子を付けてきたのです。

また、

文字列を入力する場合には、

配列名に&演算子を付けていないことに注目してください。

配列名はそれ自体が先頭要素をさすポインタの役割を持っているので、

&演算子を記述する必要がなかったのです。

変換仕様には、いままで使ってきた以外にも、

たくさんの種類があります。

 

出力幅を指定する

はじめに、

出力幅を指定する

変換仕様を使ってみます。

出力する文字や数値などの間隔を指定することができます。

実際に以下のコードを入力してみてください。

sample102.c

f:id:YuyaTerayama:20180915222337p:plainーsample102の実行画面ー

  1  2  3  4  5  6  7  8  9 10

sample102では1から10までの数値を繰り返し出力しています。

実行結果を見るとわかる通り、

3字幅で出力が行われています。

変換仕様に数値を指定することで、

出力幅を指定することができます。

尚、出力する値が指定幅よりも大きいケタ数になった場合は、

出力幅が無視され、

そのケタ数で出力されます。

実際に文字幅を自分で変えて実行してみてください。

尚、出力の幅の中では、

出力を右寄せまたは左寄せにすることができます。

何も指定しないか、+をつけると右寄せで出力されます。

-をつけることで、左寄せにすることができます。

 

精度を指定する

printf( )関数では数値を出力する際には、

出力される

小数点以下のケタ数(精度)を指定する

ことができます。

このためには、ピリオド(.)を付けた数値を変換仕様として指定します。

実際にコードを入力してみます。

sample103.c

f:id:YuyaTerayama:20180915223944p:plainーsample103の実行画面ー

小数値を入力してください。

3.141592000

小数点以下3ケタで出力すると3.142です。

浮動小数点数は通常6ケタで表示されるので、

ケタ数を指定することで、

出力を読みやすくすることができます。

 

変換仕様を組み合わせる

いままでの変換仕様を組み合わせて、

複雑な書式指定をすることができます。

例えば、

浮動小数点数を左寄せにして、3字幅・小数点以下を3ケタ」

という指定をすることができます。

%±出力幅.精度 書式

このようにして組み合わせることが可能です。

 

〜END〜

*C言語* 〜43時限目〜 共用体型の仕組みについて・・・

〜目次〜

 

 

 

共用体型の仕組みについて

新しい型について学んでいきます。

共用体型(union type)

と呼ばれる型は、

構造体型と似たかたちを持っています。

共用体型の宣言は以下の通りです。

union 共用体型名{

  型名 識別子;

  型名 識別子;

  ・・・

};

共用体型は、構造体型のstructの代わりに、

union

というキーワードを使います。

共用体型も、

共用体型の変数を用意することで、

値を格納することができます。

ただし、

共用体型の各メンバは、

同時に値を記憶できるのではなく、

全体で1つしか値を記憶することができない

という特徴を持っています。

実際に以下のコードを入力してみてください。

sample99.c

f:id:YuyaTerayama:20180915194939p:plainーsample99の実行画面ー

西暦を入力してください。

2018

西暦は2018です。

元号は2018です。

元号を入力してください。

30

元号は30です。

西暦は30です。

実行画面からわかる通り、

共用体のメンバは、

同時に別の値を記憶することができない

ということが確認できます。

あるメンバの値を変更すると、

他のメンバの値も同じものに変更されます。

共用体のメンバは全てメモリの同じ位置に、

値を格納することになっています。

共用体は限られたメモリを節約するために使われる型になっています。

 

列挙型の仕組みについて

また、新しい型として、

列挙型(enumerated type)

という型について学んでいきます。

列挙型の宣言の仕方は以下の通りです。

enum 列挙名 {識別子1, 識別子2, 識別子3,・・・};

列挙型は識別子を値として格納できる型のことです。

例えば1週間を列挙型にすると以下の通りです。

enum Week{SUN, MON, TUE, WED, THU, FRI, SAT};

実際に列挙型を使ったコードを入力してみます。

sample100.c

f:id:YuyaTerayama:20180915200223p:plainーsample100の実行画面ー

月曜です。

sample100はwの値によって異なる出力をします。

列挙型の値は識別子なので、

読みやすコードを記述することができます。

 

列挙型の数値を指定する

列挙型は識別子の値を格納できるが、

内部的には順に0から1つずつ増える整数の値が、

割り振られて扱われる仕組みになっています。

なので、

sample100のcaseの横は0からの整数に変えても、

問題なくプログラムが実行されます。

ただし、

識別子を使って値を記述した方が、

わかりやすいコードが作成できるので、

列挙型の長所を十分に使うことができるでしょう。

尚、列挙型を宣言する際には、

割り振られる整数値を変えることもできます。

コードによっては、

この整数値を自分で指定する方が便利な場合があります。

宣言をするときに代入演算子を使って数値を指定します。

列挙型が示す数値は、

重複があっても大丈夫です。

指定しな部分では、原則どおり1つずつ増えます。

 

列挙型とマクロを比較する

マクロとを使っても同じように数値を、

わかりやすい名前で置き換えることができました。

#define SUN 0

#define MON 1

・・・

これは列挙型と同じ働きを持っています。

しかし、

何か意味のあるまとまった数値を複数扱う場合には、

列挙型を使った方がコードが読みやすくなります。

 

〜END〜

余談ーPart2(ポイントを貯める)

こんにちは!

 

駆け出しエンジニアTPYです!

 

余談ーPart1に続いて、余談ーPart2です!

Part1ということなので、

Part1以降もあるってバレてるはず…

 

Part1で、

恥ずかしながら書かせていただいのですが、

私自身、

勉強に力入れてるし…

インドアだし…

バイトをあまりしていないということで、

本当にお金がない。。。

 

勉強に集中できなくなった時、

息抜きは何でしようか迷っていました。

 YouTubeもそこまで好きじゃないし…

Part1で取り上げたのですが、

Huluに助けてもらっています。

  • 月額安い
  • 豊富な種類の映像見放題
  • 操作簡単

 これ最強!

 

家で息抜きをする分にはHuluがあれば、

もう心配ない!!!

 

でも、

買い物だってします。

買い物の際にポイントが貯まるってよくあります。

実際にポイント貯まるところなら、

ケチだなーとか思わずに貯めたほうがいいです!

その貯まったポイントで、

他の商品を買うことだったり、

国内旅行に行けたりします!

 

実際に私が使っているサイトを紹介したいと思います。

ちなみに、全部登録無料です!

これです⬇︎

 

 DOCOMOユーザーじゃなくても、

利用することができます!

これは本当に使いやすいポイントサイトで、

安心もできるので登録をお勧めします。

無料で利用登録できるってところも損無し!

 

登録をしておくだけで、

買い物に関係する有益な情報を無料で得ることができたり、

買い物をすること自体が楽しくなります。

 

もう一つ、

最後に紹介するのが、

これまた無料で登録できて最強のサービス!

聞いたことがあるかもしれませんが、

モニターです。

IOSユーザーは⬇︎

 

 Androidユーザーは⬇︎

 

ここから登録することができます。

登録に抵抗を感じる方が多いかもしれませんが、

実際に登録するだけでお小遣いを稼ぐことができます。

登録しなければ稼げないお金です…

このお小遣いを大事に何個も稼ぐことで、

日々の生活は楽になるんです。

実際に私も色々なポイントやモニターに登録しています。

そこで得たポイントで好きなものが買えるって…最高です!

 

実際に私も使っていますが、

  • 登録・設定は簡単
  • 初期設定完了後は作業が不要
  • 普段通りスマホを使うだけで、毎月謝礼が入る

慣れれば簡単なんです!

 

モニター登録後、

  • アプリインストール
  • サインイン
  • プロファイルをインストール

上記の3つをした後には、

普段通りにスマホを使うだけで、

初回のご契約時は1,200円、それ以降は毎月200円分の

謝礼が支払われます。

 

勉強の合間などに、

スマホでチョチョっとお小遣い稼ぎはいかがですか! 

 

 

 

余談ーPart1(Huluで映画を見る)

こんにちは!

 

駆け出しエンジニアTPYです!

 

プログラミングの勉強を毎日頑張っていますが、

ずっと参考書だったり、オンラインの学習システムを使って、

勉強していると・・・辛いです…

 

しかも、

勉強に時間を当てているため、

バイトもそこまでできないので、

お金もない…

 

そこで出会ったのがHuluという、

海外ドラマ、国内ドラマ、映画、アニメ

などの映像コンテンツが見放題の定額制動画配信サービス!!

これです⬇︎

 

実際にHuluを使ってみて、

いいと思ったことを簡単にまとめます。

  • Huluに掲載のコンテンツは何をどれだけ見ても、月額933円(税別)
  • 追加課金や超過課金は一切なし
  • 登録金・解除金も不要
  • オンデマンド配信以外にも、リアルタイムで楽しめるコンテンツも豊富
  • 1つのアカウントで6つまでプロフィール作成ができ、家族で楽しめる

 

これだけ良いと思うところが、

見つかりました!

登録も簡単で、コンテンツも豊富で…

そんなサービスが月額933円って安すぎる…

 

ずっと勉強するよりも、

何かリラックスできることを挟んだ方が効率は上がると聞きました。

実際に私も区切りのいいところまで勉強したら、

息抜きの1つとして、

Huluでアニメやドラマ、映画などを見ています。

そうすることで、

気分を切り替えできて、

勉強への集中力が増しているような気がします!

Huluの掲載しているコンテンツはとても豊富で、

飽きることがありません。

 

今なら2週間お試しで無料です!

是非、この機会にお試し下さい!

⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎⬇︎

*C言語* 〜42時限目〜 構造体の配列を作る・・・

〜目次〜

 

 

 

構造体の配列を作る

「構造体の配列」を作っていきます。

構造体型は通常の型と同じように扱うことができるので、

構造体の配列を作ることが可能です。

実際に以下のコードを入力して見てください。

sample97.c

f:id:YuyaTerayama:20180915134034p:plainーsample97の実行画面ー

車のナンバーは7777:ガソリン量は12.300000

車のナンバーは6666:ガソリン量は32.100000

車のナンバーは5555:ガソリン量は43.100000

3台の車について、ナンバーとガソリン量を管理する

プログラムを作成しました。

配列の各要素が構造体となっているのです。

このようにすることで、

複雑なコードを繰り返し文を使うことで、

簡単に記述することができるようになります。

 

構造体でリストを作る

構造体のメンバとして、

同じがたへのポインタをメンバとすることがあります。

以下のような構造体型を宣言することで、

内部のポインタによって、

同じ型の構造体をさし示すことができるようになります。

この方法を使うことで、

構造体を数珠つなぎにして管理することができます。

typedef struct Car{

  int num;

  double gas;

  struct Car *next;

}Car;

実際に以下のコードを入力して、

確認して見ます。

sample98.c

f:id:YuyaTerayama:20180915135315p:plainーsample98の実行画面ー

車のナンバーは7777:ガソリン量は12.300000

車のナンバーは6666:ガソリン量は32.100000

車のナンバーは5555:ガソリン量は43.100000

sample98では、

struct Carという構造体型にポインタを含めて、

別のstruct Car構造体を示すことができるようになっています。

つまり、

ある車が別の車をさし示すことができるのです。

このような方法を使うことで、

車を数珠つなぎにして管理することができます。

実際にコードを詳しく見ていきます。

最初に、car0のnextメンバにcar1のアドレスを代入しています。

こうすることで、

car0とcar1がつながります。

次に、car1のnextメンバにcar2のアドレスを代入しています。

これで、

car1とcar2がつながります。

最後にcar2のnextメンバにNULLを代入します。

これは標準ライブラリのマクロで定義されている値で、

ポインタが何もさし示さない際に代入する値です。

sample98では、car2の次に何もさし示さないようにして、

car2を末尾のデータとしています。

このようにしてつないだ構造体の列に、

順番にアクセスすることができます。

このような数珠つなぎの構造のことを、

リスト(list)

と呼びます。

C言語では構造体を利用して、

リストを構成することができるのです。

リストは、順番を入れ替えたり、

ユーザーの入力に応じた柔軟な処理をする場合に、

便利な構造になっています。

 

データ構造

リストや配列など、

プログラムで使われるデータを管理するための構造のことを、

データ構造(data structure)

と呼びます。

今回のリストでは、

あらかじめ用意した3つの構造体を数珠つなぎにしました。

実務上で使われるリストでは、

ユーザーの操作に応じて必要な数のデータを数珠つなぎにするのが普通です。

 

次回は共用体型の仕組みについてやっていきます。

 

〜END〜

*C言語* 〜41時限目〜 ビットフィールドを使う・・・

〜目次〜

 

 

 

ビットフィールドを使う

構造体のサイズに影響を与える、

ビットフィールド(bit field)

というメンバについて学んでいきます。

構造体のメンバの中には、

取りうる値の範囲が狭くて済むものがあります。

以下のような構造体の宣言、

小さなサイズのメンバを宣言することができます。

typedef struct Car1{
  int num;

  double gas;

  unsigned int tire : 3;   (3ビットのメンバ)

  unsigned int roof : 1;   (1ビットのメンバ)

  unsigned int color : 4;   (4ビットのメンバ)

}Car1;

3つのメンバの最後には「:O」という記述があります。

これは、

「指定したメンバをOビットにする」

という意味を持っています。

このように、

ビットを指定したメンバのことを、

「ビットフィールド」と呼びます。

例えばtireは3ビットなので、8種類の値を格納できます。

このように取りうる値が少ないメンバは、

ビットフィールドとしておくと便利です。

ビット数を指定しておくと、

構造体全体のサイズを小さくし、

メモリを節約できる可能性があるからです。

実際にビットフィールドを使ってコードを入力します。

sample94.c

f:id:YuyaTerayama:20180914141202p:plainーsample94の実行画面ー

ビットフィールドを使った構造体のサイズは24バイトです。

ビットフィールドを使わない構造体のサイズは32バイトです。

sample94では、2種類の構造体を宣言しています。

Car1はビットフィールドを使った構造体型です。

Car2はビットフィールドを使わない構造体型です。

sizeof演算子と使って、2つの型のサイズを調べています。

実行画面をみてわかる通り、

メンバをビットフィールドとしておくことで、

構造体全体のサイズを小さくすることができる可能性があります。

構造体のサイズは、各メンバのサイズを足し合わせたものになるとは限りません。

なので、

ビットフィールドを使っても、

常に全体のサイズを小さくできる訳ではないのです。

使っている実行環境によって結果は異なります。

 

引数として構造体を使う

構造体を関数の中で使う方法について見ていきます。

構造体は、関数の引数として利用することができます。

sample95.c

f:id:YuyaTerayama:20180914142321p:plainーsample95の実行画面ー

ナンバーを入力してください。

7777

ガソリン量を入力してください。

12.3

車のナンバーは7777:ガソリン量は12.300000

引数は原則として値渡しで関数内に渡されます。

構造体を引数とした場合も、「値」が渡されます。

これは、

実引数の構造体のメンバの値がそれぞれコピーされて、

関数の本体に渡される

ということを意味しています。

つまり、

ここでは構造体のメンバであるnumとgasの値が、

コピーされて関数に渡されるようになっているのです。

 

構造体へのポインタを引数に使う

メンバがたくさんある構造体を引数として使う場合には、

注意が必要になります。

関数を呼び出すたびに、

たくさんのメンバがコピーされるため、

関数の呼び出しに時間がかかってしまうことがあります。

このため、

大きな構造体を関数の引数として利用する場合、

構造体ではなく、

構造体へのポインタを引数として使う

ことがあります。

つまり、

構造体型の変数のアドレスを使うようにするのです。

構造体へのポインタを関数の引数としておくと、

アドレスを渡すだけで関数が呼び出されます。

構造体へのポインタの方が構造体よりもサイズが小さいということは、

すでに学びました。

なので、

構造体へのポインタを使った方が、

処理速度が向上する場合があります。

尚、ポインタで渡した場合は引数を実質的に参照渡しとすることになるので、

渡した構造体のメンバの値を関数内で変更することができます。

ただし、このような関数内では、

構造体へのポインタを使って各メンバにアクセスする、

処理を記述しなくてはいけません。

ポインタからメンバにアクセスする場合には、

アロー演算子(ー>)

を用いると便利です。

実際に引数として構造体へのポインタを渡す、

コードを入力して見ます。

sample96.c

f:id:YuyaTerayama:20180914143555p:plainーsample96の実行画面ー

ナンバーを入力してください。

7777

ガソリン量を入力してください。

12.3

車のナンバーは7777:ガソリン量は12.300000

この関数内ではポインタが渡されるので、

メンバにアクセスする場合には、

ドット演算子ではなく、アロー演算子を使います。

 

〜END〜

*C言語* 〜40時限目〜 構造体を初期化する・・・

〜目次〜

 

 

 

構造体を初期化する

構造体を宣言した後に、

ドット演算子を使ってメンバに値を代入する方法について、

学びました。

この宣言と値の代入を構造体でもまとめることができます。

そのことを、

構造体の初期化

と呼びます。

変数を宣言する際に、{ }で囲んで値を記述すると、

カンマで区切った順番にメンバに値が格納されます。

構造体にあらかじめ初期値を与える際に便利なので、

覚えてください。

39時限目のコードを初期化を使って書き換えてみます。

sample91.c

f:id:YuyaTerayama:20180913214311p:plainーsample91の実行画面ー

車のナンバーは7777:ガソリン量は12.300000

 

構造体に代入する

これまでは各メンバに対して、

代入演算子を使って値を格納してきました。

構造体変数そのものに対して代入演算子を使うとどうなるのか、

以下のコードを入力して確認してみます。

sample92.c

f:id:YuyaTerayama:20180913215259p:plainーsample92の実行画面ー

car1の車のナンバーは7777:ガソリン量は12.300000

car2の車のナンバーは6666:ガソリン量は32.100000

car1をcar2に代入しました。

car2の車のナンバーは7777:ガソリン量は12.300000

sample92では、

car1とcar2という構造体を宣言しています。

そして、代入を行なっています。

この代入は、

car2のメンバにcar1のメンバを1つずつコピーして値を格納する

ということを意味しています。

構造体で同士でこのような代入をすることができるので、

覚えておいてください。

 

構造体型のサイズを知る

構造体も新しい型です。

そこで、構造体型のサイズについて調べてみます。

構造体型のサイズを調べるには、以前使っていた

sizeof演算子を使います。

以下のコードを入力してみてください。

sample93.c

f:id:YuyaTerayama:20180914023218p:plainーsample93の実行画面ー

int型サイズは4バイトです。

double型サイズは8バイトです。

構造体struct Car型のサイズは16バイトです。

構造体struct Car型へのポインタのサイズは8バイトです。

構造体struct Car型は、int型とdouble型のメンバを持っている。

構造体型のサイズは、各メンバのサイズを足し合わせたものと同じか、

それよりも大きくなります。

従って、たくさんのメンバを持つ構造体や大きなサイズのメンバを持つ

構造体は大きなサイズになります。

ただし、

実行画面を見てわかる通り、

構造体のサイズは2つの型をぴったり足し合わせたサイズに、

なるとは限りません。

実行環境によってサイズは少し変わってきます。

一般的に、

多くのメンバを持つ構造体へのポインタは、

構造体そのもののサイズよりも小さくなっています。

 

次回はビットフィールドについて学んでいきます。

 

〜END〜

*C言語* 〜39時限目〜 構造体の基本・・・

〜目次〜

 

 

構造体型の仕組みについて

新しく決めることができる型として、

構造体型(structure type)

というものがあります。

この型は、

異なる型の値をまとめて新しい型にする

という機能を持っています。

車で例えると、

ナンバー(int型)、ガソリン量(double型)などの、

異なる型の値をまとめて、

「車」をあらわす型にすることができるのです。

構造体型がどのような型であるか取り決めることを、

構造体型の宣言

と呼びます。

構造体型を宣言するには、

struct

というキーワードを使います。

構造体型はブロックの中に、

変数などをまとめて記述したものです。

例で出した車の場合は以下のように宣言できます。

struct Car{    (車をあらわす構造体型Car)

  int num;      (ナンバーを格納する)

  double gas;    (ガソリン量を格納する)

}

 

構造体変数を宣言する

構造体型を宣言することで、

新しい型としてコードの中で使うことができます。

構造体変数の宣言は以下の通りです。

構造体型名 構造体変数名;

struct Car型の変数も、通常の変数と同じように宣言します。

以下のように宣言することで、

struct Car型の変数となります。

struct Car car1;

 

メンバにアクセスする

構造体型の変数(構造体)を宣言すると、

その中のnumやgasに、

実際のナンバーやガソリン量を格納することができるようになります。

このnumやgasといった変数のことを、

メンバ(member)

と呼びます。

構造体のメンバを利用するためには、

ドット演算子(.)

というものを使います。

そして、メンバを利用することを、

メンバにアクセスする

と呼びます。

構造体のメンバへのアクセスは以下の通りです。

構造体変数名.メンバ

実際にコードを入力して、

どのようにして使うのか確認してみます。

sample88.c

f:id:YuyaTerayama:20180913211355p:plainーsample88の実行画面ー

車のナンバーは7777: ガソリン量は12.300000

このようにすることで、

車を扱うコードを書くことができました。

尚、メンバの値をキーボードから入力できると、

より柔軟なプログラムにすることができます。

実際にコードを入力してみます。

sample89.c

f:id:YuyaTerayama:20180913211754p:plainーsample89の実行画面ー

ナンバーを入力してください。

7777

ガソリン量を入力してください。

12.3

車のナンバーは7777:ガソリン量は12.300000

これまでの変数と同じで、

&をつけるということに注意をしてください。

尚、&は構造体名の前につけます。

 

typedefで名前を割り当てる

構造体型の型名を短縮するために、

typedef

というキーワードを使う方法があります。

//構造体型 struct Carの宣言

typedef struct Car{

  int num;

  double gas;

} Car;

こうすることで、「struct Car」という型名に対して、

「Car」という新しい型名をつけることができます。

このため、あとで構造体型の変数を宣言する時には、

以下のように短い名前を使って宣言することができます。

Car car1;

typedefを使うことは便利になるので、

実際にコードの中で使ってみます。

sample90.c

f:id:YuyaTerayama:20180913212556p:plainーsample90の実行画面ー

ナンバーを入力してください。

7777

ガソリン量を入力してください。

12.3

車のナンバーは7777:ガソリン量は12.300000

尚、typedefでつける名前は、

Carでなく別の名前でも問題はありません。

 

次回は構造体の初期化から学んでいきます。

 

〜END〜