第 1 回 復習

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

1-1. この講義について

この講義では C 言語を使って、データ構造とアルゴリズムについ て学びます。

C++ は複雑ですので、この講義には向きません。 C 言語に特化して講義しま す。

1-2. Cの処理系

今年度は各自のパソコンでC言語のコンパイラをインストールして、学習し ます。 授業を受けるにあたって必要なのは、Cコンパイラとプログラムを編集する エディタになります。 なお、C++言語はC言語と完全に互換性はありませんが、C++コンパイラにC言語モードが内蔵されていて、Cコンパイラとして使うことができるものもあります。

Cコンパイラには様々な種類がありますが、本講義で作る プログラムに対しては、せいぜい printf を使う程度という意味で、どんな C コンパイラでも講義資料のプログラムは動かせ、レポートも作成できます。

Linux の様々なディストロでは gcc や clang などをすぐにインストールで きるはずです。

MacOSX では Xcode をインストールすると gcc がインストールされます。 また、 Xcode で C 言語のプログラムを編集、実行することもできます。

工学部第二部情報通信工学科ではパソコンを指定していないので、推奨環境 はありませんが、 一応、市場占有率などを考慮すると Windows 10や11 を使用している学生が多い のではないかと思います。 従って、以後、講義中では、Windows 10 (Windows 11) を使用することを前 提とし、他の環境を使用している人については質問などを通じて対応するよ うにしようと 思います。

Windows10 を使用している場合、最初の選択肢としては、Microsoft Visual Studio で C++ の環境をインストールすることです。 実際にインストールしてみましたが、2022 のコミュニティというバージョンで は、C++デスクトップ開発環境を選択すると 8.47GB のダウンロードと、再起動が 必要です。

本講義での標準環境として、インストールが楽で、ダウンロード容量も少な くて、多機能なものとして、msys2 を採用したいと思います。 なお、似たような環境に Cygwin もあります。 とにかく、Cコンパイラが使える環境があれば、新しく準備する必要はありません。

1-3. MSYS2のインストール

MSYS2 では Windows 上で UNIX のコマンドライン風の環境を実現します。 但し、MSYS2ではWindowsのコマンドも使えます。

  1. ホームページ https://www.msys2.org/ より、msys2-x86_64-20220319.exe をダウンロードし、実行します。
  2. 指示に従っていると c:\msys64 または c:\msys32 のフォルダにインストー ルされます。 そして、msys2 を実行するか尋ねられますので、実行します。
  3. msys2 を実行すると背景が黒く、キーボードでコマンドを入れることのでき る画面が表示されます。 ここでコマンドを表す文字列をキーボードから入力して、様々な操作を行い ます。 Windows のコマンドプロンプトやPowerShellと同じようなものです。
  4. 初回にpacman -Syuを入れると、様々な追加パッケージを導入 後、画面を閉じて再起動するようなメッセージが出ます。
  5. msys2 のウィンドウを閉じ、 Windows のメニューより 「MSYS2 64bit」→「MSYS2 MSYS」で再び起動しま す。
  6. pacman -Su を入れてさらに追加パッケージを導入して、MSYS2 のインストールが完了し ます。
  7. さらにpacman -S gccでCコンパイラgccをインストールします。 以上で、Windows用のC言語の環境構築は終了です。

なおこの pacman はパッケージマネージャの意味で、必要なパッ ケージをサーバーからダウンロード、インストールするものです。 pacman --helpで説明が表示されます。 pacman -S は sync の意味で、指定したパッケージの最新のも のをインストールします。 -Sy は手元のサーバー情報を最新のものにする意味で、 -Su は手元のサーバー情報を元に、古いパッケージを全て新し いものにする意味です。

1-4. エディタの準備

道具を導入する場合にはいくつかの考え方があります。 以下に典型的な考え方を示しますが、どれが優れた考え方かは個人の考え方 とケースバイケースによるのではないでしょうか?

  1. 新しいものは避け、既存のものを工夫して使う
  2. 身近な多くの人が使っているものを導入し、困った時は頼れるようにする
  3. 現在最も優れたものを導入する
  4. プロが使っているものを苦労しながら覚える

プログラムを編集するエディタとして、上記の考え方に対応させて紹介しま す。 どれを導入しても講義を受けることはできますが、利便性などは大きく異な ります。

  1. Windows 既存のエディタ notepad はプログラムの編集にも使えます。 msys2 のコマンドラインで notepad と打ち込むことで起動で きます。 C言語の編集モードはありません。
  2. 日本人のユーザが大勢いるエディタとして、テラパッド https://tera-net.com/ があります。 日本語のマニュアルがあり、C言語の編集モードがあります。
  3. Visual Studio などは最も優れたものの一つですが、これとは別に Visual Studio Code というプログラムエディタがあります。 自動整形など機能が高いです。 MacOSX でも使用できますが、MacOSX では Xcode を使用するのも手だと 思います。 この他、Eclipseも使用できます。
  4. プロが使用するツールには Visual Studio も Xcode も含まれます。 この他、UNIX で定番のエディタとして Vim や Emacs があります。 著者は30年以上に渡って Emacs を主に使っています。

