【初心者向け】情報学部生と学ぶC言語 [7限目:構造体]

構造体とは

例えば、30人のクラスのテストの点数を扱う時のことを考えてみましょう。名前のための変数”name”、数学のための変数”math”、英語のための変数”english”を用意して各々にデータを入力していくとします。このとき、名前の表には「”田中太郎”,”山田花子”,…」といったように名前のデータだけ、数学の表には「”60”,”80”,…」と数学の点数のデータだけが格納されているとしたらとても分かりにくいですよね?

普通、こういう時は「”田中太郎”について”数学”,”英語”のデータ」、「”山田花子”について”数学”,”英語”のデータ」と一人ひとりデータを分けて扱います。

このように複数のデータを一つのまとまりとして扱う時に使用されるのが構造体です。

では、「『九州』にある県の『県名』と『人口』、『面積』を構造体としてひとまとめにし、それらを表示するプログラム」を作ってみましょう。

#include<stdio.h>
#include<string.h>

#define MAX 64

struct kyushu {
	char prefecture[MAX]; //県名
	int population; //人口
	double square; //面積
};

int main(void)
{
	struct kyushu fukuoka;
	
	strcpy(fukuoka.prefecture, "Fukuoka");
	fukuoka.population = 511;
	fukuoka.square = 4986.52;
	
	printf("県名 : %s\n", fukuoka.prefecture);
	printf("人口 : %d 万人\n", fukuoka.population);
	printf("面積 : %.2f 平方キロメートル\n", fukuoka.square);
	
	return 0;
}
■実行結果
県名 : Fukuoka
人口 : 511
面積 : 4986.52

解説

構造体は以下のように宣言します。

struct 構造体タグ {
    型名 メンバ
};

上記のソースコードでは、

構造体タグが「kyushu」でメンバが「”prefecture”,”population”,”square”」となります。

構造体を宣言した時、記憶域上には各メンバが宣言順に並びます。

そして、これら個々のデータをひとつのオブジェクトに格納するための宣言が上記のプログラムの以下の部分となります。

struct kyushu fukuoka;

構造体の個々のデータにアクセスするとき

オブジェクト.メンバ

と記述することでそのオブジェクトに関しての個々のデータを扱うことができます。

例えばオブジェクト”fukuoka”の人口”population”にアクセスする時、”fukuoka.population”と記述して取り扱います。

オブジェクト”fukuoka”について図で示したものが以下になります。

上のプログラムでは構造体の型の変数の宣言を行ったのちに、数値の代入を行っていますが、宣言した時に初期化を行うことで簡略化することができます。

また、構造体の宣言時にtypedef宣言といって

typedef struct 構造体タグ {
    型名 メンバ
} typedef名;

 

とすることで構造体の型の変数を宣言する際に

typedef名 変数名

とすれば良くなるため、記述が簡潔化します。

これらを利用して、上記のプログラムを書き換えたものが以下のプログラムです。

#include<stdio.h>

#define MAX 64

typedef struct kyushu {
	char prefecture[MAX]; //県名
	int population; //人口
	double square; //面積
} Kyushu;

int main(void)
{
	Kyushu fukuoka = {"Fukuoka", 511, 4986.52};
	
	printf("県名 : %s\n", fukuoka.prefecture);
	printf("人口 : %d 万人\n", fukuoka.population);
	printf("面積 : %.2f 平方キロメートル\n", fukuoka.square);
	
	return 0;
}
今は”fukuoka”だけしか扱ってないけど、それ以外の県の情報を追加した時mainで同じようなことを何回も書かなきゃいけないよね?メンドクセー

構造体の型の変数には配列も使用できます。これでその悩みは解決できますね。

#include<stdio.h>

#define MAX 64
#define MEMBER 3

typedef struct kyushu {
	char prefecture[MAX]; //県名
	int population; //人口
	double square; //面積
} Kyushu;

int main(void)
{
	Kyushu mem[] = {
			{"Fukuoka", 511, 4986.52},
			{"Kumamoto", 175, 7409.48},
			{"Oita", 113, 6340.73},
			};
	
	for(int i=0;i<MEMBER;i++){
		printf("県名 : %s\n", mem[i].prefecture);
		printf("人口 : %d 万人\n", mem[i].population);
		printf("面積 : %.2f 平方キロメートル\n", mem[i].square);
		if(i != MEMBER-1)
			puts("");
	}
	
	return 0;
}
■実行結果
県名 : Fukuoka
人口 : 511 万人
面積 : 4986.52 平方キロメートル

県名 : Kumamoto
人口 : 175 万人
面積 : 7409.48 平方キロメートル

県名 : Oita
人口 : 113 万人
面積 : 6340.73 平方キロメートル

C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [6限目:ポインタ]

ポインタはC言語の学習における最難関のひとつとされています。現にポインタを理解出来ないためにC言語の習得を諦める人も多数います。そこでポインタを理解するために以下のステップを踏んで説明していきます。いずれもポインタを理解するためには必要な知識となるためひとつひとつしっかり理解されることを推奨します。

ふたつの値の和、差、積、商を求める関数を用いて、main関数内でそれらの答えを出力するプログラムを作りましょう。

#include <stdio.h>

void cal(int num1, int num2, int sum, int diff, int prod, double quot)
{
	sum = num1 + num2;
	diff = num1 - num2;
	prod = num1 * num2;
	if(num2==0)
		quot = 0;
	else
		quot = (double)num1 / (double)num2;
}

int main(void)
{
	int x,y;
	int wa = 0, sa = 0, seki = 0;
	double sho = 0.0;
	
	printf("整数1:");
	scanf("%d", &x);
	printf("整数2:");
	scanf("%d", &y);
	
	cal(x, y, wa, sa, seki, sho);
	
	printf("和:%d\n", wa);
	printf("差:%d\n", sa);
	printf("積:%d\n", seki);
	printf("商:%.1f\n", sho);
	
	return 0;
}
■実行結果[例]
整数1:30
整数2:8
和:0
差:0
積:0
商:0.0
あれれ~?おかしいぞ~?
答えが全部0になってるよ。

