C言語

目次

基本的な命令、ライブラリの使い方を確認することを目的としたプログラム例を載せています。

1.動作環境(サンプルの実行環境)
・VirtualBoxのCentOs7マシン
・CentOsのバージョン
# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
・コンパイラのバージョン
【cコンパイラ】
・パッケージ一覧
# yum list | grep gcc

・インストール
# yum -y install gcc
・バージョン確認
# gcc –version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

2.Cについて

(1)歴史
1972年、ベル研、Dennis Ritchieによって設計された。cは、科学技術計算などの問題を解決するための問題指向型(高級言語)に対して、コンピュータを動かすための言語として設計(機械指向型言語、低級言語)されたが、コンピュータの細部を意識しないで使えるので、低級以上、高級以下の位置づけの言語。

(2)プログラムのソースファイル作成から実行形式にするまでの流れ

gcc オプション
-Wall: gcc に 詳細なWarning を出力
-o file: 出力先をfileに指定
-v: コンパイルの各ステージで実行されるコマンドを表示する
-c: コンパイルのみ行い、リンクは行なわない
-S: コンパイルが終ったところで処理を中断する

(3)言語規格
・C90『JIS X 3010:1996 プログラム言語C』で規定されるC言語規格
・C99『JIS X 3010:2003 プログラム言語C』で規定されるC言語規格
・C11 C99の後継として、2011年に制定されたISO/IEC 9899:2011で規定されるC言語規格。最新の規格。
・MISRA C
 英国The Motor Industry Software Reliability Association(MISRA)によって定められた、C言語のコーディングガイドライン

3.Cプログラムのサンプル

3.1 サンプル1
 main()関数で構造体のメンバに値を設定して、値を出力する関数を呼んで表示するプログラム。1つのソースファイルに実装する場合と、2つのファイルに分けて実装する場合の2パターンについて作成する。
(1)1つのファイル(main1.cのみ)で実装する場合

main1.c

#include <stdio.h>

typedef struct _Person{  //構造体宣言
    char * name;
    int age;
}Person;

void send(Person mperson);//プロトタイプ宣言


int main(void){
    Person man1;
    man1.name="satou";
    man1.age=20;
    send(man1);
}

void send(Person mperson){
   printf("name:%s\n",mperson.name);
   printf("age:%d\n",mperson.age);
}

(2)2つのファイル(main2.c,member.c)で実装する場合

main2.c

#include "member.h"

int main(void){
    Person man1;
    man1.name="satou";
    man1.age=20;
    send(man1);
}

member.h

//構造体宣言
typedef struct _Person{
    char * name;
    int age;
}Person;

//プロトタイプ宣言
void send(Person mperson);

(解説)
member.cの関数の利用側で構造体が必要になるため、ヘッダファイルに含める

member.c

#include <stdio.h>
#include "member.h"

void send(Person mperson){
   printf("name:%s\n",mperson.name);
   printf("age:%d\n",mperson.age);
}

(解説)
printf()はこの関数内でのみ使用するため、標準ライブラリのインクルード文はヘッダファイルに入れない。
自分のヘッダファイルを読み込み、コンパイル時にチェックできるようにする。

4.文法とサンプル

4.1 入出力
標準の入出力関数

(1)putchar
stdio.hの中で定義されているマクロ。
仮引数のint型データの下位1バイトを切り出して標準出力に送る。
プロトタイプ int putchar(int)

sample_1.c

#include<stdio.h>
#include<stdlib.h>

int main(){
	int i;
	putchar('A');
	putchar(0x41);//16進
	putchar(65);//10進
  	putchar('\n');

	int a=0x44434241;
	for(i=0;i<4;i++){   //1バイトづつ取り出し
		putchar(a);
		a=a>>8;
		putchar('\n');
	}

	int b=0x44434241;
	putchar(b);
	putchar(b);
	putchar(b);
	putchar(b);
	putchar(b);
	putchar('\n');
  	return 0;
}

(2)printf
標準ライブラリに含まれている関数で、ヘッダファイルから関数の情報(関数プロトタイプ)を読み込む。
プロトタイプ
int printf(const char* format,…);
戻り値:int型 標準出力に渡したバイト数、エラーが発生した場合は負の値
printfは出力用、scanfは入力用に使われ、fは”formatted”で書式付きを表す。
書式は%(変換文字)で指定する。c:文字、d:10進整数、e:科学表記による浮動小数点数、f:浮動小数点数、s:文字列。
表示桁数は<全体の幅>.<小数点以下の幅>で指定。片方だけの指定、又は指定しなくても良い。指定がなければデフォルトが使用。 <小数点以下の幅>は、文字列の場合には最大文字数。

例)printf(“%s”,”abc”);

#include<stdio.h>
int main(void)
{
    printf("%c\n",'A'); 
    printf("-1は、符号付%d 符号無%u 16進%x\n",-1,-1,-1);
    printf("%sは%f\n","円周率", 3.14159); 
    return 0;
}

(3)getchar
stdio.hの中で定義されているマクロ。キーボードからの文字の読み取りに使われる。
プロトタイプ
int getchar(void);
戻り値:int型 受け取った0~255の範囲の値。エラーが起きた場合はEOF(多くの場合-1)を戻す

sample_3.c

#include<stdio.h>
int main(void)
{
        int c;
        c=getchar();
        printf("「%c」の文字コードは十進で%dです\n",c,c);        
        return 0;
}

(4)scanf
標準ライブラリに含まれている関数で、ヘッダファイルから関数の情報(関数プロトタイプ)を読み込む。標準ファイルstdinから文字を読み取る。
プロトタイプ
int scanf(const char *format,…);
戻り値:int型 読み込んだデータの数。エラーが起きた場合はEOF(多くの場合-1)を戻す。
書式は%(変換文字)で指定する。c:文字、d:10進整数、f:浮動小数点数(float)、lf:浮動小数点数(double)、s:文字列。
2個目以降の引数: データを格納するメモリー番地。

sample_2.c

include<stdio.h>

int main(void)
{
	int i;/*データを記憶する変数を用意*/
        double d;/*データを記憶する変数を用意*/

        scanf("%d", &i);/*入力を10進整数として読み、その値を変数iの番地のメモリーにint型で書きこむ*/
        scanf("%lf", &d);/*入力を実数として読み、その値を変数dの番地のメモリーにdouble型で書きこむ*/

        printf("i=%d d=%f \n", i, d);

        return 0;
}

4.2 データ型、演算子

(1)データ型
基本のデータ型は文字型 char 、整数型 int、実数型 float、倍精度実数型 double

データ型名値の範囲
char1バイトの符号付整数。ASCIIコードといった文字コードに使用。
unsigned char1バイトの符号なし整数
short2バイトの符号付整数
unsigned short2バイトの符号なし整数
long4バイトの符号付整数
unsignedlong4バイトの符号なし整数
int2または4バイトの符号付整数(コンパイラに依存)
unsigned 2バイトまた4バイトの符号なし整数(コンパイラに依存)unsigned intは簡略化してunsignedと書ける。
float4バイトの単精度浮動小数点実数
double8バイトの倍精度浮動小数点実数

バイト数と表現できる値(10進数)の範囲
(上段:符号無し/下段:符号有り、2の補数表示)
1バイト(8ビット):0~255
          -128~127
2バイト(16ビット):0~65,535
          -32,768~32,767
4バイト(32ビット):0~4,294,967,295
          -2,147,483,648~2,147,483,647
8バイト(64ビット):0~18,446,744,073,709,551,615
 -9,223,372,036,854,775,808~9,223,372,036,854,775,807

(2)リテラル(直定数)
リテラルを書けるのはデータ型で定義されたもののみ。
整数定数 int=5
実数定数 double=3.14, double=3.0e-10, double=3.14F、
文字定数 char=’A’ ,char=’\n’(改行),char=’\t’(タブ)
文字列定数 char=”Hello\n”,char=”あいうえお”

(3)変数
変数名はデータを記憶するメモリーの場所(アドレス)で変数の名前とデータ型を指定して定義する。データ型で必要なメモリーのバイト数がわかる。
例)int a;

(4)演算子
①算術演算子
 + 加算 a+b aにbを加えた値を戻す
 - 減算 a-b aからbを引いた値を戻す
 * 積算 a*b aとbの積の値を戻す
 / 除算 a/b aをbで割った商を戻す
  a,bが共に整数なら商も整数を戻す。
  aかbが実数なら実数の割り算結果を戻す。
 % 剰余算 a%b

②代入演算子
 = 代入 a=b bの値をaに代入する
 += 加算と代入 a+=b a=a+bと同じ
 -= 減算と代入 a-=b a=a-bと同じ
 *= 積算と代入 a*=b a=a*bと同じ
 /= 除算と代入 a/=b a=a/bと同じ
 %= 剰余算と代入 a%=b a=a%bと同じ

③インクリメント/ディクリメント演算子
 ++ 変数の値を1増加 ++a 増加して値を戻す(前置)
 ++ 変数の値を1増加 a++ 値を戻してから増加する(後置)
 – 変数の値を1減少 –a 減少させてから値を戻す(前置)
 – 変数の値を1減少 a– 値を戻してから減少する(後置)

④ビット演算子
 ~ ビット反転 ~a ビットを反転
 & ビット単位のAND a & b aとbのビット毎のAND
 | ビット単位のOR a | b aとbのビット毎のOR
 ^ ビット単位のXOR a ^ b aとbのビット毎のXOR
 << 上位bit側へのシフト a << n aのビットを上位側にn個シフト
  下位ビットは0を補充
 >> 下位bit側へのシフト a >> n aのビットを下位側にn個シフト             
  符号無しの変数は上位に0を補充(論理シフト)
  符号付の変数は最上位ビットの値を補充(算術シフト)

⑤演算子の優先順位と結合規則
・演算子優先順位
関数呼び出し () > 配列要素 [] > アドレス演算子 & > 単項 + - 
> インクリメント演算子 ++,ディクリメント演算子 –,論理演算の否定 !
> ビットの反転 ~,sizeof演算子,キャスト演算子など
乗算 * > 除算 / > 剰余算 % > 加算 + > 減算 – > ビットシフト << >> > 比較 < > <= >= など
・結合規則
優先順位が同じ演算子が連続しているときの優先順位
左から右:下記以外の2項演算子と条件演算子
a*b/cは(a*b)/cの順番
右から左:代入演算子、単項演算子、条件演算子
a=b=cはa=(b=c)の順番