1-5. プログラムの実行法

プログラムはソースコードともソースファイルとも呼ばれ、文字が改行で 区切られたテキストファイルで表現されます。 さらに、C言語のソースファイルには、 .c という拡張子がファ イル名につけられます。

ソースファイルはそのままで実行できません。 実行可能なファイル形式は OS によって異なります。 基本的には、OSが読み込むと、コンピュータの機械語として実行できるよう なファイルで、これを実行ファイルなどとも呼びます。 特に Windows では .exe という拡張子がファイル名に付いています。

ソースファイルを実行ファイルに変換するのを翻訳と呼んだり、 コンパイルと呼んだりします。 コンパイルをする実行ファイルをコンパイラと呼びます。

GNUプロジェクト(http://www.gnu.org/)では自由なソフトウェアとして、C コンパイラ GCC を提供しています。 gcc ソースファイル名を入力すると、a.out(Windows では a.exe)という名前で翻訳結果が実行ファイルとして出力されます。

MSYS2の場合

  1. MSYS2 MSYS を立ち上げます。 「スタート」→「MSYS2 64bit」→「MSYS2 MSYS」で起動します。 画面に背景が黒い画面が出ます。
  2. この画面にコマンドを打つと、実行されます。 特定のフォルダ(ディレクトリ)が カレントディレクトリと呼ばれ、関連付けられています。
  3. 少し、コマンドの練習をしてみましょう。
    1. カレントディレクトリを表示するコマンド は pwd
    2. カレントディレクトリに含まれるファイル名を表示するのは ls。 詳細を表示するには ls -l。 この他様々なオプションがあるが、大抵「空白」、「マイナス」、 「英字」 の組み合わせで指定する。
    3. コマンドの使い方を知りたい場合は、コマンド名の後に --helpオプションを付ける。
    4. 複数のファイルなどをまとめて入れるディレクトリ(フォルダ)を 作るには mkdir ディレクトリ名とする。 消すにはrmdir ディレクトリ名とする。 (ls -lで確認)
    5. カレントディレクトリを変更するにはcd ディレクトリ 名とする。 (pwdで確認)
  4. さて、授業用のディレクトリを作り、さらに本日のディレクトリを作る
    1. mkdir ad
    2. cd ad
    3. mkdir 20220414
    4. cd 20220414
    5. pwd コマンドで /home/ログイン名/ad/20220414 が表示されることを確認する
  5. カレントディレクトリにソースファイルを作成する。 hello.c という名前のソースファイルを作成するには 次のようにする。
    1. メモ帳を使うなら notepad hello.c & を打ち込むと、メ モ帳が開き、編集可能になる。 (& はマルチタスクを意味する)
    2. 他のエディタを使うのなら、C:\msys64\home\ログイン名\ad\20220414\hello.c を 編集する
  6. エディタ画面にプログラムを書き込みます。
  7. プログラムの入力が終ったら、save します。
  8. gcc hello.cを実行すると、 a.exe が作られます。
  9. ./a.exeを打ち込むと Hello World が表示されます。

演習1-1

次のプログラムを実行させなさい。

#include <stdio.h>
main(){
  printf("Hello World\n");
}

(付録)Visual Studio の場合

Visual Studio Community 2022 では次のようにします。

  1. まず Visual Studio を立ち上げます。 「スタート」→「Visual Studio 2022」で起動 します。
  2. 「新しいプロジェクトの作成」で、「空のプロジェクト」を選びます。
  3. プロジェクト名は適当につけて「作成」を押して下さい。
  4. ソリューションエクスプローラ中の「ソースファイル」を右クリックして、 出てきたメニューに対して、「追加」→「新しい項目の追加」を選びます。
  5. 出てきた「新しい項目の追加」ダイアログで、テンプレートで「C++ ファ イル」を指定し、ファイル名に「hello.c」など作成したい C 言語のファイル 名をそのまま入れ、「追加」ボタンを押します。
  6. 画面にそのファイルの入力欄が出てきたらプログラムを書き込みます。
  7. プログラムの入力が終ったら、「ビルド」→「ソリューションのビルド」 でコンパイルし実行ファイルを作ります。
  8. 「デバッグ」→「デバッグなしで開始」でプログラムを実行します。

なお、「プロジェクト」→「○○(プロジェクト名)のプロパティ」でプロ パティページを開き、次のように設定すべきですが、しなくても通常問題あり ません。

1-6. C 言語の基礎

プログラムの全体の構造

C 言語のプログラムは最後が「.c」で終るテキストファイルに書きます。

構造1

#include <stdio.h>
main(){
  ここに文を書く
}

構造2

#include <stdio.h>
#include <math.h>
main(){
  ここに文を書く
}

構造 2 は平方根 sqrt() や三角関数 sin() など数学的な関数を使用する時だ け使い、通常は構造 1 を使います。

文はセミコロン「;」で区切ります。

またプログラムの任意の場所に /* で始まり */ で終るコメントを書くことが できます。

プログラムの組み立て

プログラムは宣言をするところと、手順を記述するところにわけることができ ます。

構造3

#include <stdio.h>
main(){
  宣言

  手順
}

宣言

宣言とは変数の登録をすることです。 変数には型と名前があります。 型は文字型 char、整数型 int、単精度浮動小数点型 float、倍精度浮動小数 点型 double があります。 名前は英字で始まる任意の英数字の列を使用できます。


int i,j;
float kotae1,kotae2;
char a,b,c;

また、通常の変数の他に配列変数を扱うこともできます。 これは、数学で扱う数列 a0, a1 のように、添字の番 号を指定して a[0], a[1] のように値を呼び出すことができます。 宣言する時は使用する数を与える必要があります。 但し、添字は 0 から始まりますので、5 個の配列を宣言した時、使用できる 添字は 0,1,2,3,4 になります。 手続き中の配列変数の添字には整数型の変数を使用することもできます。


int x[3]; /* 使用できる変数名は x[0], x[1], x[2] */
char word[2]; /* 使用できる変数名は word[0], word[1] */

宣言では変数の最初の値(初期値)を与えることができます。 文字型とは文字一文字のことで、文字型の定数を表すにはシングルクォーテー ションマーク「' '」で括ります。 なお、改行記号は '\n' で表します。 配列変数では 0 番目の値から順に { } の中にカンマで区切って与えることが できます。{ } で値を与える場合、使用する配列の数を与えなくても良いです。


int i=0;
char a='x', b='\n';
float y[2]={1.3 , 3.5}; /* y[0]=1.3, y[1]=3.5 */
int k[]={3, 2, 1}; /* k[0]=3, k[1]=2, k[2]=1 */

文字型の配列変数は文字列を使用するのに使うことができます。 その場合、文字列の最後に必ず特別な文字 '\0' を入れる必要があります。 また、文字型の配列変数の初期化には上記のような { } を使用する代わりに、 文字列を " " で括る方法もあります。この場合最後に自動的に '\0' が割り 当てられます。


char x[]="abc"; /* x[0]='a', x[1]='b', x[2]='c', x[3]='\0' */

手順

本講義では手順として次のものを取り上げます。

  1. 代入文
  2. printf
  3. if
  4. while

代入文

代入文は「変数名 = 式」という形式で書き、式の値が変数に入ります。 ですから、「 i = i+1 」という代入文では i+1 の値が i に入りますから、 i の値が 1 増えます。 式には通常の四則演算の他、数学関数も使用できます。 但し、演算の優先順位を与えるカッコは丸カッコ ( ) しか使用できません。 また、変数を含む式は変数の型が考慮されます。整数型の変数 a,b にそれぞ れ 7,2 が入っていた時、 a/b の結果は整数型に直され、3 になります。 なお、 a を b で割った余りを求めるには a % b と書きます。


a = ((1+2)*3+4)*5;
x[2] = sqrt(y[1]);

C 言語ではあらゆるものが値を持ちます。代入文自体も代入された値を値とし て持つので、次のような記法が可能になります。


i=j=0;

C 言語独特の記法として代入演算子やインクリメント、デクリメントがありま す。代入演算子「変数 += 式」は式の値だけ左辺の変数を増やすという意味に なります。また、インクリメント、デクリメントは i++, --i などで、それぞ れ i が 1 ずつ増減します。但し、++, -- が先頭に来る場合の式の値は増え た後の値になりますが、後に来る場合は式の値は増える前の値になります。


s+=a[i];              /* s=s+a[i]; と同じ */
--j;                  /* j=j-1; と同じ */
z[i++]=y[j++];        /* z[i]=y[j];i=i+1;j=j+1;z[i-1]; と同じ */

printf

標準出力に文字を出力するのが printf です。指定した文字を出力するだけで なく、変数の内容も表示できます。 printf の最初の引数は文字列で、基本的にはその内容が表示されます。


printf("Hello World\n");

文字列の中に 「%+文字」 が含まれると、その位置に変数の値が表示されます。 文字型変数には %c, 整数型変数には %d, 浮動小数点型には(float も double も) %f を使用します。


char x='a';
int y=5;
float z=6.2;
printf("変数 x の値は %c",x);
printf("変数 y の値は %d, 変数 z の値は %f",y,z);

文字型の配列変数の内容を全て表示するには %s を使用します。 但し、配列の最後には '\0' が割り当てられている必要があります。


char x[]="abc"; /* x[0]='a', x[1]='b', x[2]='c', x[3]='\0' */
printf("配列変数 x には文字列 %s が入っている",x);

if

if 文には次の二つの構文があります。


if(条件){文1;}
if(条件){文2;}else{文3;}

始めの構文は条件が成立する時(0 でない時)だけ文1を実行し、成立しなかっ た時(0 だった時)はなにもしません。 二番目の構文は条件が成立する時(0 でない時)は文2を実行し、成立しなかっ た時(0 だった時)は文3を実行します。


if(0){y=1;}              /* 何もしない */
if(1){y=1;}              /* y=1; と同じ */
if(x){y=1;}else{y=2;}    /* x が 0 でない時 y=1; x が 0 の時 y=2; */

条件式

二つの値を比較をする条件式には次の書き方があります。

a == b
a と b は等しい
a != b
a と b は等しくない
a < b
a は b より小さい
a > b
a は b より大きい
a <= b
a は b 以下
a >= b
a は b 以上

これらの値は条件が成立すれば 1、成立しなければ 0 になります。


if(x>max){max=x;}

if(b==0){printf("全ての値\n");}
else{printf("解なし\n");}

二つの条件式を一つにまとめるため次の書き方があります。

(A) && (B)
A と B の両方が成り立つ(両方が 0 でない)
(A)||(B)
A か B のどちらかが成り立つ(どちらかが 0 でない)
!(A)
A が成り立たない(A が 0 である)

if((a==0)&&(b!=0)){printf("解なし");}
if((a!=0)||(b!=0)){x=-b/a;}

while

while 文の構文は if と良く似ています。


while(条件){文;}

「条件を調べて、成立すれば文を実行する」というのを繰り返します。 適切な回数だけ繰り返させるためには何らかのアルゴリズムが必要になります。

なお、for 文は while 文を読みやすくするために導入された別の書き方です。 次の for と while は同じ意味になります。


for(A;B;C){
  D;
}


A;
while(B){
  D;
  C;
}

for(i=0;i<3;i++){
  printf("あ");
}

i=0;
while(i<3){
  printf("あ");
  i++;;
}

#define

#define を使用すると、定数を使用することができます(実際はマクロの定義)。 次のように使用します。


#include <stdio.h>
#define N 3
main(){
  int x[N]={7, 3, 4};
  int i;

  for(i=0;i<N;++i){
    printf("%d\n",x[i]);
  }
}

1-7. プログラム例

  1. 
    #include <stdio.h>
    main(){
      printf("Hello World!\n");
    }
    
  2. 
    #include <stdio.h>
    main(){
      int a=1;
      float b=3.14;
      char c='a';
      char d[]="bcdef";
      printf("%d %f %c %s\n",a,b,c,d);
    }
    
  3. 
    #include <stdio.h>
    #include <math.h>
    main(){
      float a=2,b=3,c=1;
      float d,x1,x2;
      printf("%f x^2 + %f x + %f = 0 の解は",a,b,c);
      d=b*b-4*a*c;
      if(d>0){
        x1=(-b+sqrt(d))/2/a;
        x2=(-b-sqrt(d))/2/a;
        printf("%f , %f \n",x1,x2);
      }else if(d==0){
        x1=-b/2/a;
        printf("%f\n",x1);
      }else{
        x1=-b/2/a;
        x2=sqrt(-d)/2/a;
        printf("%f±%fi\n",x1,x2);
      }
    }
    
  4. 
    #include <stdio.h>
    #define N 10
    main(){
      int i,j;
      for(i=0;i<N;i++){
        for(j=0;j<N;j++){
          printf("〇");
        }
        printf("\n");
      }
    }
    

演習1-2

上のプログラム例 4 を改造して次を表示するプログラムを作りなさい。

  1. 〇〇〇〇〇
    〇〇〇〇
    〇〇〇
    〇〇
    〇
    
  2.    〇
      〇〇〇
     〇〇〇〇〇
    〇〇〇〇〇〇〇
    
  3. 〇〇〇〇〇
    〇   〇
    〇   〇
    〇   〇
    〇〇〇〇〇
    

坂本直志 <[email protected]>
東京電機大学工学部情報通信工学科