さすがコ○ン君!実は、こうなってしまうという所に「値渡しとは何なのか」という事が表されています。

値渡しとは

値渡しとは、コンピュータプログラム中で関数やプロシージャなどに渡す引数として変数などを指定する際、その値のみを引き渡す方式。渡された引数の値を変更しても呼び出し元の変数の値は更新されない。


引用元:IT用語辞典 e-Words

「渡された引数の値を変更しても呼び出し元の変数の値は更新されない。」という所に注目しましょう。

例えば上記の引用文を利用してこのページの中で以下のような文章に書き換えたとします。

値渡しとは、「アタイ・ワタシ」の2語から構成され、女の子の一人称を表す隠語である。

この時、このページ内の「値渡しとは」の文章(コピーした値)は変更されましたが、引用元の文章(オリジナルの値)は変更されませんよね?

これが値渡しというものです。値渡しでは引数によりひとつの値を計算して返すことは出来ますが、上記のプログラムのように複数の値を一度に計算したい時には、2個以上の値を返せないという性質上、実現できません。

そこで利用されるのがポインタです。

ポインタを理解するために、まずアドレスというものを理解しなければなりません。

アドレスとは

英語でアドレス(address)というと、住所や番地のほかに演説や講演といったような意味がありますが、ここで使うアドレスは番地ということを意味します。つまり、自分のいる所(=場所)を示しています。各々の変数には宣言した時にアドレスが付与されます。アドレスを用いる際、変数の前に”&”を用います。この”&”アドレス演算子と言います。そしてアドレスを出力するための変換指定には%pを用います。

pはpointerの意

変数名 アドレス演算子 変換指定
n &n %p

では、さまざまな型のアドレスを出力するプログラムを作りましょう。

#include <stdio.h>
int main(void){
	int a;
	double b;
	char c;
	
	printf("aのアドレス:%p\n", &a);
	printf("bのアドレス:%p\n", &b);
	printf("cのアドレス:%p\n", &c);
	
	return 0;
}
■実行結果[例]
aのアドレス:200
bのアドレス:204
cのアドレス:208

ここでは説明のためアドレスの出力を簡易的に”200″といったような10進数で表示していますが、通常は16進数で表示されると思います。[例]0x000000000000(実行環境により異なる)

ポインタとは(参照渡しとは)

最初に作成した「ふたつの値の和、差、積、商を求める関数を用いて、main関数内でそれらの答えを出力するプログラム」はポインタというものを使うことにより実現できます。以下のソースコードからポインタの使い方についてみていきましょう。

#include <stdio.h>

void cal(int num1, int num2, int *sum, int *diff, int *prod, double *quot)
{
	*sum = num1 + num2;
	*diff = num1 - num2;
	*prod = num1 * num2;
	if(num2==0)
	*quot = 0;
	else
	*quot = (double)num1 / (double)num2;
}

int main(void)
{
	int x,y;
	int wa = 0, sa = 0, seki = 0;
	double sho = 0.0;
	
	printf("整数1:");
	scanf("%d", &x);
	printf("整数2:");
	scanf("%d", &y);
	
	cal(x, y, &wa, &sa, &seki, &sho); // (num1 = x, num2 = y, int *sum = &wa, 以下略)を意味する
	
	printf("和:%d\n", wa);
	printf("差:%d\n", sa);
	printf("積:%d\n", seki);
	printf("商:%.1f\n", sho);
	
	return 0;
}
■実行結果[例]
整数1:20
整数2:8
和:28
差:12
積:160
商:2.5

解説

ポインタは変数の前に”*”を付けて宣言します。例えば「intへのポインタ型p」を生成したい時は以下のように宣言します。

int *p;

この時、変数は「『int型の値を格納する変数のアドレス』を格納する箱」を意味します。

そして

int *p;
p = &n;

とした時、ポインタpにはnのアドレスが格納されます。このことを「pはnを指す」といいます。

そして、ポインタが指し示す先の中身を使用する時には”*”(間接演算子という)を付けます。この時ポインタは格納されているアドレスを参照して、そのアドレスにある変数の中身を指します。そしてその変数の中身を出力します。このことを慣例的に参照渡しといいます。

ここで、ポインタの使い方のおさらいをしておきましょう。

int *p; // intへのポインタ型の変数pの宣言
p = &n; // pにnのアドレスを格納
printf(“%d”, *p); //間接演算子”*”をつける事で参照したアドレス先の中身を扱える

値渡しと参照渡しの違い

先程のプログラムからポインタを使わない場合(=値渡し)とポインタを使う場合(=参照渡し)の違いをみていきましょう。

値渡し

値渡しは中身が同じである変数を複製します。この時、格納されているアドレスが異なるため複製した値を変更してもオリジナルの値は変わりません。

参照渡し

参照渡しはオリジナルの値が格納されている変数のアドレスを複製します。オリジナルのアドレスが格納された変数の値を変更する時、そのアドレスを参照してオリジナルの値そのものを変更します。

そういえば、今まで何も考えずに使ってたけど
scanf(“%d”, &n);
ってアドレス演算子を使ってたんだ!

いい所に気づきましたね!scanfは「渡されたアドレスを参照して、そこにある変数の中身を入力される値に変更する」という関数だったのです。

ポインタについて理解できるかどうかがC言語について理解しているかどうかに直結するといっても過言ではありません。しっかり復習してポインタを理解できるようになりましょう。


C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [5限目:列挙体]

列挙体とは

列挙体について理解するために、以下に示す

[様々な国の選択肢の中から選ばれた国の挨拶を表示するプログラム]

から列挙体とはどういうものなのか、そしてその使い方について学んでいきましょう。

#include <stdio.h>

enum greet { Japan, America, Korea, Invalid};