⑥キャスト演算子
(変換先の型名)変換の対象

⑦自動型変換
演算子(オペレータ)の被演算数(オペランド)の型が演算子の想定に一致しない場合に自動的に型変換が行われる

4.3 制御文

4.3.1 判定
 等価演算子 == 等号   真:1 偽:0
 != 不等号  真:1 偽:0
 関係演算子 >,≧,<,≦ 真:1 偽:0
 論理演算子 
 論理積AND && 真:1 偽:0
 論理和OR || 真:1 偽:0
 否定 NOT ! 真:1 偽:0
 優先順位
(高い順)! , < , <= , > , >= , == , != , && , ||

4.3.2 if文(分岐)
if(条件式1)
{
  文1;
}
else if(条件式2)
{
  文2;
}
else
{
  文3;
}

4.3.3 switch文(分岐)
switch(式){
case 定数式1:
文1;
break;
case 定数式2:
文2;
break;
default:(どのcaseにもあてはまらない場合、defaultは省略可)
文3;
}
※定数式はリテラル、またはリテラル間の簡単な演算式でコンパイル時点で値が定まっている式

4.3.4 while文(繰り返し)
while(条件式){文1; 文2;... }
動作:条件式の値が真(0以外)なら文を実行し再び条件式の判定を行い、偽(0)になるまで繰り返す。
 文が1つしか無いときは、ブロック{}を省略できる。
while(条件式) 文 ;

4.3.5 do while文(繰り返し)
繰り返しの文を実行後に条件判定を行う
do {文1;文2; ...} while(条件式);
文が1つしか無いときは、ブロック{}を省略できる。
do 文 ; while(条件式);

4.3.6 for文(繰り返し)
for(初期設定式;条件式;再設定式) { 文1 ; 文2 ; 文3 }
文が1つしか無いときは、ブロック{}を省略できる。
for(初期設定式 ; 条件式 ; 再設定式) 文;
初期設定式を実行後、条件式の値が真(0以外)なら文を実行する。再設定式を実行後、再び条件式の判定を行う。

4.3.7 breakとcontinue文
(1)break文
Switch, while, for, do-while文から出て、次の文へ処理を移す命令
(2)continue文
whileやdo while文なら次の処理を条件式へ移す命令。for文の場合は再設定式へ移す。
breakが繰り返し文の外へ移す命令であるのに対して、continueは繰り返し文の残りをスキップする命令。

4.4 記憶クラスとスコープ
記憶領域はプログラム( 機械語命令)を記憶するコード領域とデータの記憶に使われるデータ領域があり、データ領域は、さらにメモリーの割り当て方でスタック領域(自動記憶域)、スタティック領域(静的記憶域)、ヒープ領域がある。

(1)スタック領域(自動記憶域)
 関数やブロックの中で変数を定義した変数はその関数やブロック内でのみ有効な局所変数(ローカル変数)。自動変数の有効期間は定義したブロックに入ってから出るまでで、ブロックから出たら再度利用される領域。

(2)スタティック領域(静的記憶域)
記憶クラス指定子staticを付けて定義した局所変数と、関数の外で定義したグローバル変数の記憶で使用される領域。
記憶場所の割り当てが変化しないので、多くの関数から名前で参照でき、データの受け渡しに使える。

(3)ヒープ領域
mallocやfree等の関数を用いてプログラム中でメモリーの確保と解放が行える領域で、ポインターを使うなどして確保したメモリーを利用する。

4.5 関数
(1)外部関数の定義と呼出し
1-3_main.c

#include<stdio.h>
#include<stdlib.h>
#include"1-3_func1.h"
int main(){
 func1();
 return 0;
}

1-3_func1.h

extern void func1(void);

1-3_func1.c

#include<stdio.h>
#include<stdlib.h>
#include"1-3_func1.h"
  void func1(){
  printf("これはグローバル関数です\n");
  }

(2)static変数の初期化は関数を最初に呼び出したときのみ
1-3-6_static.c

/*
  staticの変数は、最初だけ初期化されるため、1,1+1=2,
2+2=4,4+3=7,7+4=11となる
  staticの無い変数は都度初期化されるため、1,2,3,4,5となる
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void func(int i){
  static int value1=1;
  int value2=1;
  value1+=i;
  value2+=i;
  printf("value1=%d \n",value1);
  printf("value2=%d \n",value2);
}
int main(){
  int i;
  for(i=0;i<5;i++){
    func(i);
  }
  return(0);
}

4.6 配列

4.6.1 配列

(1)1次元配列
要素の型 配列名[要素数];
int a[5]={1,2,3,4,5};

(2)2次元配列
要素の型 配列名[行数][列数];
int[2][3]={{1,2,3},{4,5,6}};

(3)文字配列
char 配列名[要素数];
ポインタを使った書き方 char * 配列名;
文字列で初期化する場合は要素数を省ける
 char 配列名[ ]=”文字列”;
※配列の要素数は文字列の終端を示す\0を含むため、文字 コード分+1となる。
char t[2][2][2]={{{‘A’,’B’}{‘1′,’2’}},{{‘C’,’D’}{‘3′,’4’}}};

4.6.2 文字列

(1)strcpy()の使い方
1-4-9_const.c

/*
  strcpy()の使い方
  string.hをインクルードする
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TEST_STRING "This is test.\n"
int main(void){
  //char *src =TEST_STRING; //下記と同じ *pとp[]は同じ
  char src[]=TEST_STRING;
  char dst[sizeof(TEST_STRING)];
  //char dst[50]="12";//上書きされる
  strcpy(dst,src);
  printf("src:%s",src);
  printf("dst:%s",dst);
  return(0);
}

(2)strcpy()の使い方
test2.c

#include <stdio.h>
#include <string.h>
 
int main(void) {
    char str1[16] = "Hello World!";
    char str2[4];
    
    // 文字列のコピー
    strcpy(str2, str1);
    printf("str2の文字列は: %s\n", str2);
    
    return 0;
}

4.7 ポインタ
(1)オブジェクトのアドレス
double型の変数x(オブジェクトともいう)のアドレスは、アドレス演算子”&”で取り出せる。
double x;
&x;(これはdouble型のポインタ)

(2)ポインタ
ポインタ(オブジェクトを指し示すためのオブジェクトであり、ポインタを入れる変数)の宣言は、
double *pt;(double型オブジェクトへのポインタ型といい、略して、double型へのポインタ型、又はdouble *型という)
 ※ポインタの型は、オブジェクトのデータ型に一致させる必要がある。

(3)ポインタが指すオブジェクトの操作
 ポインタに間接演算子”*”を適用することで、ポインタが示すところのオブジェクトを操作できる。
double x;
double *pt;
pt=&x;
*pt;(xのエイリアス(別名)となる)

#include <stdio.h>

int main(void)
{
	double x=1.23;//初期値
	double *pt;//ポインタ宣言
	pt=&x;//変数xのアドレスをポインタに代入
	printf("代入前のx:%lf\n",x);
	*pt=1.25;//ポインタが示すオブジェクト(xのこと)に値を代入
	printf("代入後のx:%lf\n",x);
}

sample_7.c ポインタを介したオブジェトへの代入と読み出し

(4)ポインタの大きさ
sample_8.c

#include <stdio.h>
#include <limits.h>

int main(void)
{
	printf("1バイトのビット数:%d\n",CHAR_BIT);
	int x=0xF4F3F2F1;//初期値
	int *pt;//ポインタ宣言
	pt=&x;//変数xのアドレスをポインタに代入
	printf("代入前のx:%x\n",x);
	*pt=0xF8F7F6F5;//ポインタが示すオブジェクト(xのこと)に値を代入
	printf("代入後のx:%x\n",x);
	printf("xのアドレス:%p\n",&x);
	printf("xのサイズ:%d\n",(unsigned)sizeof(x));
	printf("ptのアドレス:%p\n",&pt);
	printf("ptのサイズ:%d\n",(unsigned)sizeof(pt));
	printf("ptが示すアドレス:%p\n",pt);
	printf("xのエイリアス*pt:%x\n", *pt);
	
}

4.8 列挙型
(1)enum(列挙型)
定数リストで定義される変数はメンバと言う。デフォルトでは定義されたメンバの順に0(ゼロ)から整数値を付与される。
1-4-7_enum.c

#include<stdio.h>
int main(){
  enum{Black,White,Blue,Red,Green};
  int c1;
  c1=Black;
  printf("%d \n",c1);
  return 0;
}

1-4-7-2_enum.c
最初のメンバに付ける整数値を定義することができる。また途中のメンバから付ける整数値を定義することもできる。

#include<stdio.h>
int main(){
  enum{
    Black=1,
    White,
    Blue,
    Red,
    Green
  };
  int c1;
  c1=White ;// 2
  printf("%d \n",c1);
  return 0;
}

(2)enumの使い方
エラー番号を取得して、case文でエラー番号に対応するエラー内容を表示する
2-2-3_main.c

#include <stdio.h>	
#include <stdlib.h>	
#include "2-2-3_func.h"	
	
int main(){	
  Device_Status num;	
  num=get_device_status();	
  char *name;	
  switch(num){	
  case DEVICE_ERROR:name="エラー";break;	
  case DEVICE_INITIALIZING:name="初期化中";break;	
  case DEVICE_RUNNING:name="動作中";break;	
  case DEVICE_WAITING:name="待機中";break;	
  case DEVICE_DISABLE:name="使用不可";break;	
  }	
  printf("デバイス状態:%s \n",name);	
  return 0;	
}	

2-2-3_func.h

//定数の宣言
typedef enum{
  DEVICE_ERROR = -1,  //エラー
  DEVICE_INITIALIZING,  //初期化中
  DEVICE_RUNNING,  //動作中
  DEVICE_WAITING,  //待機中
  DEVICE_DISABLE  //使用不可
} Device_Status;
//プロトタイプの宣言
Device_Status get_device_status();

typdefにより”Device_Status”が構造体の型名となる

2-2-3_func.c

#include <stdio.h>
#include <stdlib.h>
#include "2-2-3_func.h"
Device_Status get_device_status(){
  Device_Status error_no;
  return(error_no=DEVICE_INITIALIZING);
}

ここでは、enumで定義したエラーを返す。
gcc 2-2-3_main.c 2-2-3_func.h 2-2-3_func.c

4.9 プリプロセッサ
 プリプロセッサはコンパイル前の前処理で文字列の置き換えを行う。プリプロセッサの起動で処理されるものは、#include,#ifdef,#defineなどがある。

(1)#include文
 ソースファイルに別のファイル(ヘッダーファイル)を読みこむという機能で
ファイル名を「<>」でくくる方法と「””」でくくる方法の2つがある。
 「<>」でくくる方法はコンパイラーに環境変数などで設定されたパスから探す。
「””」でくくる方法はカレントディレクトリを探して、無ければコンパイラーに環境変数などで設定されたパスから探す。

(2)#ifdef文,#ifndef文
・インクルードのネストによって多重インクルードの発生を防止する
 #ifndef _FILE_INCLUDED
 #define _FILE_INCLUDED
 (ヘッダファイルの本体)
 #endif /* _FILE_INCLUDED */

 ヘッダファイル名”_FILE_INCLUDED”(名前は任意)が定義されていないときは定義してヘッダファイルを読み込む。また、ヘッダファイル名”_FILE_INCLUDED”が定義されていたときはヘッダファイルは読み込まないで#endifに移る。

