まとめと期末テスト
授業アンケート
期末テスト実施要項
1. 試験日程・会場
実施日時:最終日(第14回) 2025年6月2日(月)13:00-14:00
試験会場:理工学部4号館西棟1階106室
試験時間:60分間
2. 持ち込み許可物品
以下の物品のみ持ち込み可能です: - 学生証(身分証明のため必須) - 筆記用具(鉛筆、ボールペン、消しゴム等) - 教科書(「新・明解C言語 入門編」 柴田望洋 著(SBクリエイティブ))
注意:上記以外の物品(電子機器、ノート、プリント類等)の持ち込みは禁止
3. 単位認定の条件
単位取得には以下の両方の条件を満たす必要があります:
- すべての演習課題(必修のみ)チェックに合格
-
授業期間中に実施された演習課題(必修のみ)チェック全てをクリア
-
期末テストに合格
- 期末テストで合格点以上を取得
4. 試験構成と配点
第一部分:選択問題 - 問題数:24問 - 配点:各問2点 - 小計:48点
第二部分:空欄補充問題 - 空欄数:8空欄 - 配点:各空欄3点 - 小計:24点
第三部分:プログラミング問題 - 問題数:2問 - 小計:28点
総合計:100点満点
期末試験の注意事項
- 試験時間は60分間です。開始の合図があるまで問題用紙を開かないでください。
- 解答はすべて解答用紙に記入してください。問題用紙には一切記入しないでください。
- 問題用紙と解答用紙には、学籍番号、氏名を必ず記入してください。
- 試験中は携帯電話や他の電子機器の使用を禁止します。すべての機器の電源を切り、カバンにしまってください。
- 試験中の私語や物の貸し借りは禁止です。不正行為とみなされる場合があります。
- 試験開始後30分は退室できません。30分以降は教員の許可を得て、解答用紙と問題用紙を提出してから、退室できますが、再入室はできません。
- 試験終了の合図があるまで着席し、解答用紙を書き続けてください。合図の後は解答をやめ、ペンを置いてください。
- 試験終了後は、教員の指示に従って、問題用紙と解答用紙を提出してください。
- 不明な点があれば、静かに手を上げて教員に質問してください。
まとめ
各回の学習ポイント
- 基礎固め(第1回~第3回):C言語の基本構文を確実に理解
- 制御構造(第4回~第5回):ループと条件分岐を活用したプログラム作成
- データ構造(第6回):配列を使った効率的なデータ処理
- 関数化(第7回):プログラムの部品化と構造的プログラミング
- 応用技術(第8回~第10回):実践的なプログラミング技法
- 文字列とポインタ(第11回~第13回):高度なデータ操作技術
第1回 - まずは慣れよう(基本の表示と入力)
学習目標
C言語の基本的な構造と入出力を理解する
プログラムの基本構造
include文とmain関数
#include <stdio.h>
の意味と役割- main関数の構造と「決まり文句」
- コンパイルとリンクの概念
出力処理
各種出力関数
- printf関数:書式化された表示
- puts関数:文字列表示と自動改行
- putchar関数:単一文字表示
- 変換指定子:
%d
,%f
等の使い方
コメント(注釈)
- 伝統的コメント:
/* ... */
- 行末コメント:
// ...
変数とデータ型
- int型変数の宣言と初期化
- 初期化と代入の違い
- 変数の生成時の不定値問題
入力処理
- scanf関数による数値入力
- 変数のアドレス演算子(&)の使用
重要なポイント
基本ルール
- 文はセミコロン(
;
)で終了し、{
と}
の間に記述された文が順に実行される - 変数は生成時に不定値を持つため、初期化が推奨される
- 改行文字
\n
や警報文字\a
などの拡張表記の理解
第2回 - 演算と型(計算と型変換)
学習目標
演算子の使い方とデータ型の概念を習得する
算術演算子
演算子 | 説明 | 注意点 |
---|---|---|
+ |
加算 | |
- |
減算 | |
* |
乗算 | |
/ |
除算 | 整数同士の除算では小数部切り捨て |
% |
剰余 | 整数のみに適用可能 |
単項演算子
- 単項+演算子、単項-演算子
- 前置・後置増分演算子(
++
) - 前置・後置減分演算子(
--
)
代入演算子
- 単純代入演算子(
=
) - 複合代入演算子(
+=
,-=
,*=
,/=
,%=
)
データ型と型変換
基本データ型
- int型(整数)
- double型(浮動小数点数)
型変換
- 暗黙の型変換:異なる型の演算時の格上げ
- キャスト演算子による明示的型変換
変換指定の詳細
- フラグ、最小フィールド幅、精度の指定
- scanfとprintfでの書式指定子の使い分け
重要なポイント
型変換の注意
- オペランドの型が同一であれば、演算結果も同じ型となる
- 型が異なる場合、小さい型が大きい型に変換されて演算される
- 整数の除算では小数部が切り捨てられることの理解
第3回 - プログラムの流れの分岐(条件判定)
学習目標
条件分岐による制御構造を理解する
if文の基本形
構文パターン
// 単純if文
if (条件) 文
// else付きif文
if (条件) 文1 else 文2
// 入れ子になったif文(else if構造)
if (条件1) 文1
else if (条件2) 文2
else 文3
比較・論理演算子
比較演算子
演算子 | 意味 |
---|---|
== |
等しい |
!= |
等しくない |
< |
より小さい |
> |
より大きい |
<= |
以下 |
>= |
以上 |
論理演算子
演算子 | 意味 | 特徴 |
---|---|---|
&& |
AND | 短絡評価 |
\|\| |
OR | 短絡評価 |
! |
NOT |
条件演算子(三項演算子)
if文を式として表現する方法複合文(ブロック)
{}
による文のグループ化- 複数の文を単一の文として扱う方法
switch文
重要なポイント
制御構造の理解
- 制御式の評価で得られた値が非0であれば真、0であれば偽
- 論理演算子は短絡評価を行う(
&&
の左が偽なら右は評価されない等) - switch文では各caseの終わりにbreak文が必要
第4回 - プログラムの流れの繰り返し(1)(基本ループ)
学習目標
基本的なループ構造を習得する
do文(後判定繰り返し)
特徴
- ループ本体が最低1回は実行される
- ユーザー入力の妥当性検証での活用
while文(前判定繰り返し)
特徴
- 条件が最初から偽の場合、1回も実行されない
- 無限ループ:
while (1)
演算子の詳細
複合代入演算子
+=
,-=
等の利点- 左辺の評価が1回のみで効率的
前置・後置増減演算子
- 前置演算子:増減してから値を返す
- 後置演算子:値を返してから増減
論理否定演算子
!
演算子とド・モルガンの法則
break文とcontinue文
文 | 動作 |
---|---|
break |
ループの強制終了 |
continue |
ループの残り部分をスキップ |
文字定数とputchar関数
- 文字定数(
'A'
)と文字列リテラル("A"
)の違い - putchar関数による文字出力
重要なポイント
ループの使い分け
- do文は少なくとも1回実行、while文は0回の可能性あり
- 複合代入演算子は左辺の評価が1回のみで効率的
- 後置演算子は値を返してから増減、前置演算子は増減してから値を返す
第5回 - プログラムの流れの繰り返し(2)(for文と多重ループ)
学習目標
より高度なループ構造と制御を理解する
for文の構造
特徴
- カウンタ用変数の開始値、終了値、増分の集約
- while文との相互変換可能性
多重ループ
構造
- 2重、3重ループの構造
- 外側・内側ループの制御変数
- 図形描画(三角形、長方形等)への応用
break文とcontinue文の多重ループでの動作
多重ループでの注意
- 直接囲んでいるループのみに影響
- 外側ループへの影響なし
プログラム要素と書式
言語要素
- キーワード(37個)の一覧
- 識別子の命名規則
- 区切り子の役割
- 自由形式記述とインデント
重要なポイント
効率的なループ設計
- for文はカウンタ用変数の制御情報を頭部に集約
- 多重ループでのbreak/continue文は最内側のループのみに作用
- 適切なインデントでプログラムの構造を明確化
第6回 - 配列(データ構造の基礎)
学習目標
配列を使ったデータ処理を習得する
配列の基本概念
定義と宣言
- 同一型要素の直線状配置
- 宣言:
型名 配列名[要素数];
- 添字演算子(
[]
)による要素アクセス - 添字は0から始まる
配列の初期化
// 初期化子リスト
int arr[] = {値1, 値2, ...};
// 要素数の自動決定
int numbers[] = {1, 2, 3, 4, 5}; // 5要素の配列
// 不足分の0初期化
int data[10] = {1, 2, 3}; // 残り7要素は0で初期化
配列の走査
基本パターン
応用例
- 最大値・最小値の検索
- 要素の並び替え(反転)
多次元配列
2次元配列
配置順序
構成要素は末尾側添字が優先的に増加する順で配置
オブジェクト形式マクロ
利点
- マジックナンバーの除去
- プログラムの保守性向上
重要なポイント
配列の理解
- 配列は同一型の変数が直線状に連続して並んだもの
- 要素数がnの配列の添字は0からn-1まで
- 代入演算子では配列全体のコピーはできない(要素ごとの代入が必要)
第7回 - 関数(プログラムの部品化)
学習目標
関数を使ったプログラムの構造化を理解する
関数の基本構造
構成要素
- 関数定義:返却値型、関数名、仮引数型並び、函数本体
- 関数呼出し:関数呼出し演算子
()
の使用 - return文による値の返却
引数と返却値
値渡し(pass by value)
- 仮引数の変更が実引数に影響しない特性
- 引数による引数の受渡し
返却値
- 返却値型が
void
の関数(値を返さない関数)
関数の設計原則
原則 | 説明 |
---|---|
汎用性 | 特定データに依存しない設計 |
独立性 | 外部変数への依存を避ける |
単一責任 | 一つの関数は一つの機能 |
配列と関数
配列の受け取り
注意点
- 要素数は別の引数として受け取る
const
型修飾子による読み取り専用指定
有効範囲と記憶域期間
範囲の種類
- ブロック有効範囲
- ファイル有効範囲
記憶域期間
- 自動記憶域期間
- 静的記憶域期間
static
記憶域クラス指定子の効果
関数原型宣言
- 関数の仕様情報の提供
- ヘッダファイルのインクルード
- 前方宣言の必要性
重要なポイント
関数設計のベストプラクティス
- 関数呼出しでは実引数の値が仮引数に代入される(値渡し)
- 配列を受け取る関数では、仮引数の配列は実引数の配列そのもの
- 関数は独立性と汎用性を重視して設計する
第8回 - 基本型(データ型の詳細理解)
学習目標
C言語が提供する各種データ型の特徴と使い分けを理解する
算術型の分類
整数型
- 文字型(
char
) - int系型(
short
,int
,long
,long long
) - 列挙型
浮動小数点型
float
double
long double
基本型
キーワードだけで型名を表せる型(文字型、int系型、浮動小数点型)
基数と基数変換
基数 | 表記法 | 使用文字 | 例 |
---|---|---|---|
10進数 | そのまま | 0~9 | 123 |
8進数 | 先頭に0 |
0~7 | 0123 |
16進数 | 先頭に0x |
0~9, A~F | 0x7B |
2進数 | - | 0, 1 | コンピュータ内部表現 |
整数型の詳細
符号の有無
- 符号付き型:負・0・正を表現(
signed
指定子または省略) - 符号無し型:0・正のみ表現(
unsigned
指定子)
表現範囲
<limits.h>
ヘッダで各型の最小値・最大値が定義
型指定子
signed
/unsigned
short
/long
/long long
文字型(char)の特徴
特性 | 説明 |
---|---|
構成ビット数 | CHAR_BIT マクロで定義(通常8ビット) |
処理系依存 | "単なる"char 型が符号付きか符号無しかは処理系による |
3種類 | char 、signed char 、unsigned char |
sizeof演算子
特徴
- 用途:型や変数のサイズをバイト単位で取得
- 返却値型:
size_t
型(符号無し整数型の同義語)
整数の内部表現
表現方法
- 符号無し整数:純2進記数法による表現
- 符号付き整数:
- 2の補数表現
- 1の補数表現
- 符号と絶対値表現
- 符号ビット:最上位ビットで符号を表現(0=非負、1=負)
ビット単位の論理演算
演算子 | 名称 | 動作 |
---|---|---|
& |
論理積 | 両方のビットが1の場合のみ1 |
\| |
論理和 | どちらかのビットが1なら1 |
^ |
排他的論理和 | ビットが異なる場合のみ1 |
~ |
補数 | 全ビットを反転 |
シフト演算
演算子 | 動作 |
---|---|
<< |
左シフト:ビットを左にずらし、右側に0を挿入 |
>> |
右シフト:ビットを右にずらす(負値の動作は処理系依存) |
浮動小数点型
特徴
- 表現方法:指数部と仮数部による科学的記数法
- 精度:
float
<double
<long double
- 使い分け:
- 基本は
double
- メモリ節約時は
float
- 高精度時は
long double
重要なポイント
データ型の理解
- 整数定数には接尾語(U, L, LL)を付けて型を明示可能
- 符号無し整数はオーバフローしても例外が発生せず、剰余が結果となる
- 浮動小数点数は有限精度のため、繰り返し制御は整数型を推奨
- 演算子には優先順位と結合性があり、同優先度では結合性で評価順序が決定
第9回 - いろいろなプログラムを作ってみよう(1)(関数形式マクロ、ソート、列挙体)
学習目標
関数形式マクロ、ソート、列挙体を実践的な技術を習得する
関数形式マクロ
定義と使用
特徴
- 展開処理:コンパイル時に引数を含めてテキスト置換
- 利点:型に依存しない汎用性、実行効率の向上
- 注意点:副作用(引数の多重評価)の可能性
コンマ演算子
動作
- 評価:左から右へ順次評価、右オペランドの値が結果
- 用途:関数形式マクロで複数の処理を1つの式にまとめる
ソート(バブルソート)
アルゴリズムの概念
- 目的:データを一定の基準で昇順・降順に並べ替え
- 手法:隣接要素の比較・交換を繰り返し
- パス:1回の走査で最小値(または最大値)を先頭に移動
- 効率:n個の要素に対してn-1パス
列挙体(enum)
基本構文
特徴
- 目的:限られた整数値の集合を名前付きで表現
- 値の割り当て:0から始まる連番(明示的指定も可能)
- 型名:
enum 列挙体タグ名
(タグ名のみでは型名にならない)
重要なポイント
実装時の注意点
- 関数形式マクロは展開時の副作用に注意(引数を括弧で囲む)
- 列挙体は整数値に名前を付けることでプログラムの可読性向上
第10回 - いろいろなプログラムを作ってみよう(2)(再帰と文字処理)
学習目標
再帰関数の深い理解と文字・入出力処理の実践的活用を習得する
再帰的関数の詳細
再帰の概念
- 定義:自分自身を含む定義や自分自身を用いた定義
- 実行過程:関数呼び出しの積み重ねと順次返却
- 適用条件:問題やデータ構造が再帰的に定義されている場合
階乗の例
// 再帰定義
// 0! = 1
// n! = n × (n-1)! (n > 0)
int factorial(int n) {
if (n == 0) return 1; // 基底ケース
return n * factorial(n-1); // 再帰ケース
}
getchar関数とEOF
機能と特徴
- 機能:標準入力から1文字を読み込んで返却
- EOF(End Of File):入力終了またはエラー時に返される負の値
- 入力終了:
- Windows:Ctrl+Z
- Unix/Linux:Ctrl+D
典型的な使用パターン
文字コードと数字文字
文字コードの基礎
- 文字コード:各文字に割り当てられた非負整数値
- JISコード:日本で広く使用される文字コード体系
数字文字の性質
- 特性:
'0'
~'9'
は連続した値を持つ(保証されている) - 変換公式:数字文字
'n' - '0' = 数値n
文字処理の実践
効率的な実装
- 数字文字カウント:switch文からif文への簡略化
- 配列添字との対応:
ch - '0'
による配列インデックス計算 - 可搬性:具体的な文字コード値に依存しない実装
バッファリング
バッファリング方式 | 動作 |
---|---|
完全バッファリング | バッファが満杯時に入出力実行 |
行バッファリング | 改行文字読み込み時に入出力実行 |
無バッファリング | 即座に入出力実行 |
拡張表記の詳細
引用符の表記規則
文字列リテラル内
"
:必須でエスケープ'
:両方可能
文字定数内
'
:必須でエスケープ"
:両方可能
数値拡張表記
- 8進拡張表記:
\nnn
(1~3桁の8進数) - 16進拡張表記:
\xnn
(任意桁数の16進数)
重要なポイント
文字処理のベストプラクティス
- 再帰関数は「基底ケース」で終了条件を明確に定義する
- 文字処理では具体的なコード値でなく文字定数を使用して可搬性を確保
- 数字文字の連続性を活用した効率的な配列インデックス計算
- 入出力のバッファリング方式がプログラムの動作に影響する
第11回 - 文字列の基本(文字の集合体)
学習目標
文字列の構造と基本的な操作方法を理解する
文字列の基本概念
定義と構造
- 文字列の定義:文字の並び(複数文字の集合)
- 文字列リテラル:
"ABC"
のような二重引用符で囲んだ文字の並び - ヌル文字(
'\0'
):文字列終端を示す値0の文字(自動付加) - メモリ占有:文字列
"ABC"
は実際には4文字分('A'
,'B'
,'C'
,'\0'
)
文字列の格納と表現
格納方法
- 格納先:
char
の配列が文字列の格納先として最適
初期化方法
// 推奨方法
char str[] = "ABC";
// 同等の方法
char str[] = {'A', 'B', 'C', '\0'};
// 空文字列
char ns[] = ""; // ヌル文字のみを含む1要素の配列
長さの概念
文字列の長さ:先頭からヌル文字までの文字数(ヌル文字を除く)
文字列の入出力
表示方法
- printf関数:変換指定
%s
- puts関数:文字列表示
読込み方法
- scanf関数:変換指定
%s
(&
演算子は不要)
書式化表示
- 最小フィールド幅の指定
- 精度の指定
- 左右寄せの指定
文字列の配列
2次元配列による複数文字列格納
構造と特徴
- 構造:要素型が
char[6]
型で要素数が3の配列 - アクセス:各文字列への個別アクセスと操作
文字列操作の基本
基本操作
- 長さ計算:ヌル文字まで走査してカウント
- 文字列の走査:先頭から順にヌル文字まで各문字を処理
- 文字の検索・カウント:特定文字の出現回数や位置の検出
文字変換関数
- toupper関数:小文字を大文字に変換
- tolower関数:大文字を小文字に変換
重要なポイント
文字列処理の基本原則
- 文字列リテラルには末尾に自動的にヌル文字が付加される
- 文字列の実際の長さと配列の要素数は必ずしも一致しない
- 文字列処理では常にヌル文字を終端として認識する
- 関数間の文字列受渡しでは要素数を別途指定する必要がない(ヌル文字で判定)
第12回 - ポインタ(1)(メモリアドレスの直接操作)
学習目標
ポインタの基本概念とメモリアドレスを使った間接操作を理解する
オブジェクトとアドレス
基本概念
- アドレス:記憶域上におけるオブジェクトの格納場所(番地)
- アドレス演算子(
&
):オブジェクトのアドレスを取得 - メモリモデル:オブジェクトは記憶域の一部を占有し、固有の番地を持つ
ポインタの基本概念
定義と宣言
- ポインタ:他のオブジェクトのアドレスを格納する変数
- 宣言:
int *p;
(int型オブジェクトへのポインタ) - 初期化:
int *p = &n;
(変数nのアドレスでポインタpを初期化) - 指す関係:「pはnを指す」:ポインタpの値がnのアドレスである状態
間接演算子(*)
機能と用途
- 参照外し:ポインタが指すオブジェクトへの間接アクセス
- エイリアス:
*p
:ポインタpが指すオブジェクトのエイリアス(別名) - 間接操作:間接式
*p
を通じてオブジェクトの値の読取り・変更が可能 - 動的アクセス:実行時にアクセス対象を決定
関数とポインタ
値渡しの制限
- 問題:仮引数の変更は実引数に反映されない
- 解決:ポインタ渡しによるオブジェクトのアドレス受渡し
ポインタ渡しのパターン
ポインタの実用例
典型的な使用場面
- 2値の交換:
swap(&a, &b)
による変数の値交換 - 複数値の返却:ポインタを通じて複数の結果を返却
- 和と差の計算:1つの関数で2つの結果を同時に取得
scanf関数とポインタ
必要性の理由
- scanf関数の特性:読み込んだ値を格納するためにポインタが必要
- 使用法:
scanf("%d", &n);
:変数nのアドレスを渡して値を格納 - 対比:printf関数は値を表示するだけなので値渡しで十分
重要なポイント
ポインタの理解
- ポインタは「オブジェクトを指す」概念で、アドレスを値として持つ
- アドレス演算子&と間接演算子*は相互に逆の操作を行う
- ポインタを使えば関数による呼出し元オブジェクトの変更が可能
- 空ポインタ(NULL)は何も指さない特別なポインタ値
第13回 - ポインタ(2)(配列との密接な関係)
学習目標
ポインタと配列の相互関係と配列処理でのポインタ活用を理解する
ポインタと配列の基本関係
配列名の解釈
- 基本原則:配列名は先頭要素へのポインタとして解釈される
- 等価性:
int a[5];
の場合、a
は&a[0]
と同等 - 例外:sizeof演算子とアドレス演算子&のオペランドの場合
ポインタ演算
演算の種類
- 後方移動:
p + i
:ポインタpが指す要素のi個後方の要素を指すポインタ - 前方移動:
p - i
:ポインタpが指す要素のi個前方の要素を指すポインタ - 型サイズ考慮:ポインタ演算では要素の型サイズが自動的に考慮される
間接演算子と添字演算子の等価性
4つの等価なアクセス方法
ポインタ取得の等価性
演算子の本質
添字演算子[]
は間接演算子*
とポインタ演算の組み合わせ
ポインタと配列の表記上の可換性
特徴
- 同等な振る舞い:配列の先頭要素を指すポインタは配列そのもののように振る舞う
- オフセット概念:配列添字はオフセット(先頭から何要素後方か)を表す
- 添字の開始:添字は必ず0から始まる(先頭要素が基準のため)
配列とポインタの相違点
項目 | 配列 | ポインタ |
---|---|---|
代入 | 不可能(x = a; はエラー) |
可能 |
アドレス | 固定 | 変更可能 |
役割 | 記憶域の確保 | 既存オブジェクトへの参照 |
配列の受渡し
仮引数の等価性
// 以下はすべて同等
void func(int v[]) { /* 処理 */ }
void func(int v[10]) { /* 処理 */ }
void func(int *v) { /* 処理 */ }
受渡しの実際
- 実際の受渡し:先頭要素へのポインタとして受渡し
- 要素数の管理:配列の要素数は別の引数として受け取る必要がある
- 直接操作:受け取ったポインタを通じて元の配列要素を直接操作可能
重要なポイント
ポインタと配列の関係
- 配列名は(一部例外を除き)先頭要素へのポインタとして扱われる
- ポインタ演算により配列要素への効率的なアクセスが可能
- 4つの等価な配列要素アクセス方法:
a[i]
,*(a+i)
,p[i]
,*(p+i)
- 関数間の配列受渡しは実質的にポインタの受渡し
- 配列の要素数情報は別途引数として渡す必要がある