void japan(void)
{
	puts("こんにちは");
}

void america(void)
{
	puts("hello");
}

void korea(void)
{
	puts("안녕하세요");
}

enum greet select(void)
{
	int tmp;
	
	do{
		printf("0...日本 1...アメリカ 2...韓国 3...終了:");
		scanf("%d", &tmp);
	}while (tmp < Japan || tmp > Invalid);
	
	return tmp;
}

int main(void)
{
	enum greet selected;
	
	do {
		switch (selected = select()){
		  case Japan : japan(); break;
		  case America : america(); break;
		  case Korea : korea(); break;
		}
	}while (selected != Invalid);
	
	return 0;
}
■実行結果
0…日本 1…アメリカ 2…韓国 3…終了:0
こんにちは
0…日本 1…アメリカ 2…韓国 3…終了:1
hello
0…日本 1…アメリカ 2…韓国 3…終了:2
안녕하세요
0…日本 1…アメリカ 2…韓国 3…終了:3

解説

列挙体とは、限られた整数値の集合を表すものです。列挙体は以下のように宣言します。

enum greet { Japan, America, Korea, Invalid };

greetを列挙体タグといい、{}内のJapan, America, Korea, Invalidを列挙定数といいます。このように宣言したとき、列挙定数には、Japanから順に、0, 1, 2, 3 と整数値が与えられます。この時、”enum greet”を列挙型といい、列挙型に変数をつけて宣言することで、その変数は列挙定数の値を取りうる変数となります。

enum greet selected;

このプログラムでは、enum greet型の変数selectedは0, 1, 2, 3の値を取りうるということになります。

ここでワンポイント

Invalidは「無効」という意味で、このプログラムでは、終了するときのための列挙定数として使用していますが、Invalidを使用せずとも同じ動きをするプログラムは作れますよね?例えばenum greet型の関数selectの中のdo-while文の条件を

//Invalidを使用しない例

do{
    ...
}while(tmp < Japan || tmp > Korea + 1);

とすれば実現可能です。

しかし、ここで新しい選択肢として、”China”を入れたいとき、先程の条件式を毎回書き換える必要があります。

//Invalidを使用せず列挙定数"China"を加えた例

enum greet { Japan, America, Korea, China };
...
do{
    ...
}while(tmp < Japan || tmp > China + 1);

しかし、Invalidを用意しておけば条件式は変更することなく、列挙体の宣言だけ変更すれば良いので、いかに有効かがわかると思います。

//Invalidを使用し列挙定数"China"を加えた例

enum greet { Japan, America, Korea, China };
...
do{
    ...
}while(tmp < Japan || tmp > Invalid);

補足

列挙定数の値は 列挙定数 = 整数値 という形で自由に設定することもできます。

例

enum name { Tanaka , Yamada = 3, Kato };

この時Tanakaの値は0、Yamadaの値は3、そしてKatoの値は指定されていないため、前の列挙定数(ここではYamada)に1を足した4になります。

列挙定数は同じ値でも構いません。いかの例では、TanakaとTaroの値はともに0となります。

例

enum name { Tanaka , Taro = 0 };

列挙体タグは必要でなければ省略することもできます。その時、その列挙型の変数の宣言はできなくなるので注意しましょう!

例

enum { JANUARY = 1, FEBRUARY, ..., DECEMBER};

上記の例を使用することで

#define JANUARY 1
#define FEBRUARY 2
...

と宣言したいとき、簡単に宣言する事が可能です。


C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [4限目:関数]

今回は関数について勉強していきましょう

関数とは

今までのプログラムで毎回書いてきたものがありますよね?その中の以下の部分をmain関数といいます。


int main(void)
{
    //省略
}

また、printfやscanfなどをライブラリ関数といいます。

これまではmain関数のみのプログラムを作成してきましたが、自分で関数を作成し、それを組み合わせてプログラムを作ることもできます。そこで今回は関数の作り方と関数の使い方について学んでいきましょう。

関数の作り方

二つの整数値のうち大きい方を返す関数を作ってみましょう。


int bigger (int x, int y)
{
    if (x > y)
        return x;
    else
        return y;
}

この関数の名前(関数名)はbiggerです。

この関数はintで宣言されているため、関数が呼び出されたとき、intの値を返します。

int x, int yは仮引数と呼ばれます。

関数の使い方

作成した関数を使うためには関数呼び出しをしなければなりません。

では先程作った関数をmain関数の中で呼び出して、二つの整数値のうち、大きい方の値を求めるプログラムを作成しましょう。

#include<stdio.h>
int bigger(int x, int y)
{
	if(x > y)
		return x;
	else
		return y;
}

int main(void)
{
	int num1,num2;
	
	printf("ひとつ目の数字は:");
	scanf("%d", &num1);
	printf("ふたつ目の数字は:");
	scanf("%d", &num2);
	
	printf("大きい方の値は%dです.\n", bigger(num1,num2));
	
	return 0;
}
■実行結果[例]
ひとつ目の数字は:5
ふたつ目の数字は:8
大きい方の値は8です.

解説

上のソースコードのmain関数内のprintfに注目してください。

printf(“大きい方の値は%dです.\n”, bigger(num1,num2));

赤の部分が関数呼び出し式とよばれ、関数呼び出し式の記述により関数を呼び出すことができます。また、()内のnum1, num2のことを実引数といいます。実引数の値が仮引数にセットされ、関数内で処理が行われた後return文により、その値が関数呼び出し式に返却されます。




関数の引数には配列を使用することもできます。平均を計算する関数を作成し5人のテストの点数の平均を求めるプログラムを作ってみましょう。

#include<stdio.h>
#define NUM 5 //受験者数

double ave(int v[], int x)
{
	int i,sum;
	sum = 0;
	
	for(i=0;i<x;i++)
		sum += v[i]; // sum = sum + v[i];
	
	return (double)sum/x;
}