・先に定義を有効になる書き方
 #ifndef MAX(x,y)
#define MAX(x,y) ・・・
#endif

・後に定義した方が有効になる書き方
#ifdef MAX(x,y)
#undef MAX(x,y) ・・・
#endif
#define MAX(x,y)・・・

(3)#define文
 文字列の置き換えを行う。
・定数の定義
#define PI 3.14
・マクロの定義
#define MAX(x,y) ((x)>(y) ? (x):(y))
sample_11.c

#define PI 3.14
#define MAX(x,y) ((x)>(y) ? (x):(y))
#include <stdio.h>

int main(void){
    printf("PI:%5.3f\n",PI);
    int x=1;
    int y=2;
    printf("MAX(%d,%d):%d\n",x,y,MAX(x,y));
}

4.10 構造体と共用体

4.10.1 構造体
 複数のデータを格納する箱(変数)をつくるとき、配列は同じ型のデータを複数格納できるが、構造体では異なるデータを複数格納することができる。
(1)構造体の型を作成
struct タグ名
{
 データ型 メンバ名;
 データ型 メンバ名;
 データ型 メンバ名;

};

(2)構造体の宣言
・変数名の構造体を1つ作成するとき。
 struct タグ名 構造体変数名;
・同じ変数名の構造体を複数作成するとき。
 struct タグ名 構造体変数名[要素数];

(3).演算子
 構造体オブジェクト内のメンバは”オブジェクト名.メンバ名”で参照。

(4)構造体の初期化
 各メンバに与える初期化子を{ , ,・・・}の形でコンマで区切って順に並べる。

sample_12.c

#include <stdio.h>

int main(void){
    //構造体の名前(タグ)をmenberとする
    struct member {
        char* name;
        int age;
    };

    //構造体のオブジェクトを定義
    struct member s1={"suzuki",20};//初期化
    struct member s2;

    //構造体のオブジェクトに値をセット
    //s1.name="suzuki";
    //s1.age=20;
    s2.name="satou";
    s2.age=35;

    //構造体のオブジェクトから値を取得
    printf("s1-name:%.10s\n",s1.name);
    printf("s1-age:%d\n",s1.age);
    printf("s2-name:%.10s\n",s2.name);
    printf("s2-age:%d\n",s2.age);

return (0);
}

(5)構造体中の構造体
 構造体のメンバとして、構造体のオブジェクトを持つことができる
sample_13.c

#include <stdio.h>

int main(void){

    struct team {
        char* t_name; 

        struct member{
            char* m_name;
            int age;
        }m1; //teamのメンバとしてオブジェクトを定義する
   }; 
    //構造体teamのオブジェクトを定義
    struct team t1;
    //値の設定
    t1.m1.m_name="suzuki";
    t1.m1.age=20;
    t1.t_name="tokyo";

    //構造体のオブジェクトから値を取得
    printf("t1.m1.name:%.10s\n",t1.m1.m_name);
    printf("t1.m1.age:%d\n",t1.m1.age);
    printf("t1.t_name:%.10s\n",t1.t_name);

return (0);
}

4.10.2 共用体
 構造体が複数のメンバを同時に持つのに対して、共用体は記憶域を共有するため、同時には1つのメンバのみを持つ。

sample_14.c

#include <stdio.h>

int main(void){
    //構造体の名前(タグ)をmenberとする
    union xy {
        int x;
        double y;
    };

    //構造体のオブジェクトを定義
    union xy xy1;
    //構造体のオブジェクトに値をセット
    xy1.x=10;
    //構造体のオブジェクトから値を取得
    printf("xy1.x:%d\n",xy1.x);
    printf("xy1.y:%f\n",xy1.y);
    printf("xy1.xのアドレス:%p\n",&xy1.x);
    printf("xy1.yのアドレス:%p\n",&xy1.y);

return (0);
}

4.11 ファイル入出力
①ファイルを開く
 FILE *fopen(const cahr *fname, const char *mode);
 fopen関数は、ファイルの読み書きに必要な情報を入れるFILE構造体を作成して、そのアドレスをFILE型のポインタとして返す。
 ”r”:読み込み専用でテキストファイルを開く。
 ”w”:書き出し専用で新しいテキストファイルを開く。
 同名 の既存ファイルがある場合ファイルは消されて空のファイルが作られる。
 ”a”:追記専用でテキストファイルを開く。
 同名の既存ファ イルがある場合データは既存ファイルに追記される。
 ”r+”:更新(読み書き可能)用でテキストファイルを開く。
 ”w+”:更新(読み書き可能)用で新しいテキストファイル を開く。
 同名の既存ファイルがある場合ファイルは消されて空のファイルが作られる。

②ファイルを閉じる
 int fclose(FILE *stream);
 fclose関数は、必要でなくなったFILE構造体のメモリーを開放する。
 streamが入力の場合はまだ読まれていないデータを捨て、出力の場合はバッファのデータをフラッシュする。
 streamが指すFILE型領域を解放しファイルを閉じる。正常で0、異常でEOFを戻す。

③ファイルへの書き込み
・指定した文字列をファイルポインタが示すファイルに書き込む
 int fputs(const char * str, FILE * fp);
 引数1:ファイルへ書き込みたい文字列へのポインタ
 引数2:文字列を書き込みたいファイルポインタ
 戻り値:正常書き込み0、書き込み失敗で「EOF(-1)」を返す

④ファイルから読み出し
・ファイルから1文字読み出す
 int fgetc(FILE * fp);
 引数1:文字を読み込みたいファイルポインタ
 戻り値:ファイルから読み込んだ1文字
 ファイルの終端まで読み込んだ場合は「EOF」が戻り値となる。
 読み込み異常時も「EOF」が戻り値となる。

・ファイルから1行分の文字列(改行文字まで)を読み出す
 char * fgets( char *s , int len , FILE *fp );
 第一引数は文字配列のポインタ
 第二引数は一行の最大文字数
 第三引数はファイルポインタ
 戻り値:ファイルポインタfpから1行、またはlenバイト読み込んでその先頭アドレスを返す。
 全行を読み込んだ場合、又はエラー時にNULL(\0)を返す。

(1)ファイル書き込み
sample_5.c

#include <stdio.h>

int main(void)
{
	FILE * fp = NULL;
	fp=fopen("Hello.txt", "w");
	fputs("Hello\n", fp);
	fputs("World\n", fp);
	fclose(fp);
	return 0;
}

Hello.txt

(2)ファイル読み出し
sample_6.c

#include <stdio.h>

int main(void)
{
	char s[15];
	FILE * fp = NULL;
	fp=fopen("Hello.txt", "r");
	if (fp == NULL) {
        	printf("file open errer.\n");
        	return 1;
    	}
	while(fgets(s, 15, fp) != NULL) {
		printf("%s", s);
	}
	fclose(fp);
	return 0;
}

The subject ends herewith.

javaフレームワークSpringBootを使ったCRUDアプリケーションの作成

1.環境
(1)開発環境
OS: Windows 10 Pro
IDE:Eclipse IDE for Enterprise Java Developers Version: 2020-12 (4.18.0)
Java version:11.0.9、Tomcat v8.0

(2)データベース
XAMPPのmysql
mysql Ver 15.1 Distrib 10.4.17-MariaDB, for Win64 (AMD64)

2.アプリケーションの概要
 データベースに対して、ユーザー名の登録、参照、更新、削除を行う。

3.設計
(1)CRUD表

(2)ER図

(3)クラス図

(4)シーケンス図

4.実装
(1)プロジェクトフォルダ作成
ファイル>新規>その他を選択し、「ウイザードを選択」画面を表示


「Springスタータ・プロジェクト」を選択

ライブラリの選択

(2)プロパティファイルの編集
Mysqlの接続情報を書く

(3)ソースファイル

テンプレート

index.html(ユーザー管理画面)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>メニュー</title>
</head>
<body>
	<h2>【ユーザー管理】</h2>
	<form action="mypage" method="post">
	   <input type="submit" name="menu1" value="「ユーザー登録」" style="width:200px;height:50px;margin:10px"><br>
	   <input type="submit" name="menu2" value="「ユーザー一覧」" style="width:200px;height:50px;margin:10px">
	</form>
</body>
</html>

UserReghist.html(ユーザー登録画面)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>登録</title>
</head>
<body>
	<h2>【ユーザー登録】</h2>
	<form action="userreghist" method="post">
		名前:<input type="text" name="user_name"><br>
		<input type="submit" name="enter" value="登録">
		<input type="submit" name="back" value="戻る">
	</form>
</body>
</html>