int main(void){
	int score[NUM];
	
	puts("テストの点数を入力してください");
	for(int i=0;i<NUM;i++)
	{
		printf("%d番目:",i+1);
		scanf("%d", &score[i]);
	}
	
	printf("テストの平均は%.1f点です.\n", ave(score, NUM));
	
	return 0;
}
■実行結果[例]
テストの点数を入力してください
1番目:50
2番目:78
3番目:92
4番目:34
5番目:66
テストの平均は64.0点です.


いかがでしたか?機能ごとに関数を作成することで、ソースコードがわかりやすくなり、エラーが発生した時も全体に影響を及ぼしにくくなったり対処がしやすくなったりと様々な利点があります。

慣れるまでは難しく感じるかもしれませんが、頑張って使いこなせるようになりましょう!

C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [3限目:条件分岐文]

条件分岐とは

今までのプログラムでは上から下へと順番に命令を行なっていくものでした。しかし、プログラムは一方通行ばかりではありません。条件分岐についてイメージしてみましょう。あなたは今冒険をしています。ドラクエの勇者とかポケモントレーナーにでもなった様子を想像しましょう。目の前には分かれ道。分かれ道の前に看板があります。看板には「○○村← →○○洞窟」の記述が。

この看板は、「あなたが○○村に行きたいなら左に行きなさいあなたが○○洞窟に行きたいなら右に行きなさい。」という「条件(赤字)命令(青字)」を意味していますよね。プログラミングでも同様に、条件と命令を記述していく必要があります。

条件
{
    命令
}

と記述することで条件分岐を行います。条件には、if文、(do)while文、for文、switch文があります。では、これら各文について学んでいきましょう。

if文

入力された数値が「正、0、負」のどれに該当するかを出力するプログラムを作りましょう。

#include<stdio.h>
int main(void)
{
	int num;
	printf("数値を入力してください:");
	scanf("%d",&num);
	
	if(num==0) //a==b:aとbが等しければ、a!=b:aとbが異なるならば
	{
		puts("入力された数字は0です.");
	}else if(num>0){
		puts("入力された値は正です");
	}else{
		puts("入力された値は負です");
	}
	
	return 0;

}
■実行結果
数値を入力してください:10
入力された値は正です
数値を入力してください:-10
入力された値は負です
数値を入力してください:0
入力された値は0です

解説

if(条件)
{
   命令1
}

「もし条件のとき命令1を実行」となります。

else
{
    命令2
}

「これまでの条件以外のとき命令2を実行」となります。

これらは組み合わせることもできまして、

else if(条件)

とすることで「これまでの条件以外のうち(条件)のとき」ということを意味します。

==演算子!=演算子のことを等価演算子と言います。一般的には学校で習った数学の知識により「a=b」で「aとbが等しい」ってことじゃないの?と思われると思いますが、変数の時に説明したようにプログラミングの世界では「a=b」は「aという変数にbという値を代入する」という意味になります。そこで「aとbが等しい」を実現するために「a==b」、「aとbが異なる」を「a!=b」で表します。

ちょっとしたポイント

正、0、負に分けるようなプログラムのとき、「数値が正かどうか→0かどうか→負かどうか」の順で条件分岐を行いがちですが、最初に数値が一つに限定されるもの(このプログラムでいえば0)を使って条件分岐したほうがわかりやすいプログラムになります。プログラムを作るときわかりやすいかどうかを意識できるようになると脱初心者の第一歩になるでしょう。

(do)while文

基本的には、do文、while文というように分けて言います。しかし、do文はwhile文と一緒に使うという特性上一緒に説明していきます。ではまず、while文についてみていきましょう。

#include<stdio.h>
int main(void){
	
	int plus,minus;
	int i=0;
	printf("正の数値を入力してください:");
	scanf("%d", &plus);
	minus = plus;
	
	while(minus>0){
		printf("%d ",minus--);
	}
	puts("");
	
	while(i<plus){
		printf("%d ",++i);
	}
	puts("");
	
	return 0;
}
■実行結果
正の数値を入力してください:10
10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10

解説

while文は

while(条件)
{
    命令
}

で表現し、「条件が満たされる間命令を繰り返す」という条件分岐となります。

”++”インクリメント演算子”–”デクリメント演算子といい変数を+1または-1します。これらの演算子を変数の前につける時、、「前置インクリメント(デクリメント)演算子」と呼ばれ、変数の後ろにつける時、、「「後置インクリメント(デクリメント)演算子」と呼ばれます。

前置演算子とは、式を評価する前にインクリメント(デクリメント)、しますよということを意味します。プログラムでいえば

printf("%d ",++i);

が該当し、printfでiの値を出力する前にiの値を+1しています。

後置演算子は前置演算子とは順番が逆で、式を評価した後で変数をインクリメントまたはデクリメントします。

続いてdo文です。do文は少なくとも一度は命令を実行したい時に使用されます。生まれた月を訪ねるプログラムで見てみましょう。

#include<stdio.h>
int main(void){
	int month;
	
	do{
		printf("あなたの誕生月は?:");
		scanf("%d",&month);
	}while(month<1||month>12);
	puts("thank you!");
	
	return 0;
}
■実行結果
あなたの誕生月は?:-1
あなたの誕生月は?:15
あなたの誕生月は?:3
thank you!

解説

do
{
    命令
}while(条件);

で表します。

これまでと異なるのが、条件が命令の後に記述されるということです。

こうすることで少なくとも一度は命令が実行されることになります。その後while文の条件を評価して、命令を繰り返すかどうかが決まります。

for文

for文はwhile文のように繰り返し(ループ)を行うために用いられますが、while文よりもわかりやすく読みやすいためwhile文より多用されます。

べき乗を計算するプログラムを用いてfor文の使い方を確認してみましょう。

#include<stdio.h>
int main(void){
	int r,n,x;
	printf("数値を入力してください:");
	scanf("%d",&r);
	printf("何乗しますか?:");
	scanf("%d",&n);
	
	x=r;
	
	for(int i=1;i<n;i++)
	{
		r = r*x;
	}
	printf("%dの%d乗は%dです\n",x,n,r);
	
	return 0;
}
■実行結果
数値を入力してください:2
何乗しますか?:3
2の3乗は8です

解説

for文は

for(式1;式2;式3)
{
    命令
}

で表現されます。式1は前処理と言われ、繰り返しの前に一度だけ評価されます。式2は制御式と言われ、ここが基本的な条件になります。式3は後始末と言われ、ループ後に評価されます。

i=1
while(i<n){
    r=r*x;
    i++;
}

と書き換えられますね。

練習問題

九九の表を作ってみましょう。

#include<stdio.h>
int main(void)
{
	for(int i=1;i<=9;i++){
		for(int j=1;j<=9;j++){
			printf("%2d ",i*j);
		}
		puts("");
	}
	return 0;	
}
■実行結果
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81

解説

まず、iが1の時が評価されます。その中の命令にfor文があるためjが1から9までの値の時i*jを出力します。その後iが2となり、この時jが1から9までというように繰り返されます。

switch文

switch文は多岐に条件分岐させたいときに用いられます。do文のところで作成した誕生月を尋ねるプログラムを改変してswitch文の使い方について確認してみましょう。

#include<stdio.h>
int main(void){
	int month;
	
	do{
		printf("あなたの誕生月は?:");
		scanf("%d",&month);
	}while(month<1||month>12);
	
	printf("あなたは");
	switch(month){
	  case 1:
	  case 2:
	  case 3: printf("冬"); break;
	  case 4:
	  case 5:
	  case 6: printf("春"); break;
	  case 7:
	  case 8:
	  case 9: printf("夏"); break;
	  case 10:
	  case 11:
	  case 12: printf("秋"); break;
	}
	printf("生まれです.\n");
	
	return 0;
}
■実行結果
あなたの誕生月は?:1
あなたは冬生まれです.
あなたの誕生月は?:7
あなたは夏生まれです.

解説

switch(変数)
{
    case 変数の値: 命令
}

で表します。

breakと記述することで、条件分岐から抜け出します。もしbreakがなければ、変数の値が合致するところ以降の命令が全て実行されてしまうため、このプログラムで例えば”4″と入力したとき”あなたは春夏秋生まれです.”と出力されてしまいます。



条件分岐をうまく使うことによりプログラムを簡潔化させることができます。しっかり復習して使いこなせるようになりましょう!

C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [2限目:様々な型と配列]

今回は前回に少しだけ触れたについて勉強していこうと思います。その過程で配列の知識も必要になってくるので配列についても抑えていきましょう。

前回の復習

型にはどんな種類があったのかおさらいしておきましょう。下の表を見てください。

 
型名とその意味
型名 意味
int 整数型
double 浮動小数点数型(8バイト)
float 浮動小数点数型(4バイト)
char 文字型
void 型なし

ではそれぞれの型について確認していきましょう。

int型

int型とは、整数を扱うための型で、サイズは4バイトです。バイトというのは情報量の単位のことで1バイト=8ビットとなります。ビットも同じく情報量の単位のことなのですが、こちらは最小単位となります。コンピュータは0と1の二つの値を組み合わせて情報を扱う(=2進数)ので、1ビットとは取り扱っているデータの一桁目が”0″か”1″かを表現していると思ってください。以下の表で2進数の3ビットで表現できる数字を確認しましょう。

 
3ビットまでで表現できる数字
ビット表現
(2進数)
普段扱う数字
(10進数)
ビット表現
(2進数)
普段扱う数字
(10進数)
0 0 100 4
1 1 101 5
10 2 110 6
11 3 111 7

表からもわかるように3ビット(桁)で0〜7の8個(2個)の数字を表現することができます。

nビットで表現できる数字の数は2n表現できる範囲の数字は0〜2n−1ということです。

***説明のため正の数に限定していますが負の数が入ってくると表現できる範囲は変わることに注意しましょう***

では4バイトのとき表現できる数字の数と範囲について考えてみてください。

4バイト = 4 × 8 ビット より
数字の数:232
範囲:0〜232−1

では二つのint型の数字の平均を計算するプログラムを作成してみましょう。

/***
filename:average.c
***/

#include<stdio.h>
int main(void)
{
int num1,num2;

printf("一つ目の数字を入力してください:");
scanf("%d",&num1);
printf("二つ目の数字を入力してください:");
scanf("%d",&num2);

printf("ふたつの値の平均は %d です\n", (num1+num2)/2);

return 0;
}
■実行結果<例>
一つ目の数字を入力してください:24
二つ目の数字を入力してください:11
ふたつの値の平均は 17 です

二つの平均値は17ってなってるけど、、、
(24+11)/2=17.5だよね?

鋭い指摘ですね。int型では小数部は切り捨てられます。そこで次に浮動小数点数を扱えるdoubleとfloatについて学んでいきましょう。

double(float)型

double(float)型について理解するために上のプログラムを改変した下のプログラムを作ってみましょう。

/***
filename:average_double.c
***/

#include<stdio.h>

int main(void)
{
	int num1,num2;
	double ans_d;
	float ans_f;
	
	printf("一つ目の数字を入力してください:");
	scanf("%d",&num1);
	printf("二つ目の数字を入力してください:");
	scanf("%d",&num2);
	
	ans_d = num1 + num2; //ans_d = (num1+num2)/2; としないことに注意
	ans_d = ans_d/2;
	
	ans_f = num1 + num2;
	ans_f = ans_f/2;
	
	
	puts("ふたつの値の平均は");
	printf("	double型ans:%f\n", ans_d);
	printf("	float型ans:%f\n", ans_f);
	printf("	キャスト:%.1f\n", (double)(num1 + num2) / 2); //(num1+num2)をdouble型にキャスト
	puts("です");
	
	return 0;
}
■実行結果<例>
一つ目の数字を入力してください:24
二つ目の数字を入力してください:11
ふたつの値の平均は
double型ans:17.500000
float型ans:17.500000
キャスト:17.5
です