UserList.html(ユーザー一覧画面)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>ユーザー一覧画面</title>
	<style type="text/css">
		/* 基本のテーブル定義 */
		.t {border:1px solid   #000000;border-collapse:collapse;table-layout:fixed;font-size:16px}
		.t td{border:1px solid #000000;height:16px;}
		.t th{border:1px solid #000000;font-size:16px}
		.t th{background-color:#FFBB88;color:#000000;}
		.t tr:nth-child(odd)  td{background-color:#C8C8E8;color:#000000;}
		.t tr:nth-child(even) td{background-color:#E8E8FF;color:#000000;}
		.t1{width:550px;}
		.t2{width:50px}
		.fixed{position: sticky;
			 top: 0;}
		#data {
		   overflow-x:scroll;overflow-y:scroll;
		   width:700px;height:245px;
		   }
		</style>
</head>
<body>
	<h2>【ユーザー一覧】</h2>
	<div id="data">
	<table class=t>
		<tr>
			<th class="t1 fixed">名前</th>
			<th class="t2 fixed">ボタン</th>
			<th class="t2 fixed">ボタン</th>
			<th class="t2 fixed">ID</th>
		</tr>
		<tr th:each="entity : ${data}">
			<td class="t1" th:text="${entity.user_name}"></td>
			<td>
			<form th:action="userlist" name="ref" method="post" >
			    <input type="submit" name="ref" class="t2" value="変更">
			    <input type="hidden" name="user_id" th:value="${entity.user_id}">
		    </form>
		    </td>
		    <td>
		    <form th:action="userlist" method="post" >
	            <input type="submit" name="del" class="t2" value="削除">
	            <input type="hidden" name="user_id" th:value="${entity.user_id}">
	        </form>
	   		</td>
	   		<td class="t2" th:text="${entity.user_id}"></td>
	   	</tr>
	</table>
	</div>
	<form th:action="userlist" method="post" >
		<input type="submit" name="back" value="戻る">
	</form>
</body>
</html>

UserUpdate.html(ユーザー変更画面)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>ユーザー変更</title>
</head>
<body>
	<h2>【ユーザー変更】</h2>
	<form th:action="userupdate" th:object="${data}" method="post">
	名前:<input type="text" name="user_name" th:field="*{user_name}">
		<input type="hidden" name="user_id" th:field="*{user_id}"><br>
		<input type="submit" name="enter" value="登録">
		<input type="submit" name="back" value="戻る">
	</form>
</body>
</html>

OK.html(登録成功確認画面)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>登録確認画面</title>
</head>
<body>
	<h2>【登録確認】</h2>
	<p th:text="${user_name}"/>さん登録しました
	<form action="userreghist" method="post">
    	<input type="submit" name="back" value="確認" style="width:200px;height:50px;margin:10px"><br>
    </form>
</body>
</html>

DelOK.html(削除成功確認画面)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>削除確認画面</title>
</head>
<body>
	<h2>【削除確認】</h2>
	<p th:text="${user_id}"/>さん削除しました<br>
	<form action="delok" method="post">
	    <input type="submit" name="back" value="確認" style="width:200px;height:50px;margin:10px"><br>
    </form>
</body>
</html>

UserCnt.java(コントローラ)

package com.example.demo;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserCnt {

	@Autowired
	DataEntityRepository repository;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String index() {
	    return "index";
	}

	@RequestMapping(value = "mypage", params = "menu1", method = RequestMethod.POST)
	public String mypage1(Model model) {
		return "UserReghist";
	}

	@RequestMapping(value = "mypage", params = "menu2", method = RequestMethod.POST)
	public String mypage2(Model model) {
		//データベースから一覧取得して、オブジェクトに入れる
		List<DataEntity> data = repository.findAll();
		//テンプレートで表示する値をセット
		model.addAttribute("data",data);
		return "UserList";
	}

	@RequestMapping(value = "userreghist", params = "enter", method = RequestMethod.POST)
	public String userreghist1(
			@RequestParam("user_name")String u_name,
			Model model) {
		//テンプレートで表示する値をセット
		model.addAttribute("user_name", u_name);
		//DBに1レコード保存する
		repository.save(new DataEntity(u_name));
		return "OK";
	}

	@RequestMapping(value = "userreghist", params = "back", method = RequestMethod.POST)
	public String userreghist2(Model model) {
		return "index";
	}


	@RequestMapping(value = "userlist", params = "ref", method = RequestMethod.POST)
	public String userlist1(
			@RequestParam Integer user_id,
			Model model) {
		//データベースから検索取得して、オブジェクトに入れる
		Optional<DataEntity> data = repository.findById(user_id);
		//テンプレートで表示する値をセット
		model.addAttribute("data",data);
		return "UserUpdate";
	}

	@RequestMapping(value = "userlist", params = "del", method = RequestMethod.POST)
	public String userlist2(@RequestParam Integer user_id,
		Model model) {
		//テンプレートで表示する値をセット
		model.addAttribute("user_id", user_id);
		//DBから削除する
		repository.deleteById(user_id);
		return "DelOK";
	}

	@RequestMapping(value = "userlist", params = "back", method = RequestMethod.POST)
	public String userlist3(Model model) {
		return "index";
	}


	@RequestMapping(value = "userupdate", params = "enter", method = RequestMethod.POST)
	public String userupdate1(@RequestParam Integer user_id,
			@RequestParam String user_name,
			Model model) {
		//テンプレートで表示する値をセット
		model.addAttribute("user_name", user_name);
		repository.save(new DataEntity(user_id,user_name));
		return "OK";
	}

	@RequestMapping(value = "userupdate", params = "back", method = RequestMethod.POST)
	public String userupdate2(Model model) {

		return "index";
	}

	@RequestMapping(value = "delok", params = "back", method = RequestMethod.POST)
	public String delok(Model model) {

		return "index";
	}

}

使用したアノテーション
@Controller
コントローラとして認識され、returnで指定したテンプレートをレンダリングして表示する
@Autowired
インスタンスを生成する
@RequestMapping
マッピングするアドレスの指定とGET/POSTメソッドの種類を指定
@RequestParam
送信される項目の名前をもつパラーメータ値を割り当てる

DataEntity.java(エンティティクラス)

package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class DataEntity {
	@Id
	@GeneratedValue
	private Integer user_id;
	private String user_name;

	public DataEntity() {
		super();
	}

	public DataEntity(Integer user_id) {
		super();
		this.user_id = user_id;
	}

	public DataEntity(String user_name) {
		super();
		this.user_name = user_name;
	}

	public DataEntity(Integer user_id, String user_name) {
		super();
		this.user_id = user_id;
		this.user_name = user_name;
	}

	public Integer getUser_id() {
		return user_id;
	}

	public void setUser_id(Integer user_id) {
		this.user_id = user_id;
	}

	public String getUser_name() {
		return user_name;
	}

	public void setUser_name(String user_name) {
		this.user_name = user_name;
	}

	@Override
	public String toString() {
		return "DataEntity [user_id=" + user_id + ", user_name=" + user_name + "]";
	}
}

使用したアノテーション
@Entity
エンティティクラスとして認識される
@Id
プライマリキーを指定
@GeneratedValue
自動的に値が生成される

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface DataEntityRepository extends JpaRepository<DataEntity, Integer> {

}

DataEntityRepository.java(JpaRepositoryインターフェース)

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface DataEntityRepository extends JpaRepository<DataEntity, Integer> {

}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>Crud_Springsample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>Crud_Springsample</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

(4)データベースとテーブル作成
 データベースは自動的に作成される
 データベース名:crud_sample
 テーブル名:data_entity(フィールド値を保存)
  hibernate_sequence(シーケンス番号を保存)

5.実行
(1)XAMPPのMySQLサーバを起動する

(2)アプリケーションを選択して、実行ボタン>「SpringBootアプリケーション」を押す

(3)ブラウザからWebサーバに接続
http://localhost:8080/

「ユーザー登録」ボタン押下

名前:テストネームを入力し、「登録」ボタン押下

「ユーザー管理」画面で「ユーザー一覧」ボタン押下

「変更」ボタン押下

「削除」ボタン押下

The subject ends herewith.

JavaサーブレットとJSPファイルを使ったCRUDアプリケーションの作成

1.環境
(1)開発環境
OS: Windows 10 Pro
IDE:Eclipse IDE for Enterprise Java Developers Version: 2020-12 (4.18.0)
Java version:11.0.9、Tomcat v8.0
(2)データベース
XAMPPのmysql
mysql Ver 15.1 Distrib 10.4.17-MariaDB, for Win64 (AMD64)

2.アプリケーションの概要

 データベースに対して、ユーザー名の登録、参照、更新、削除を行う。

3.設計
(1)CRUD表

(2)ER図

(3)クラス図

(4)シーケンス図

4.実装
(1)プロジェクトフォルダ作成
ファイル>新規>その他を選択し、「動的Webプロジェクト」を選択

(2)mysqlドライバーのビルドパスを設定
 プロジェクトフォルダのWebContent/WEB-INF/libに
MysqlコネクタMysql-connector-java-8.0.12.jarをダウンロードし保存する。
https://dev.mysql.com/downloads/connector/j/
 プロジェクトを選択してマウス右ボタンで「ビルド・パス」>「ビルド・パスの構成」を選択して、「javaのビルドパス」の画面を表示する。(下図)
「JARの追加」を選択し、「JARの選択」画面で、WebContent/WEB-INF/lib配下の「Mysql-connector-java-8.0.12.jar」を選択して、適用する。

(3)ソースファイル
Index.jsp(ユーザー管理画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>メニュー</title>
</head>
<body>
<h2>【ユーザー管理】</h2>
<a href="/Crud_sample/view/UserReghist.jsp">『ユーザー登録』</a><br>
<a href="/Crud_sample/UserCnt2">『ユーザー一覧』</a>
</body>
</html>


UserReghist.jsp(ユーザー登録画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>登録</title>
</head>
<body>
	<h2>【ユーザー登録】</h2>
	<form action="/Crud_sample/UserCnt" method="post">
		名前:<input type="text" name="user_name"><br>
		<input type="submit" value="登録">
		<a href="/Crud_sample/index.jsp">戻る</a>
	</form>
</body>
</html>


UserList.jsp(ユーザー一覧画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="model.UserModel,java.util.ArrayList,java.util.Iterator" %>

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>ユーザー一覧画面</title>
	<style type="text/css">
	/* 基本のテーブル定義 */
	.t {border:1px solid   #000000;border-collapse:collapse;table-layout:fixed;font-size:16px}
	.t td{border:1px solid #000000;height:16px;}
	.t th{border:1px solid #000000;font-size:16px}
	.t th{background-color:#FFBB88;color:#000000;}
	.t tr:nth-child(odd)  td{background-color:#C8C8E8;color:#000000;}
	.t tr:nth-child(even) td{background-color:#E8E8FF;color:#000000;}
	.t1{width:550px;}
	.t2{width:50px}
	.fixed{position: sticky;
		 top: 0;}
	#data {
	   overflow-x:scroll;overflow-y:scroll;
	   width:700px;height:245px;
	   }
	</style>
</head>
<body>
	<h2>【ユーザー一覧】</h2>
	<form action="/Crud_sample/UserCnt2" method="post" >
		<div id="data">
		<table class=t>
			<tr>
				<th class="t1 fixed">名前</th>
				<th class="t2 fixed">ボタン</th>
				<th class="t2 fixed">ボタン</th>
				<th class="t2 fixed">ID</th>
			</tr>
			<%
			//リクエストスコープからインスタンスを取得。
			ArrayList<UserModel> user_s=(ArrayList<UserModel>)request.getAttribute("userlist");
			//インスタンスがNULLでないとき、イテレータで1件づつ取り出す
			if(user_s!=null){
				Iterator<UserModel> iterator = user_s.iterator();
				while(iterator.hasNext()){
					 UserModel user = (UserModel)iterator.next();
					int uid=user.getUser_id();
			%>
				<tr>
				<td class="t1"><%=user.getUser_name() %></td>
				<td><button type="submit" name="ref" class="t2" value=<%=uid %> >変更</button></td>
				<td><button type="submit" name="del" class="t2" value=<%=uid %> >削除</button></td>
				<td class="t2"><%=user.getUser_id() %></td>
				</tr>
			<%
				}
			}
			%>
			</table>
		</div>
		<a href="/Crud_sample/index.jsp">戻る</a>
	</form>
</body>
</html>


UserUpdate.jsp(ユーザー変更画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="model.UserModel" %>
<%
//リクエストスコープからオブジェクト取得
UserModel user_m=(UserModel)request.getAttribute("user_m");
int id=user_m.getUser_id();
String user_name=user_m.getUser_name();
%>

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>ユーザー変更</title>
</head>
<body>
	<h2>【ユーザー変更】</h2>
	<form action="/Crud_sample/UserCnt3" method="post">
		id:<%=id %>
		<input type="hidden" name="user_id" value=<%=id %>><br>
		名前:<input type="text" name="user_name" value=<%=user_name %>><br>
		<input type="submit" value="登録">
		<a href="/Crud_sample/index.jsp">戻る</a>
	</form>
</body>
</html>


OK.jsp(登録成功確認画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ page import="model.UserModel" %>
<%
//リクエストスコープからオブジェクト取得
UserModel user_m=(UserModel)request.getAttribute("user_m");
%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>登録確認画面</title>
</head>
<body>
	<h2>【登録確認】</h2>
	<%=user_m.getUser_name() %> さん登録しました<br>
	<a href="/Crud_sample/index.jsp">確認</a>
</body>
</html>


NG.jsp(登録失敗確認画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>登録確認画面</title>
</head>
<body>
	<h2>【登録確認】</h2>
	登録に失敗しました<br>
	<a href="/Crud_sample/index.jsp">確認</a>
</body>
</html>


DelOK.jsp(削除成功確認画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="model.UserModel" %>
<%
//リクエストスコープからオブジェクト取得
UserModel user_m=(UserModel)request.getAttribute("user_m");
%>

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>削除確認画面</title>
</head>
<body>
	<h2>【削除確認】</h2>
	user_id:<%=user_m.getUser_id() %> さん削除しました<br>
	<a href="/Crud_sample/index.jsp">確認</a>
</body>
</html>


DelNG.jsp(削除失敗確認画面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>削除確認画面</title>
</head>
<body>
	<h2>【削除確認】</h2>
	削除に失敗しました<br>
	<a href="/Crud_sample/index.jsp">確認</a>
</body>
</html>


UserCnt.java(コントローラ)
「ユーザー登録画面」からのpost受信処理

package controller;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import model.UserModel;
import model.UserRegist;

/**
 * Servlet implementation class User_cnt
 */
@WebServlet("/UserCnt")
public class UserCnt extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserCnt() {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//リクエストパラメータの文字コードを指定
	    request.setCharacterEncoding("UTF-8");
	    //リクエストパラメータの取得
	    String user_name=request.getParameter("user_name");
	    System.out.println("user_name:"+user_name);
	    //Modelオブジェクト作成
	    UserModel user_m=new UserModel();
	    user_m.setUser_name(user_name);
	    //DAOのメソッドを使いDBに登録
	    UserRegist u=new UserRegist();
	    boolean res=u.user_create(user_m);
	    //リクエストスコープに保存(ユーザ名を表示するため)
	    request.setAttribute("user_m", user_m);
	    //DBへの保存結果でOK、又はNGのポップアップ表示
	    if(res==true) {
	    	//OK画面へフォワード
	    	 RequestDispatcher dispatcher=request.getRequestDispatcher("/view/OK.jsp");
		      dispatcher.forward(request, response);
	    }else {
	    	//NG画面へフォワード
	    	 RequestDispatcher dispatcher=request.getRequestDispatcher("/view/NG.jsp");
		      dispatcher.forward(request, response);
	    }
	}
}


UserCnt2.java(コントローラ)
「ユーザー管理画面」からのget受信処理
「ユーザー一覧画面」からのpost受信処理

package controller;

import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import model.UserModel;
import model.UserRegist;

/**
 * Servlet implementation class UserCnt2
 */
@WebServlet("/UserCnt2")
public class UserCnt2 extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserCnt2() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//DAOのインスタンス作成
		UserRegist s=new UserRegist();
		//DBの参照結果のArrayListオブジェクト作成
		ArrayList<UserModel> userlist=s.user_listget();
        //DBの参照結果をリクエストスコープに保存
        request.setAttribute("userlist", userlist);
  	    //ユーザー一覧画面にフォワード
  		RequestDispatcher dispatcher=request.getRequestDispatcher("/view/UserList.jsp");
        dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
	    //リクエストパラメータの文字コードを指定
	    request.setCharacterEncoding("UTF-8");
	    //リクエストパラメータの取得
	    String button1=request.getParameter("ref");
	    String button2=request.getParameter("del");
	    //変更釦、又は削除釦の処理
	    if(button1==null && button2==null) {
	    	System.out.println("変更釦、削除釦の対象:NULL");
	    }else {
		    if(button1==null){
		    	System.out.println("変更釦の対象:NULL");
		    }else{
		    	System.out.println("変更釦の対象id:"+button1);
				UserRegist s=new UserRegist();
				int key=Integer.parseInt(button1);
				UserModel user_m=s.ref(key);//戻り値
				System.out.println("戻り値:"+user_m);
				System.out.println(user_m.getUser_id());
		      	System.out.println(user_m.getUser_name());

			      //リクエストスコープに保存
				  request.setAttribute("user_m", user_m);
			      //変更画面にフォワードする
			      RequestDispatcher dispatcher=request.getRequestDispatcher("/view/UserUpdate.jsp");
			      dispatcher.forward(request, response);
		    }

		    if(button2==null){
		    	System.out.println("削除釦の対象:NULL");
		    }else{
		    	System.out.println("削除釦の対象id:"+button2);

		   	//指定されたレコードの削除
		    	UserRegist s=new UserRegist();
		    	int key=Integer.parseInt(button2);

		    	//レコード削除メソッド
				boolean res=s.user_del(key);//戻り値boolean

				UserModel user_m=new UserModel();
				user_m.setUser_id(key);
				if(res==true) {
					//削除処理成功画面にフォワードする
					request.setAttribute("user_m", user_m);
				    RequestDispatcher dispatcher=request.getRequestDispatcher("/view/DelOK.jsp");
				    dispatcher.forward(request, response);
				}else {
					System.out.println("レコードの削除失敗");
					//削除処理失敗画面にフォワードする
				    RequestDispatcher dispatcher=request.getRequestDispatcher("/view/DelNG.jsp");
				    dispatcher.forward(request, response);
				}
		    }
	    }
	}
}

UserCnt3.java(コントローラ)
「ユーザー変更画面」からのpost受信処理

package controller;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import model.UserModel;
import model.UserRegist;

/**
 * Servlet implementation class UserCnt3
 */
@WebServlet("/UserCnt3")
public class UserCnt3 extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserCnt3() {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//リクエストパラメータの文字コードを指定
	    request.setCharacterEncoding("UTF-8");
	    //リクエストパラメータの取得
	    String user_id=request.getParameter("user_id");
	    String user_name=request.getParameter("user_name");
	    //UserModelクラスのインスタンスに保存
	    UserModel user_m=new UserModel();
	    int id = Integer.parseInt(user_id);
	    user_m.setUser_id(id);
	    user_m.setUser_name(user_name);
	    //InfoRegistクラスのメソッドにDBに保存する値を値参照渡し
	    UserRegist u=new UserRegist();
	    boolean res=u.user_update(user_m);
	    //リクエストスコープに保存
	    request.setAttribute("user_m", user_m);
	    //DBに保存OK、又はNGのポップアップ表示
	    if(res==true) {
	    	//OK画面へフォワード
	    	 RequestDispatcher dispatcher=request.getRequestDispatcher("/view/OK.jsp");
		      dispatcher.forward(request, response);
	    }else {
	    	//NG画面へフォワード
	    	 RequestDispatcher dispatcher=request.getRequestDispatcher("/view/NG.jsp");
		      dispatcher.forward(request, response);
	    }
	}
}

UserModel.java(データモデル)

package model;

import java.io.Serializable;

public class UserModel implements Serializable {
	private int user_id;
	private String user_name;
	//コンストラクタ
	public UserModel(int user_id, String user_name) {
		super();
		this.user_id = user_id;
		this.user_name = user_name;
	}
	public UserModel(String user_name) {
		super();
		this.user_name = user_name;
	}
	public UserModel() {
		super();
	}
	//ゲッターセッター
	public int getUser_id() {
		return user_id;
	}
	public void setUser_id(int user_id) {
		this.user_id = user_id;
	}
	public String getUser_name() {
		return user_name;
	}
	public void setUser_name(String user_name) {
		this.user_name = user_name;
	}
}


UserRegist.java(DAOパターン)

package model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;

public class UserRegist {
    static final String URL ="jdbc:mysql://localhost:3306/crud_sample?characterEncoding=UTF-8&serverTimezone=JST";
	static final String USERNAME ="root";
	static final String PASSWORD ="";

	public boolean user_create(UserModel user_m) {
	    try {
	        // MySQLのドライバを指定
	    	Class.forName("com.mysql.cj.jdbc.Driver");
            // MySQLデータベースに接続 (DB名,ID,パスワードを指定)
	    	Connection connection = DriverManager.getConnection(URL, USERNAME,PASSWORD);
	    	System.out.println("DB接続OK");
			String str1=user_m.getUser_name();
            // ステートメントを作成
            Statement stmt = connection.createStatement();
            String str="INSERT INTO tbl_user(user_name) VALUES('" + str1 + "')";
            //sql実行
            stmt.executeUpdate(str);
            // ステートメントをクローズ
            stmt.close();
            // 接続をクローズ
            connection.close();
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
	    return true;
		}

	public  ArrayList<UserModel> user_listget() {
		//DBに登録してある一覧を検索して、List<String>に保存する
		int id=0;
		String user_name="";
        ArrayList<UserModel> userlist = new ArrayList<UserModel>();
        try {
	        //MySQLのドライバを指定
	    	Class.forName("com.mysql.cj.jdbc.Driver");
            // MySQLデータベースに接続 (DB名,ID,パスワードを指定)
            Connection connection = DriverManager.getConnection(URL, USERNAME,PASSWORD);
            System.out.println("DB接続OK");
            //DBに登録したデータから一覧の項目を取得する
			String sql="SELECT user_id,user_name FROM tbl_user";
            PreparedStatement pstmt=connection.prepareStatement(sql);
            ResultSet rs=pstmt.executeQuery();
            while(rs.next()) {
            	id=rs.getInt("user_id");
            	user_name=rs.getString("user_name");
            	//DBから取得したデータをリストに保存
        	    UserModel user_m=new UserModel(id,user_name);
        	    userlist.add(user_m);//※java.lang.NullPointerExceptionが発生
            }
            // ステートメントをクローズ
			rs.close();
            // 接続をクローズ
            connection.close();
	    }
        catch (Exception e) {
            e.printStackTrace();
        }
	   	return userlist;
	}


	//指定された1レコードを取得
	public UserModel ref(int key_id) {
		//DBを検索して、該当する1レコードをインスタンスに保存する
		UserModel user_m=new UserModel();
		int id=0;//
		String user_name="";
        try {
	        //MySQLのドライバを指定
	    	Class.forName("com.mysql.cj.jdbc.Driver");
            // MySQLデータベースに接続 (DB名,ID,パスワードを指定)
            Connection connection = DriverManager.getConnection(URL, USERNAME,PASSWORD);
            System.out.println("DB接続OK");
            //DBに登録したデータから一覧の項目を取得する
 			String sql="SELECT * FROM tbl_user WHERE user_id=?";
			PreparedStatement pstmt=connection.prepareStatement(sql);
			//key_idをintからStringに変換
			String key_ids=String.valueOf(key_id);
			pstmt.setString(1,key_ids);
			ResultSet rs=pstmt.executeQuery();
			rs.next();//これが必要
			id=rs.getInt("user_id");
			System.out.println("id"+id);
            user_name=rs.getString("user_name");
            user_m.setUser_id(id);
            user_m.setUser_name(user_name);
            // ステートメントをクローズ
			rs.close();
            // 接続をクローズ
            connection.close();
	    }
        catch (Exception e) {
            e.printStackTrace();
        }
        return user_m;
	}

	public boolean user_update(UserModel user_m) {
	    try {
	        //MySQLのドライバを指定
	    	Class.forName("com.mysql.cj.jdbc.Driver");
            // MySQLデータベースに接続 (DB名,ID,パスワードを指定)
	    	System.out.println("DB接続開始");
	    	Connection connection = DriverManager.getConnection(URL, USERNAME,PASSWORD);
	    	System.out.println("DB接続OK");
			String str1=user_m.getUser_name();
			int id=user_m.getUser_id();
            String sql="UPDATE tbl_user SET user_name=? WHERE user_id=?";
            PreparedStatement pstmt=connection.prepareStatement(sql);
            //key_idをintからStringに変換
			String key_ids=String.valueOf(id);
			pstmt.setString(1, str1);
			pstmt.setString(2, key_ids);
			pstmt.executeUpdate();
            // ステートメントをクローズ
            pstmt.close();
            // 接続をクローズ
            connection.close();
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
	    return true;
		}

		//指定された1レコードを削除
		public boolean user_del(int key_id) {
		    try {
		        // 先程インストールしたMySQLのドライバを指定
		    	Class.forName("com.mysql.cj.jdbc.Driver");
		        // MySQLデータベースに接続 (DB名,ID,パスワードを指定)
		        Connection connection = DriverManager.getConnection(URL, USERNAME,PASSWORD);
		        System.out.println("DB接続OK");
		        //DBに登録したデータから一覧の項目を取得する
				//String sql="DELETE FROM tbl_info_sum WHERE id=?";
				String sql="DELETE FROM tbl_user WHERE user_id=?";//削除フラグの追加
				PreparedStatement pstmt=connection.prepareStatement(sql);
				//key_idをintからStringに変換
				String key_ids=String.valueOf(key_id);
				pstmt.setString(1,key_ids);
		        int line=pstmt.executeUpdate();
		        System.out.println("id="+key_ids+"を"+line+"行削除しました");
		    }catch (Exception e) {
		        e.printStackTrace();
		        return false;
	        }
		    return true;
		}
}

(4)データベースとテーブル作成
データベース作成
・データベースの作成
CREATE DATABASE crud_sample;
・DB接続
USE crud_sample;

・テーブル作成CREATE TABLE tbl_user(user_id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,user_name VARCHAR(100));

5.実行

(1)XAMPPのMySQLサーバを起動する

(2)アプリケーションを選択して、実行ボタン▷を押す

(3)ブラウザからWebサーバに接続http://localhost:8080/Crud_sample/

「ユーザー登録」ボタン押下

名前:テストネームを入力し、「登録」ボタン押下

「ユーザー管理」画面で「ユーザー一覧」ボタン押下

ID:47の「変更」ボタン押下

ID:47の「削除」ボタン押下

The subject ends herewith.

Javaサーブレットの基本

Eclipseによる動的Webプロジェクトの作成と、サーブレットクラスの処理を実行する。

1.開発環境
 OS: Windows 10 Pro
 IDE:Eclipse IDE for Enterprise Java Developers Version:2020-12 (4.18.0)
 Java version:11.0.9、Tomcat v8.0Eclipse

2.プロジェクトの作成
(1)ファイル>新規>その他を選択し、「動的Webプロジェクト」を選択

(2)プロジェクトフォルダが作成される

2.サーブレットクラスの作成
(1)ファイル>新規>その他を選択し、「サーブレット」を選択

(2)サーブレットクラスファイルの編集

3.サーブレットクラスの実行
 アプリケーションを選択して、実行ボタン▷を押す

@WebServlet(“/User_cnt”)で指定したため、/(プロジェクト名)/(@WebServletアノテーションで指定したURLパターン)でアクセスできる。
http://localhost:8080/Crud_sample/User_cnt
http://<サーバ名>/<アプリケーション名>/

4.サーブレットクラスの実行の仕組み
アプリケーションサーバは、サーブレットクラスの@WebServletアノテーションを読み取り、URLパターンの設定を行う。

以上

Source Treeの導入

 Source Tree はGitツール(CUIキャラクタベースユーザインタフェース)のバージョン管理を GUI(画面操作)で扱えるツールです。

1.Source Treeのインストール
(1)「SourceTree」をダウンロードするhttps://www.atlassian.com/ja/software/sourcetree

(2)「SourceTree」をインストールする

以下の画面が表示されれば、インストールは終了

2.Source Treeを使ってGitリポジトリを操作

(1)GitHubのリポジトリのURLをクリップボードにコピーする(赤枠)

(2)リモートリポジトリからローカルリポジトリの作成

「Clone」を選択し、リモートリポジトリのURLと保存先のパスを設定して、「クローン」ボタンを押すと、ローカルリポジトリが作成される。

(3)ワーキングツリーでファイルを新規作成し、リモートリポジトリを更新
①ファイル新規作成

作業ツリーに新規作成したファイルが表示される

②インデックス(ステージングエリア)に追加

③インデックスにあるファイルをコミット
 変更理由などを入力して、「コミット」ボタンを押す

④リモートリポジトリを更新する
 「プッシュ」ボタンを押す

「プッシュ」ボタンを押す

リモートリポジトリにファイルが追加された

The subject ends herewith.

Gitの導入

1.Gitとは
 Gitはコミットしたファイルの保管庫(「リポジトリ」という)にあるファイルのバージョン管理をするためのツールで、キーボードで入力するコマンドによって操作するCUI(キャラクタベースユーザインタフェース)ツール。
 GitはLinuxを開発したLinus Benedict Torvaldsが、Linuxの開発でソースコードのバージョン管理を行うために作ったツール。
また、GitHubはGitリポジトリをホスティングをするWebサービスの一つ。
 他にGitリポジトリをホスティングをするソフトウェアとしてはGitLab Inc.が開発したGitLabがあり、オープンソース版と有償版のソフトウェアがあり、自前でGitホスティングサーバを用意できます。
 プログラムに限らず、ドキュメントのバージョン管理にも利用でき、リポジトリのフォルダ構成などはプロジェクト毎に決めます。また、リポジトリのブランチの分け方などは「git-flow」などのワークフローが参考になります。

2.Gitで使う用語
・リポジトリ
 ファイルの状態の記録を貯めておく場所のこと。自分のPC側のリポジトリをローカルリポジトリ、サーバ側のリポジトリをリモートリポジトリといいます。
・コミット
 ファイルの新規作成、修正などをあるタイミングで確定することをコミットといいます。
・ファイルのコミットまでに使う場所
 ワークツリー(作業ディレクトリともいう)、ステージングエリア(インデックスともいう)、Gitディレクトリの3つの場所があります。
  ワークツリー:Gitで管理するファイルの保存
  ステージングエリア:コミットするファイルの情報を保存
  Gitディレクトリ:コミットしたファイルの情報を保存
・プッシュ
 ローカル側のリポジトリのコミットをリモート側に反映させること
・クローン
 リモートリポジトリをローカル側にコピーする操作
・プル
 リモートリポジトリから最新の変更履歴をダウンロードして、自分のローカルリポジトリにその内容を取り込むこと。フェッチとマージの両方の操作。
・フェッチ
 リモートリポジトリからファイルの最新情報を取得する操作。
・ブランチ
 ファイルの編集履歴を分岐させて記録していく機能で、ブランチした元にマージできます。

3.GitHubを使ったファイルバージョン管理
 大まかな手順を以下に示します。
①GitHubなどにフォルダのひな形の入ったリモートリポジトリを作成します。
②利用者は、ローカルPC(Gitがインストールされていること)にcloneコマンドで、ローカルリポジトリを作成します。
③ファイルの新規作成、変更、削除、フォルダの新規作成、変更などを行います。
④確定させたいファイル、フォルダをaddコマンドでステージングエリアに移します。
⑤ステージングエリアに置いたファイル、フォルダをcommitコマンドでコミットします。
⑥pushコマンドで、リモートリポジトリに上げます。
⑦pullコマンドで他のメンバが編集したファイルを自分のローカルリポジトリに取り込みます。

4.Gitツールのインストール
 Windows10にGitのインストール
①Gitのサイトを開き、「Downloads」を選択
http://git-scm.com/

②OSを選択すると、ダウンロードが開始される

③ダウンロードしたファイルを実行

デフォルトの設定のまま、インストール

コマンドプロンプトを起動し、バージョンを確認する
> Git –version

5.Gitコマンドによるリモートリポジトリ更新までの操作

(1)スタートメニューから「GitBash」を開く

(2)ユーザ名とメールアドレスを設定する
 $ git config –global user.name (ユーザ名)
 $ git config –global user.email (メールアドレス)

(3)リモートリポジトリをローカルリポジトリに取得

①GitHubのリモートリポジトリ

②リモートリポジトリをローカルに取得
 予め、ローカルにリポジトリを置くフォルダを作成(ここでは”work”)し、cdコマンドでこのフォルダに移動し、cloneコマンドを実行。このときの接続先はGitHubのリポジトリからクリップボードにコピー(①の赤枠)
 $ git clone (GitHubの接続先)

.gitのフォルダ内容

(4)ワークツリーにフォルダ、ファイルを作成

(5)リモートリポジトリにアップ
①リポジトリの状態確認(git tatusコマンド)
 $ git status

②ステージングエリアに登録(git addコマンド)
 $ git add アプリの開発/
※ステージングエリアに登録するフォルダ、ファイルは、カレントディレクトリ配下(”git add .”)、サブディレクトリ(git add /アプリの開発/プログラム)、ファイル(git add /アプリの開発/ドキュメント/sampleファイル.txt)など、指定できる。

③ローカルリポジトリにコミット(git commitコマンド)
 $ git commit
エデッタ画面が開くので、「i」(insert)キーを押して編集モードにし、ESCキーのあと「:」、「wq」(書き込み)し、終了すると、コミットが完了。

ローカルリポジトリの状態を確認する
 $ git status

④リモートリポジトリにプッシュ(git pushコマンド)
 $ git push origin master
 git push(プッシュ先のリモートリポジトリの名前) (プッシュするブランチ名)

6.Gitコマンド
 Gitコマンドのレファレンス

 https://git-scm.com/docs/git#_git_commands

The subject ends herewith.

Windows10にVSCodeでc開発環境を構築する

目次

1.VSCodeのインストール
ダウンロードサイト
https://code.visualstudio.com/

Windowsx64 Stable(安定版)を使用

①「VSCodeUserSetup-x64-1.45.1.exe」を実行する

②インストール先の指定

③プログラムグループの指定

④追加タスクの選択

⑤インストール準備完了

⑥セットアップ完了

⑦VSCodeの起動

2.VSCodeに拡張機能追加
 拡張機能の追加は、「拡張機能」ボタンを押して、検索文字で検索し、「インストール」を押すことで機能追加される。

使用した拡張機能は以下の通り。
(1)Japanese Language Pack for Visual Studio Code
メニューを日本語化する機能

(2)Code Runner
再生ボタンなどでコンパイル&実行を行う機能

(3)C/C++
VsCodeにC言語の予約語や関数名などの予測候補文字列を表示する機能

(4)ftp-simple
リモートサーバなどにftpでアップロードするときに使用。

3.MinGWのインストール
cコンパイラとして、MinGWをインストールする
ダウンロードサイト
https://osdn.net/projects/mingw/releases/

①「mingw-get-setup.exe」を実行

②インストールするパッケージを選択
「mingw32-base-bin」にチェックを入れ、「mark for installation」を選択

③「gcc-g++-bin」を選択し、Instalationメニューの「Apply Changes」を選択

④「Apply」を選択

⑤インストール完了
「mingw32-base-bin」と「mingw32-gcc-g++-bin」の2つが緑になる

⑥環境変数にコマンドパスを設定する
システム詳細設定>ユーザー環境変数>Pathのところで「新規」を選択し、
”C:¥MinGW¥bin”を追加する

⑦インストール確認
PowerShellを起動して、”gcc –help”を実行し、helpメッセージが出れば完了

4.ソースコードの作成
(1)ワークスペースの作成
 予めワークスペースのフォルダを作成しておき、「フォルダを開く」でそのフォルダを選択すると、VSCodeのエクスプローラーに表示される。

(2)ソースコードファイルの作成
 「新しいファイル」を選択して、ファイル名を入力。

ソースコードを編集する

(3)コンパイルとexeファイルの実行
ターミナルの「新しいターミナル」でターミナルを表示する

コンパイラコマンド”gcc -o test test.c”を実行

”test.exe”を実行

5.ビルドとデバック
(1)ビルド
ソースファイルを選択して、「デバックの開始」を押すと、環境の選択が表示されるので、「C++(GDB・LLDB)」を選択し、「gcc.exe-アクティブファイルのビルドとデバック」を選択すると、ビルドが始まり、task.json、launch.jsonの2つのファイルが作成される。

tasks.json:コンパイルやデバッグなどのタスクの設定を定義するファイル
launch.json:VSCodeのデバッグ機能を使うための設定を定義するファイル

(2)デバック
「デバックの開始」を押すと、ビルドと実行する。ブレークポイントで止まる。

デバックを開始すると、変数、レジスタを表示

下記のボタンでプログラムを進める

Visual Studioのステップ実行には「ステップイン」「ステップオーバー」そして「ステップアウト」の3種類がある。
()内は、ショートカットキー
・ステップイン(F11):最もステップ単位が小さいデバッグ方法で1行単位で実行 される。このステップ実行をすると、関数の内部にも入るこ とができる。
・ステップオーバー(F10):1行単位で実行されるが、関数があった場合その関数 を実行して次の行に移行する。関数の内部に入らない。
・ステップアウト(Shift+F11):関数の外(呼び出し元)に出るまでプログラムを 進めるステップ実行方法。

the end

PythonでNumPyとmatplotlibを使って2次元、3次元グラフを描く

1.環境
・windows10
・Anaconda バージョン conda 4.8.3
・Jupyter notebooks

2.グラフの描画
2.1 手順
①%matplotlib inline
Jupyter Notebookでアウトプット行に表示するためのコード
②ライブラリのインポート
import matplotlib.pyplot as plt
import numpy as np
③描画領域の作成
”fig”の名前の領域を作成
fig = plt.figure() ※1
④座標軸の作成
上記で作成した領域に座標を作成
・複数の座標軸を一度に作成 .subplots() ※2
axes = fig.subplots(2, 3)(例:2行×3列)
axes[0,0].plot([1,3,5,2,4,8]) (例:0行、0列の座標に表示)
・一つづつ座標軸を作成 .add_subplot()  ※2
 ax1=fig.add_subplot(2, 3,1)(例:2行×3行の1番目を作成)
 ax1.plot([1,2,3]) 座標に表示
⑤描画 .plot()
2.2 主なパラメータ
※1 figure()のパラメータ
fig = plt.figure(figsize=(10,7), dpi=100,facecolor=’w’,tight_layout=True)
figsize :領域のサイズ。横縦をfigsize=(width, height)で指定
width, heightはインチ単位で指定。デフォルト6.4in×4.8in
dpi :1インチあたりのドット数
facecolor :図の背景色
tight_layout :Trueでオブジェクトの配置が自動調整
※2 subplots()、.add_subplot()のパラメータ
※3 plot()のパラメータ
線種指定
plot(…,ls=記号,…)で指定できる線種
種類 記号
実線 ‘-’
破線 ‘–’(-が2つ)
一点鎖線 ’-.’
点線 ’:’
plt.plot()を実行すると自動でFigureオブジェクトも作成されるので、plt.figure()は割愛

3.2次元グラフの作成
(1)1つの座標に2つのグラフを表示  [sample_3-1]

plt.plot()を実行すると自動でfigureオブジェクトも作成されるので、plt.figure()は省略

#3.2 2次元グラフ
#(1)1つの座標に2つのグラフを表示
#[sample_3-1]
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace( -5, 5, 10) #数列を作成、下記と同じ
#x=np.array([ -5,-4,-3,-2,-1,0,1,2,3,4,5])
y1 = np.exp(-x) #y=e^-x
y2 = np.exp(x) #y=e^x

plt.plot(x, y1, label='test')   #2次元座標に描画
plt.plot(x, y2, label='test2')   #2次元座標に描画
plt.legend()  #凡例の表示
plt.grid() #グリッド表示
plt.xlabel('x')  #x軸ラベル表示
plt.ylabel('y')  #y軸ラベル表示
plt.title('test graph')  #タイトル表示

(2)複数の座標にグラフを表示  [sample_3-2]

#3.2(2)複数の座標にグラフを表示
#[sample_3-2]
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
#描画領域の作成
fig = plt.figure()
x = np.linspace( -5, 5, 10) #数列を作成、下記と同じ

#座標の作成(複数)
ax1=fig.add_subplot(2, 2,1)#2*2の1番目
ax2=fig.add_subplot(2, 2,2)#2*2の2番目
ax3=fig.add_subplot(2, 2,3)#2*2の3番目
plt.subplots_adjust(wspace=0.4, hspace=0.6)#座標間にスペースを設ける

y1 = np.exp(-x) #y=e^-x
y2 = np.exp(x) #y=e^x
y3 = x**2 #y=x^2

#描画
ax1.plot(x, y1, label='test1')   #2次元座標に描画
ax1.legend()  #凡例の表示
ax1.grid() #グリッド表示
ax1.set_xlabel('x')  #x軸ラベル表示
ax1.set_ylabel('y')  #y軸ラベル表示
ax1.set_title('test1 graph')  #タイトル表示

ax2.plot(x, y2, label='test2')   #2次元座標に描画

ax2.legend()  #凡例の表示
ax2.grid() #グリッド表示
ax2.set_xlabel('x')  #x軸ラベル表示
ax2.set_ylabel('y')  #y軸ラベル表示
ax2.set_title('test3 graph')  #タイトル表示

ax3.plot(x, y3, label='test3')   #2次元座標に描画
ax3.legend()  #凡例の表示
ax3.grid() #グリッド表示
ax3.set_xlabel('x')  #x軸ラベル表示
ax3.set_ylabel('y')  #y軸ラベル表示
ax3.set_title('test3 graph')  #タイトル表示

4.3次元グラフの作成
(1)1つの座標  [sample_4-1]

#4.3次元グラフの作成
#4.(1)1つの座標
#[sample_4-1]
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-3.0, 3.0, 0.1) #arange()は間隔(公差)を指定
y = np.arange(-3.0, 3.0, 0.1) #linspace()は要素数を指定

#格子点の作成
X, Y = np.meshgrid(x, y) #x座標とy座標の要素の入った配列を指定すると、各軸のグリッドの要素を返す

Z = X**2+Y**2 #演算X^2+Y^2の結果

#描画領域の作成
fig = plt.figure()
ax = Axes3D(fig)

ax.set_xlabel("x") #X軸ラベル
ax.set_ylabel("y") #Y軸ラベル
ax.set_zlabel("f(x, y)") #Z軸ラベル

ax.plot_wireframe(X, Y, Z)  #3次元の曲面
#ax.plot_surface(X, Y, Z)  #3次元の曲面塗りつぶし
#ax.scatter(X, Y, Z)  #点で表示

(2)複数座標  [sample_4-2]

#4.(2)複数グラフ作成
#[sample_4-2]
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

#描画領域の作成
fig = plt.figure(figsize=(20,15),facecolor='g')

#1つ目の格子点生成
x1 = np.arange(-3.0, 3.0, 0.1)
y1 = np.arange(-3.0, 3.0, 0.1)
X1, Y1 = np.meshgrid(x1, y1)
Z1 = X1**2+Y1**2

#2つ目の格子点生成
x2 = np.arange(-3.0, 3.0, 0.1)
y2 = np.arange(-3.0, 3.0, 0.1)
X2, Y2 = np.meshgrid(x2, y2)
Z2 = X2**2+Y2**2

#1つ目の座標生成と描画
ax1 = fig.add_subplot(2, 2,1, projection='3d') 
ax1.set_xlabel("x1")
ax1.set_ylabel("y1")
ax1.set_zlabel("f(x1, y1)")
ax1.plot_wireframe(X1, Y1, Z1)

#2つ目の座標生成と描画
ax2 = fig.add_subplot(2, 2,2, projection='3d') 
ax2.set_xlabel("x")
ax2.set_ylabel("y")
ax2.set_zlabel("f(x, y)")
ax2.plot_wireframe(X2, Y2, Z2)

(3)1つの座標に2つのグラフ [sample_4-3]

#4.(3)1つの座標に2つのグラフ
#[sample_4-3]
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

#範囲と間隔の設定
x = np.arange(-5, 5, 1)
y = np.arange(-5, 5, 1)

#格子点作成
X, Y = np.meshgrid(x, y)
print(X)
print(Y)

#計算
Z1 =X**2+Y**2
Z2 =X**2-Y**2

#描画領域の作成
fig = plt.figure()
ax = Axes3D(fig)

#描画
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("f(x, y)")
ax.plot_surface(X, Y, Z1, rstride=1, cstride=1, cmap='summer', linewidth=0.3)
ax.plot_surface(X, Y, Z2, rstride=1, cstride=1, cmap='spring', linewidth=0.3)

5.参考
・Python公式サイト
https://www.python.org/
・日本のPythonコミュニティ
https://www.python.jp/index.html
・Windows版Anacondaのインストール
https://www.python.jp/install/anaconda/windows/install.html
・NumPy Pythonを使用した科学計算の基本パッケージ
https://numpy.org/
・matplotlib
プログラミング言語Pythonおよびその科学計算用ライブラリNumPyのためのグラフ描画ライブラリ
https://matplotlib.org/
・mplot3d( 3次元プロット) matplotlibの機能を拡張するためのツールキット
https://matplotlib.org/stable/tutorials/toolkits/mplot3d.html

The subject ends herewith.

Google Mapの表示

web画面内にGoogle Mapを表示する方法

googlemap_sample3.html

<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Google Maps APIテスト</title>
<style type="text/css">
#container {
	width: 700px;
	margin: 0 auto;
}
#sample {
	width: 700px;
	height: 400px;
}
</style>
</head>
<body>

<div id="container">
	<div id="sample"></div>

</div>

<script src="./sample3.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
</body>
</html>

sample3.js

var map;
var marker = [];
var infoWindow = [];
var markerData = [ // マーカーを立てる場所名・緯度・経度
	{
		name: '神保町駅',
		lat: 35.695932,
		lng: 139.75762699999996,
		icon: 'sample3.png' // マーカーメージ変更
	}, {
		name: '小川町駅',
		lat: 35.6951212,
		lng: 139.76610649999998
	}, {
		name: '淡路町駅',
		lat: 35.69496,
		lng: 139.76746000000003
	}, {
		name: '御茶ノ水駅',
		lat: 35.6993529,
		lng: 139.76526949999993
	}, {
		name: '新御茶ノ水駅',
		lat: 35.696932,
		lng: 139.76543200000003
	}
];

function initMap() {
	// 地図の作成
	var mapLatLng = new google.maps.LatLng({lat: markerData[0]['lat'], lng: markerData[0]['lng']}); // 緯度経度のデータ作成
	map = new google.maps.Map(document.getElementById('sample'), { // #sampleに地図を埋め込む
		center: mapLatLng, // 地図の中心を指定
		zoom: 15 // 地図のズームを指定
	});

	// マーカー毎の処理
	for (var i = 0; i < markerData.length; i++) {
		markerLatLng = new google.maps.LatLng({lat: markerData[i]['lat'], lng: markerData[i]['lng']}); // 緯度経度のデータ作成
		marker[i] = new google.maps.Marker({ // マーカーの追加
			position: markerLatLng, // マーカーを立てる位置を指定
			map: map // マーカーを立てる地図を指定
		});

		infoWindow[i] = new google.maps.InfoWindow({ // 吹き出しの追加
			content: '<div class="sample">' + markerData[i]['name'] + '</div>' // 吹き出しに表示する内容
		});

		markerEvent(i); // マーカーにクリックイベントを追加
	}

	marker[0].setOptions({// マーカーのオプション設定
		icon: {
			url: markerData[0]['icon']// マーカーの画像を変更
		}
	});
}

// マーカーにクリックイベントを追加
function markerEvent(i) {
	marker[i].addListener('click', function() { // マーカーをクリックしたとき
		infoWindow[i].open(map, marker[i]); // 吹き出しの表示
	});
}

プログラミングを始めて2年間の振り返り

プログラミングを始めたころを振り返る

 私がコンピュータに初めて触れたころは職場にあったコモドールPET、マイブレーン3000、PC9801などのPCは計算の自動化が主な目的でした。   
 当時はPCも高価で、さらにアプリケーションを開発するためのソフトウェアも高価でした。
 それから30年近く経った現在では、コンピュータハードウェア(CPU、メモリ、ネットワーク)の高性能低価格化やOSS(オープンソースソフトウェア)の普及やインターネットを通じてITに関する最新情報を簡単に得られるようになり、無料から始めて、サービスのアイデアをインターネット上で形にできる時代になりました。
 このようにソフト開発の環境が整ってきたことで始めたプログラミングですが経過を振り返ります。
 プログラミングする人(プログラマー)には、
・大学などでコンピュータサイエンス(情報工学、情報科学、計算機科学、計算機工学などの総称)を学んだ後、又は学びながらプログラミングを習得
・学問から入るのではなく、すでにあるプログラムをまねて動かしながら知識を積み上げる
の2つのパターンがあると思います。
 英会話に例えると、前者は文法から積み上げて会話を習得した人、後者は英語を使いながら必要に応じて文法を調べ、会話数を増やした人に例えられるかと思います。
 私の場合は、前者2:後者8くらいの割合。知識としては教養程度のコンピュータに関わる理論(代数学少々、コンピュータの仕組みなど)を過去に学んだ記憶があり、プログラムを作ることを目標に、職業訓練、書籍を中心に学習。
 プログラミングを始めたときはプログラミングに対する認識は、フローチャートで描かれる処理を演算子、データ型、制御文(繰り返しのfor文、条件分岐のif文、switch文)、ライブラリ(ファイル入出力、メモリ操作など)を使ってソースコードを作成し、コンパイルして、実行する程度の知識。
 プログラミングを始めて間もなく、プログラミングするためには、プログラム言語を使ってソースコードの作成するだけでなく、ビルドツール(ソースコードなどを元に実行可能ファイルを生成まで自動化)、模擬環境での実行までが行える統合開発環境、ソースコードやプロジェクトファイルの世代管理するためのツール(サブバージョン、Git)などがあることを知る。また、プログラミング言語についてはオブジェクト指向のメリットを実感できるようになるまで試行錯誤しながら習得。
 このオブジェクト指向は、C++からJava、C#へと受け継がれ、新しいプログラム言語のほとんどで取り入れられている。言語によって、多少の文法の違いはあるものの、1つの言語で理解すると他の言語でも応用が利く。
 また、Webシステムの開発ではフロント側はHTML、CSS、Javascript、フレームワークのjQuery、サーバ側ではPHP、フレームワークのLarabel、Java、フレームワークのSpringBootなど、組み込み系プログラムの開発では、C、C++、Android(javaのフレームワーク)、スマホの専用アプリの開発ではAndroid、iOSのswiftなど、用途に応じてプログラム言語が異なることが多い。

 プログラムを作成する過程で調査した内容について、メモの内容をベースに順次、本サイトに載せる予定です。