実行結果からもわかるようにdoubleとfloatでは小数を扱えるということにおいて違いはありません。両者の違いは扱える範囲で、double型の方が広い範囲を扱えるよくらいの認識で大丈夫です。

ソースコードの説明

double型をprintfで出力するためには、変数指定フォーマットは%fとする必要があります。この時小数第6位まで表示されます。

ans_d = num1 + num2; //ans_d = (num1+num2)/2; としないことに注意
ans_d = ans_d/2;

の部分ですが、上の行ではint型の変数 num1 + num2 をdouble型の変数 ans_d に変換しています。上の例で言えば、num1 + num2 は 24 +11 なので 35 になります。それをdouble型に変換するので 35.000000 となります。
そして2行目で35.000000を2で割っているためans_dには17.500000が格納されているということになります。

“//ans_d = (num1+num2)/2; としないことに注意”とありますがなぜこれがダメなのでしょうか?

これは、35/2を計算した結果(=17[int型であるから小数点切り捨て])をdouble型に変換することになってしまい、ans_dに格納された数字は 17.000000 になってしまうということが問題です。

printf("	キャスト:%.1f\n", (double)(num1 + num2) / 2); //(num1+num2)をdouble型にキャスト

キャストとは、上で行った、ans_d = num1 + num2; の操作と似たようなもので、あらかじめ宣言していた型から別の型に変換するときに使います。
(double)(num1 + num2) の部分がキャストを行っている部分で、
(型名) 変数名
で宣言します。

また変数指定フォーマットを%.1fとしていますが”.1″とつけることで小数点第1位まで表示してくださいという指示を送ることができます。

このプログラムではint型のnum1とnum2をdouble型に変えるということを行っていますが、最初から
double num1,num2;
と宣言しておくという手法もあります。

そのとき、scanfの変数指定フォーマットは%lf(エルエフ)としなければならないことに注意しましょう。

scanf("%lf", &num1);

char型

続いては文字型のcharについてみていきましょう。

charは文字を格納する変数を扱うための型です。以下のプログラムで確認していきましょう。

/***
filename:char.c
***/

#include<stdio.h>

int main(void)
{
	char s1[] = "A";
	char s2[] = "ABC";
	
	printf("s1の文字列は %s\n",s1);
	printf("s2の文字列は %s\n",s2);
	printf("s2の文字列の1文字目は %c\n",s2[0]);
	printf("s2の文字列の2文字目は %c\n",s2[1]);
	printf("s2の文字列の3文字目は %c\n",s2[2]);
	printf("s2の文字列の4文字目は %c\n",s2[3]);
	
	return 0;
}

このソースコードを理解するためにはまず、配列について学ばなければいけません。一緒に確認していきましょう。

配列

配列は
型名 変数[要素数]
で宣言します。

変数とは文字や数字を格納するための箱のようなものです。配列はその箱を要素数ぶんだけ並べたものだと思ってください。図に示すとこんな感じ。

配列の要素数は指定しなければ、宣言された時の文字列と文字列の終わりを表す”\0″の分だけ用意されます。ですから上の変数sの配列の要素数は”ABC”と”\0″を合わせて4つということになります。
要素数は0番目から始まるので格納された文字のn番目を呼び出したいときには、
変数[n-1]
と宣言しなければいけません。

ソースコードの説明

printfで文字を出力するときの変数指定フォーマットは%sです。
逆に一文字だけ出力するときには%cを使います。



様々な型が扱えるようになったことで、作成できる範囲が広がったのではないかなと思います。
次回はif文やfor文など条件分岐について扱っていきます。条件分岐では配列が活躍するので、復習しておきましょう。

C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [1限目:変数と標準入出力]

前回の復習

前回はprintfをつかってHello World!という文字の出力を行いました。

しかし、printfで出力出来るのは文字だけではありません。プログラムの中で計算してその数値を出力するなんて事もできます。

ということで、今回は数値の出力から取り扱っていきます。

数値の出力

23+47を計算して出力するプログラムを作りましょう。以下のソースコードを見てください。

/******
filename:constant.c
*******/

#include<stdio.h>
int main(void)
{
	printf("%d\n",23+47);

	return 0;
}
■実行結果
70

コードの説明

%d

dはdecimal(10進数という意味です)の頭文字で、「以下の実引数を10進数で表示しでください」という書式の指定を行なっています。コードでいえば23+47が対象の実引数となります。

変数

変数というのは、文字や数字などの値を格納する箱のようなものです。aという箱に10という数字を入れるというようなイメージです。箱という表現はプログラミングにおいて、しばしば使われる表現です。

以下のプログラムは先程の計算を一度変数に代入して出力するプログラムです。

/*******
filename:variable.c
*******/

#include<stdio.h>
int main(void)
{
	int a=23;
	int b=47;
	int sum=a+b;
	
	printf("%d\n",sum);
	
	return 0;
}

 

■実行結果
70

コードの説明

int a=23

intというのは整数を意味します。ですからint aというのは変数aは整数の型ですよという宣言になります。他にも様々な型があります。

 
型名とその意味
型名 意味
int 整数型
double 浮動小数点数型(8バイト)
float 浮動小数点数型(4バイト)
char 文字型
void 型なし

また、a=23というのは変数aを23という値で初期化するということを意味します。

変数は宣言された時点である値が割り当てられます。そのままでは計算出来ないので最初に初期化してあげる必要があります。

またa=23というのは、変数aに23を代入するということを意味します。数学のようにaと23が等しいという意味ではありません。

プログラミングでは=で結んだ時、右の値を左の変数に代入するということを意味します。ですからプログラミングではa=bとb=aでは全く違うということに注意しましょう!

前回の復習part2

コードを書いていく上で最初に記述する呪文がありましたよね?

えーと。#include<stdio.h>だっけ?

そうです!ではstdioとはなんの略ですか?

standard input/output だから標準入出力だ!

さすがですね!完璧です。

stdioが標準入出力ならば出力があれば入力もあるはず。

ということで、入力について学習しましょう。

入力にはscanfを使おう!

今回はキーボードから数値を入力し、その値を使って計算して出力するプログラムを作成します。

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

/*****
filename:input.c
*****/

#include<stdio.h>
int main(void)
{
	int a=0;
	int b=0;
	
	printf("一つ目の値は?:");
	scanf("%d", &a);
	
	printf("二つ目の値は?:");
	scanf("%d", &b);
	
	printf("%d + %d = %d\n", a, b, a+b);
	
	return 0;
}

 

■実行結果[例]
一つ目の値は?:23
二つ目の値は?:47
23 + 47 = 70

コードの説明

scanf

キーボードからの入力をコンピュータが待つときに使われる命令です。キーボードから入力される値は、「,」以下の変数に格納されます。その際、&をつけることに注意しましょう。

今回のプログラムでは、scanf(“%d”,&a)となっているので、「aという変数にキーボードから入力された10進数の値を格納する」という命令になります。


次回は、今回少し触れた型について、整数型以外にも触れていきましょう。

C言語学習におすすめのテキストはこちら

【初心者向け】情報学部生と学ぶC言語 [0限目:C言語とは]

こんにちは。2浪1留現役大学生のつれなまです。今回から、まだまだ全然詳しくはない情報学部生の僕と一緒にC言語について学んでいきましょう。

え?C言語って難しいんじゃないの?

はい。その通りです。しかし、僕の大学では入学してすぐ必修科目としてC言語の演習がありました。当時はみんなC言語なんて習ったことも聞いたこともない状態でしたから、何をやっているかも理解できないまま、手探りで課題をこなしていました。しかし、学年が上がり他の言語などに触れるにつれ、C言語を学んでよかったなと思えるようになりました。

大学でも初学者に学ばせているくらいですから、しっかり学べば確実に意味のあるものになります。

まだまだ未熟な僕ですから、一緒に学ぶ気持ちで、C言語に触れていきましょう。

C言語はこんな人に向いてる

・コンピュータについて詳しく知りたい

・プログラミングを根本から学びたい

・勉強する時間と根気がある

・難しいものにチャレンジするのが好きだ

C言語学習におすすめのテキストはこちら

C言語とは

1972年に、Dennis M. Ritchieが開発したプログラミング言語です。

なんでCなの?

いい質問ですね。それはC言語が開発される以前にBCPL言語というものがありまして。その言語を参考にB言語というものが作られました。そしてその後継として生まれたのが、C言語だったわけです。Bの次だからC。まるでヤバTの曲みたいですね。

C言語って何に使えるの?

C言語はシステムからアプリ開発まで様々なことに使えますが、C言語で書くのが大変なので、敬遠されることも多いです。

C言語には実行速度が速いという特徴がありまして。分かりにくいかもしれませんが、今パソコンかスマホでこの画面を見ていて、画面をスクロールして動き出すまでに1秒,間が空いたらイラっと来ますよね?

ゲームで敵を見つけてボタンを押しているのに、反応するのに1秒かかったとしたら
マリオならクリボーにやられていることでしょう。そういった、処理速度の速さを活かしたい時、C言語は重宝されます。

それでは、今回はC言語を体験してみましょう。

C言語を始めるための準備

C言語をはじめるのに必要なもの

テキストエディタ

テキストエディタとは、C言語をはじめとする、プログラミング言語を記述するためのソフトのことです。windowsでは「メモ帳」、Macでは「テキストエディット」、Linuxだと「Vi」が最初から使えるようになっています。

標準のテキストエディタは、機能も少なく視覚的にも使いずらいですが、今回は体験ということで、これらを使っていきましょう。

便利なテキストエディタを使いたいよっていう方は、各自で「フリーテキストエディタ Mac(Windows/Linux)」なんかでネット検索してみてください。このサイトでも紹介できればいいのですが、2、3個ほどしか使ったことがないので紹介できません。すみません。

コンパイラ

コンパイラとは、人が記述したプログラミング言語(高級言語と言います)を機械語(低水準言語と言います)に直してやるプログラムのことです。

というのも、私たちが扱っているプログラミング言語とは、人間にとって分かりやすいような言葉である一方、そのままではコンピュータにとっては理解しにくいものとなっています。それをコンピュータに分かりやすい形に翻訳してあげるものがコンパイラというわけです。

外国人同士が会話するときに翻訳機を用いるようなものだと思ってください。

コンパイラをインストールしよう

Mac編

Finder→アプリケーション→ユーティリティ→ターミナル

の順に起動してください。

ターミナルを開いたら

「gcc」と記述しエンターキーを押してください。

すると「インストールしますか?」といった内容のポップアップが出てくると思うので、その指示に習ってインストールしてください。

出てこない人はすでにgccコンパイラがインストールされているはずです。

「gcc –version」と記述しエンターキーを押したあと以下のような表示が出てくればOKです。

windows編

Windowsでは、コンパイラをインストールするために「MinGW」というものをインストールしなければなりません。

こちらを参照してください。画像付きで分かりやすく説明してあります。3.拡張子の表示まで行っておけば、とりあえず大丈夫でしょう。

ソースコードを保存するためのフォルダを作ろう

お好きな場所に新規フォルダを作成してください。オススメの場所はデスクトップです。デスクトップで右クリックをすれば新規フォルダの作成ができるはずです。フォルダ名は「C」とでもしておいてください。

お疲れ様です。これでC言語を扱うための準備が整いました。

C言語を実際に書いてみよう

テキストエディタを開いてC言語を記述していきます。

Macでは、

標準では、Launchpadを開いて、その他のところに「テキストエディット」があると思います。見つからないよって人はLaunchpadの検索のところで「テキストエディット」で検索してください。

Windowsでは、

画面左下のロゴをクリックして「windows アクセサリ」→「メモ帳」の順に起動していきましょう。見つからない方は検索部分で「メモ帳」で検索してください。

起動できたら新規書類を開いて、以下のコードを記述していきましょう。

#include<stdio.h>
int main(void)
{
	printf("Hello World!\n");
	
	return 0;
}

 

記述し終えたら、「helloworld.c」という名前で、先ほど作った「C」フォルダに保存してください。

ソースコードの説明

#include<stdio.h>

ほぼ100%つかうので、毎回書く呪文のようなものだと思ってください。printfやscanfといった命令を使用するために記述します。

<stdio.h>のstdioは「standard input/output」の略で標準入出力を意味します。studioと間違えないように注意しましょう。

int main(void)

main関数と言います。関数については今後詳しく説明する予定です。

printf(“”)

「“と”の間にある文字の出力」という命令です。

return 0

return文と言います。0のことを戻り値と言います。

あー、クロアチア代表のサッカー選手ね!ってコラ

return文に関しても今後様々な使い方を紹介すると思いますが、とりあえずreturn 0で覚えておけば大丈夫です!

作ったソースコードを実行しよう

Macではターミナルを、windowsではコマンドプロンプトを開きましょう。

Macでは
△△△:~ ○○○$

windowsでは
△:○○○>

と書いてあると思います。○○○の部分をディレクトリと言いまして、今いる場所を表示しています。住所みたいなものだと思ってください。

それでは、

「cd 」***cdの後ろのスペースを忘れないこと!!***

と書いて、「C」フォルダをドラッグ&ドロップして、エンターキーを押してください。

先ほどの○○○の部分が「C」となっていれば、成功です。

ちなみに「cd」とはチェンジディレクトリの頭文字をとったものです。

続いて、

「gcc -o helloworld helloworld.c」

と書いてエンターキーを押しましょう。

このコマンドをコンパイルと言いまして、先ほどインストールしたコンパイラを使って、実行可能ファイルを生成するためのコマンドになります。

上記のhelloworldの部分は、生成したい実行可能ファイル名を指し、

helloworld.cは先ほど作った、コンパイルする対象のファイル名を記述します。

また、helloworldの部分を省略し、

「gcc -o helloworld.c」

とすることもできますが、その際「a.out」というファイルが自動生成されます。実行可能ファイル名が全て「a.out」となるので、実行前に毎回コンパイルしなければならないことに注意しましょう。

間違いなくコードを記述できていれば、helloworldという実行可能ファイルが生成されているはずです。

ターミナルまたはコマンドプロンプトで「ls(エルエス)」と書いてエンターを押してください。

helloworldと出てくれば成功です。

続いて、

「./helloworld」

と記述し、エンターを押せば、ファイルが実行され、

「Hello World!」

と出てくれば成功です。

これがC言語のソースコードの生成から実行までの流れになります。


「Hello World!」って出力されたからってなんだよと思われていると思いますが、C言語の可能性は無限大です。次回からも楽しんで学習していきましょう!

C言語学習におすすめのテキストはこちら

情報学部以外の人がIT系企業へ就活する時にプログラミング言語の勉強をお勧めしない理由

この記事はこんな人にオススメ

・情報系の学部以外からIT系企業へ就職するためにプログラミングを学ぼうと考えている方

・プログラミングを学ぶうえで目的が明確でない方

こんな人はこの記事には合いません

・プログラミングを学ぶ上で目的が明確な方

・コーダーとして活躍したい方

大学で情報系の学部へ通う僕には就活の時期になると、他学部の同年代の人から

「IT系の企業に就職しようと思ってるんだけど、プログラミング言語ってどれをやればいいの?」

と質問された。

その質問が来るといつも、

「またその質問か、、、」

と頭を悩ませることになる。

その理由が

  • プログラミング言語は、目的において最適な言語が異なる
  • そもそも言語を学ぶことに意味があるのか

という点である。

このことについて以下で解説していきたい。

プログラミング言語は、目的において最適な言語が異なる

システム開発ならCやJava、機械学習ならPython、webサイトならHTML、css、JavaScriptみたいに目的において、学ぶべき言語は異なってくる。

上で述べた

「IT系の企業に就職しようと思ってるんだけど、プログラミング言語ってどれをやればいいの?」

という質問が困るというのは、このことに該当している。

例えるなら、

「海外に住もうと思ってるんだけど、何語の勉強すればいいかな?」と問われているようなものだ。

この問いに答えようと思うと「世界共通語だしとりあえず英語でもやれば」というようなふわっとした返答しかできない。そもそもどこに住むか決めるのが先だろう。

そもそも言語を学ぶことに意味があるのか

勘違いして欲しくないのだがプログラミング言語は学ぶ価値がないという意味ではない。

タイトルにある通り、IT企業へ就職するために学ぼうと考えているのならば、プログラミング言語を知っていることが就活するうえでそんなにプラスになるとは思えないということである。

プログラミングについては、就職した後に周りに聞きながら使い方に慣れていったほうがはるかに効率的だと思うし、今の時代ネットで調べれば書き方やテンプレートは載っているので知っている必要もあまり感じない。

それなら何すればいいの?

僕のお勧めは、情報処理技術者試験の勉強である。

情報処理技術者試験とは、国家試験であり4つの区分に分けられ、簡単なものから順にITパスポート、基本情報技術者、応用情報技術者、スペシャリストの区分がある。

他学部からの就活で考えるなら基本情報技術者試験に合格していれば、情報技術についてある程度の知識があることの証明となり、就活を有利に進められるだろう。

情報処理技術者の秋季試験の申し込みが7月11日より受付が開始されます。僕は応用情報処理技術者試験を受けようと思い、今勉強中です。皆さんも一緒に受けてみませんか? 2019.07.05