%=====================================================================
% 秋田高専 5E 計算機応用 テキスト
%テーマ サンプルプログラム
%    本テキストの内容
%        ・
%        ・
%        ・
%        ・
%
% last updated 2005.5.19
%    created by  Masashi Yamamoto
%     e-mail yamamoto@akita-nct.jp
%=====================================================================
\documentclass[10pt,a4paper]{jarticle}
\usepackage{graphicx,amsmath,amssymb,ascmac,theorem,float}
\usepackage{listings, jlisting, html}
\oddsidemargin 0mm  %左の余白 25.4mm-0mm奇数ページ
\evensidemargin 0mm %左の余白 25.4mm-0mm偶数ページ
\textwidth 160mm
\newcommand{\command}[1]{「\texttt{#1}」}
\newcommand{\tw}[1]{\texttt{#1}}
\newcommand{\vm}[1]{\boldsymbol{#1}}
%
\renewcommand{\lstlistingname}{リスト}
\lstset{language=C,%
        basicstyle=\footnotesize,%
        commentstyle=\texttt,%
        classoffset=1,%
        keywordstyle=\bfseries,%
	frame=tRBl,framesep=5pt,%
	showstringspaces=false,%
        numbers=left,stepnumber=1,numberstyle=\footnotesize%
	}%
%
\begin{document}
\title{構造体の練習問題のプログラム例}
\author{山本昌志\thanks{独立行政法人　秋田工業高等専門学校　電気情報工学科}}
\date{2004年5月19日}
\maketitle
%
%=====================================================================
\section{本日の学習内容}
%=====================================================================
教科書 p.288 練習問題8のプログラム例を示し、その動作を詳細に説明する。これらのプ
ログラムは、これまで学習してきたことの全てが含まれている。動作の分からないところ
があれば、教科書などを見て、完全に理解する必要がある。

ここでのメインテーマは構造体である。構造体の基本的な概念は、「プログラマーが分かり
やすいように、データをまとめて管理する」と言うことである。これが便利なものである
と理解し、自由自在に使いこなせなくてはならない。
%
%=====================================================================
\section{Lesson 8-1 アンケート集計}
%=====================================================================
%---------------------------------------------------------------------
\subsection{問題}
%---------------------------------------------------------------------
%
\begin{itembox}[l]{Lesson 8-1}
以下のような予想結果を10人分入力し、男女別の予想結果を「勝ち・引き分け・負け」に
 分けて集計し、表示するプログラムを構造体を利用して作成しなさい。
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	あるスポーツの勝敗予想
	 1人目の予想 (男性:M)　ホームチーム　勝ち:1
	 2人目の予想 (男性:F)　ホームチーム　負け:2
	　　・
	　　・
	　　・
	10人目の予想 (男性:F)　ホームチーム　引き分け:0
 \end{verbatim}
\end{quote}
\end{itembox}
%
%---------------------------------------------------------------------
\subsection{問題分析と構造体}
%---------------------------------------------------------------------
%---------------------------
\subsubsection{問題分析}
%---------------------------
問題は単純である。10人分の予想結果を入力し、男女別に勝敗の予想人数を集計し、表示
するプログラムである。ここで構造体を使うとしたら、各人の情報(データ)に対してであ
る。各人が持つ情報は、
\begin{itemize}
 \item 性別
 \item ホームチームの勝敗予想
\end{itemize}
の2種類である。ということで、図\ref{fig:img_struct_1}のように10個のこれらを格納する構造
体を使うことにする。
%
\begin{figure}[H]
 \begin{center}
  \includegraphics[keepaspectratio,scale=1.0]{figure/img_struct_1.eps}
  \caption{勝敗予想の基本情報}
  \label{fig:img_struct_1}
 \end{center}
\end{figure}
%

集計結果も構造体にすることも可能であるが、教科書の解答の通り、配列を使うことにす
る。集計結果は全て男女別の勝敗予想の人数で、同じ性質の整数の集まりなので、配列で
も十分である。
%
%---------------------------
\subsubsection{構造体の定義}
%--------------------------
各人の情報は性別と勝敗予想である。それが10人分ある。10人同じ情報があるので、それ
は配列にするのが良いだろう。各個人の情報は、構造体で一つの変数にまとめると分かりや
すくて良い。性別と勝敗予想を一つの変数にまとめるために、C言語では次のように書く。
%
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	struct datatype{
	  char sex;
	  int toto;
	};
 \end{verbatim}
\end{quote}
%
\tw{datatype}という構造体を定義し、その中には性別を表す文字型(\tw{char})の変数
\tw{sex}と、勝敗予想を表す整数型(\tw{int})の変数\tw{toto}がある。これら2つの変数
を構造体\tw{datatype}のメンバーと言う。これで、図\ref{fig:diff_struct_1}のような
変数が定義できたのである。
%
\begin{figure}[H]
 \begin{center}
  \includegraphics[keepaspectratio,scale=1.0]{figure/diff_struct_1.eps}
  \caption{構造体のイメージ。構造体(struct datatype)は2つのメンバーがある。}
  \label{fig:diff_struct_1}
 \end{center}
\end{figure}
%

文字型変数\tw{sex}に1文字を格納して各人の性別を表す。例えば、メンバーの\tw{sex}
は
\begin{itemize}
 \item \tw{f}が格納されていれば女性(female)
 \item \tw{m}が格納されていれば男性(male)
\end{itemize}
とする。整数型変数\tw{toto}には、ホームチームの試合の予想結果を表す。例えば、メ
ンバー\tw{toto}は、ホームチームの勝敗として
\begin{itemize}
 \item 0が格納されていれば、引き分け
 \item 1が格納されていれば、勝ち
 \item 2が格納されていれば、負け
\end{itemize}
とする\footnote{ここでも文字型の変数が使えるが、教科書の通り整数型を使う。}。ここ
で、メンバー\tw{sex}が\tw{f}や\tw{m}が男性や女性、\tw{0,1,2}が引き分けや勝ち負け
を表すと決めたのはプログラマーであり、コンピューターはなにも関知していない事を忘
れてはならない。

これで、データ構造の内容が決まった。新しい変数の型として構造体を定義した。まだ、データの型の定義が終わっただけで、コンピューターのメモリーの確保が終わっ
ていない。実際にデータを操作する場合、メモリーを確保する事が必要である。これは、
プログラム中で
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	struct datatype data[10];
 \end{verbatim}
\end{quote}
と書けばよい。そうすると、図\ref{fig:struct_memory_1}のようにメモリーが確保され
る。
%
\begin{figure}[H]
 \begin{center}
  \includegraphics[keepaspectratio,scale=1.0]{figure/struct_memory_1.eps}
  \caption{メモリー中の構造体のデータ}
  \label{fig:struct_memory_1}
 \end{center}
\end{figure}
%
%---------------------------------------
\subsubsection{構造体のメンバーへのアクセス}
%---------------------------------------
これで、データの構造が決まったので、あとはそれぞれのメンバーにアクセスする方法が
分かれば、構造体の全てが分かる。構造体のメンバーへのアクセスの前に通常の変数と配
列のデータへのアクセスの方法を復習する。通常の変数、例えば\tw{a}という変数へのア
クセスは容易で、変数名を使えばそのデータを参照できる。次に配列であるが、それは配
列名と添え字を示すことによりデータにアクセスできる。例えば、\tw{b[3]}とかである。

データは構造体のメンバーに格納されているから、それにアクセスするためには、構造体
名とメンバー名を示す必要がある。実際のアクセスの方法については、%
\htmladdnormallink{既に学習}
{http://www.akita-nct.jp/~yamamoto/lecture/2005/2E/1st/html/%
node3.html#SECTION00032000000000000000}%
したように、ドット演算子をつかう。ここでは、次のように使われている。
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	data[loop].sex
	data[loop].toto
 \end{verbatim}
\end{quote}
%
%---------------------------------------------------------------------
\subsection{プログラム例}
%---------------------------------------------------------------------
この問題のプログラム例%
\begin{rawhtml}
(<a href="http://www.akita-nct.jp/~yamamoto/lecture/2005/2E/4th/index.html#toto">toto.c</a>)
\end{rawhtml}
をリスト\ref{prog:question}に示す。このプログラムは、グローバルな部分と4つの関数
からできておりそれぞれの動作は以下の通りである。

%------------------------
\subsubsection{グローバル}
%------------------------
\begin{list}{}{\leftmargin=7em \labelwidth=5em}
 \item[10-13行]\htmladdnormallink{構造体の定義}%
	       {http://www.akita-nct.jp/~yamamoto/lecture/2005/2E/1st/html/%
	       node3.html#SECTION00031000000000000000}
 \item[17-19行]\htmladdnormallink{関数プロトタイプの宣言}%
	       {http://www.akita-nct.jp/~yamamoto/lecture/2004/1E/27th/html/%
	       node3.html}
\end{list}
%
%----------------------------
\subsubsection{\tw{main}関数}
%----------------------------
\begin{list}{}{\leftmargin=7em \labelwidth=5em}
 \item[25行]\htmladdnormallink{メイン関数}%
	       {http://www.akita-nct.jp/~yamamoto/lecture/2004/1E/28th/html/%
	       node1.html#SECTION00011000000000000000}%
	       の始まり。メイン関数の終わりは、39行である。
 \item[28行]\htmladdnormallink{構造体変数の宣言}%
	       {http://www.akita-nct.jp/~yamamoto/lecture/2005/2E/3rd/html/%
	       node3.html#SECTION00033000000000000000}。
	       これは、配列型の構造体を宣言して、メモリーを確保している。
 \item[29行]集計結果を格納する\htmladdnormallink{配列}%
	       {http://www.akita-nct.jp/~yamamoto/lecture/2004/1E/18th/html/%
	       arry.html}の宣言。この配列には、以下のようなデータが格納される。
	       \begin{quote}
		\setlength{\baselineskip}{12pt}
		\begin{verbatim}
		result[0][0] : 女性で引き分けと予想した人数
		result[0][1] : 女性で勝ちと予想した人数
		result[0][2] : 女性で負けと予想した人数
		result[1][0] : 男性で引き分けと予想した人数
		result[1][1] : 男性で勝ちと予想した人数
		result[1][2] : 男性で負けと予想した人数
		\end{verbatim}
	       \end{quote}
 \item[33行]データ入力用の\htmladdnormallink{関数}%
	       {http://www.akita-nct.jp/~yamamoto/lecture/2004/1E/27th/html/%
	       index.html}の呼び出し。
 \item[34行]結果集計の関数の呼び出し。
 \item[35行]結果出力の関数の呼び出し。
 \item[38行]メイン関数が\htmladdnormallink{戻り値}%
	    {http://www.akita-nct.jp/~yamamoto/lecture/2004/1E/27th/html/%
	    node3.html#SECTION00032000000000000000}%
	    を返して、呼びだし元へ戻る。
 \item[39行]メイン関数のブロックの終わりを示している。
 \end{list}
%
%------------------------------------------
\subsubsection{データ入力関数(\tw{data\_input})}
%------------------------------------------
\begin{list}{}{\leftmargin=7em \labelwidth=5em}
 \item[55行]データ入力関数の開始
 \item[56行]ループのカウンターに用いる変数宣言
 \item[57行]キーボード入力の時にバッファーに残るゴミを入れる。
 \item[62-68行]\tw{for}文による10回のループ
 \item[63行]性別の入力を促す。
 \item[64行]\tw{scanf}関数によりキーボードからデータを取得して、構造体変数
	    \tw{data[loop]}のメンバー\tw{sex}に格納する。
 \item[66行]ホームチームの勝敗の入力を促す。
 \item[67行]\tw{scanf}関数によりキーボードからデータを取得して、構造体変数
	    \tw{data[loop]}のメンバー\tw{toto}に格納する。
 \item[70行]関数が戻り値を返して、呼びだし元へ戻る。
 \item[71行]関数のブロックの終わりを示している。
\end{list}
%
%---------------------------------------------
\subsubsection{データの集計関数(\tw{calc\_result})}
%---------------------------------------------
\begin{list}{}{\leftmargin=7em \labelwidth=5em}
 \item[93行]データ入力関数の開始
 \item[94行]ループのカウンターに用いる変数宣言
 \item[97-101行]人数を格納する配列をゼロに初期化する。
 \item[103-109行]男女別勝敗の人数のカウント
 \item[111行]関数が戻り値を返して、呼びだし元へ戻る。
 \item[112行]関数のブロックの終わりを示している。
\end{list}
%
%-------------------------------------------
\subsubsection{結果出力関数(\tw{print\_result})}
%-------------------------------------------
これは説明するまでもないであろう。各自考えよ。
%
%----------------------------
\subsubsection{プログラムリスト}
%----------------------------
%
\input{program/toto_c.tex}
%
\begin{latexonly}
\begin{lstlisting}[caption=アンケートの集計,label=prog:question]
/*==================================================================*/
/*==================================================================*/
/*           教科書 「C言語プログラミング初歩の初歩」                    */
/*                練習問題 8 Lesson 8-1 アンケートの集計               */
/*==================================================================*/
/*==================================================================*/
#include <stdio.h>

/* ---- 構造体　---- */
struct datatype{
  char sex;       /* 性別を表す文字         m:男性  f:女性     */
  int toto;       /* 予想結果を記憶する整数  0:引分  1:勝  2:負 */
};

/* ---- プロトタイプ宣言 ---- */

int data_input(struct datatype data[]);
int calc_result(struct datatype data[], int result[][3]);
int print_result(int result[][3]);


/*==================================================================*/
/*           メイン関数                                              */
/*==================================================================*/
int main(void){

  /* ---- 変数宣言 ---- */
  struct datatype data[10];  /* 構造体の宣言 */
  int result[2][3];          /* 勝敗予想人数[0:男 1:女][0:引分 1:勝 2:負]*/

  /* ---- 実行文 ---- */

  data_input(data);              /* データ入力関数呼び出し */
  calc_result(data, result);     /* 結果集計関数の呼び出し */
  print_result(result);          /* 結果表示関数の呼び出し */
  
  
  return 0;
}


/*==================================================================*/
/*  データの入力                                                     */
/*   [引数]                                                         */
/*      仮引数  data[] : 予想結果を格納する構造体 参照渡し               */
/*   [戻り値]                                                       */
/*            int : 常に 0 が返される                                */
/*   [動作内容]                                                      */
/*      ユーザーに入力を促し、キーボードから入力された　男性 or 女性　と    */
/*      勝敗予想を引数で渡された構造体に格納する。                        */
/*            男性 f   女性 m                                        */
/*            勝ち 1   引き分け 0   負け 2                            */
/*            これらの値は、予想結果を格納する構造体 data[] に格納される   */
/*==================================================================*/
int data_input(struct datatype data[]){
  int loop;             /* 読み込み番号のカウンター      */
  char temp;            /* バッファーに残ったゴミを入れる */


  /* ---- 勝敗予想の入力 ---- */

  for(loop = 0; loop < 10; loop++){
    printf("%d人目の予想をする方の性別は?  女性:f  男性:m\n",loop+1);
    scanf("%c%c", &data[loop].sex, &temp);

    printf("ホームチームの試合?  勝ち:1   引き分け:0   負け:2\n");
    scanf("%d%c", &data[loop].toto, &temp);
  }

  return 0;
}
    

/*==================================================================*/
/* データの集計 　　　　　　                                           */
/*   [引数]                                                         */
/*      仮引数  data[]    : 予想結果が格納されている構造体 参照渡し       */
/*             result[][]: 集計結果の集計を格納する配列   参照渡し       */
/*                            result[0:女性 1:男性][0:引分 1:勝 2:負] */
/*   [戻り値]                                                        */
/*            int : 常に 0 が返される                                 */
/*   [動作内容]                                                      */
/*      予想結果の集計をおこなう。各場合における人数は配列result[][]       */
/*      に格納される。                                                */
/*      勝敗予想を引数で渡された構造体に格納する。                        */
/*            result[0][0] : 女性で引き分けと予想した人数               */
/*            result[0][1] : 女性で勝ちと予想した人数    　　           */
/*            result[0][2] : 女性で負けと予想した人数　　               */
/*            result[1][0] : 男性で引き分けと予想した人数               */
/*            result[1][1] : 男性で勝ちと予想した人数    　　           */
/*            result[1][2] : 男性で負けと予想した人数　　               */
/*==================================================================*/
int calc_result(struct datatype data[], int result[][3]){
  int loop1, loop2;

  /* ---- 初期化 ---- */
  for(loop1=0; loop1<2; loop1++){
    for(loop2=0; loop2<3; loop2++){
      result[loop1][loop2]=0;         /* 勝敗予想人数の配列を全てゼロに */
    }
  }

  for(loop1=0; loop1<10; loop1++){
    if(data[loop1].sex == 'f'){
      result[0][data[loop1].toto]++;  /* 女性の場合 */
    }else{
      result[1][data[loop1].toto]++;  /* 弾性の場合 */
    }
  }

  return 0;
}

/*==================================================================*/
/*           結果表示                                                */
/*==================================================================*/
int print_result(int result[][3]){

  printf("\n##集計結果表示##\n");
  printf("女性の予想は、[勝ち:%2d][引き分け:%2d][負け:%2d]\n",
	 result[0][1],result[0][0],result[0][2]);
  printf("男性の予想は、[勝ち:%2d][引き分け:%2d][負け:%2d]\n",
	 result[1][1],result[1][0],result[1][2]);

  return 0;
}
\end{lstlisting}\vspace{5mm}
\end{latexonly}
%
\fbox{実行結果}
%
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	##集計結果表示##
	女性の予想は、[勝ち: 2][引き分け: 2][負け: 1]
	男性の予想は、[勝ち: 1][引き分け: 2][負け: 2]
 \end{verbatim}
\end{quote}
%
%
%=====================================================================
\section{Lesson 8-2 データをまとめて管理する1}
%=====================================================================
%---------------------------------------------------------------------
\subsection{問題}
%---------------------------------------------------------------------
\begin{itembox}[l]{Lesson 8-2}
音楽CD 10枚に入っている曲 (各CDには6曲) を入力し、テキストファイルに記録するプロ
グラムを作成しなさい。ただし、作成するテキストファイル(CDdata.txt)は次の通りとし
ます。
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	CD1 title: Zokkon C GENGO
	Artist: Hoge Maru
	song1: Ikeike hensuu
	song2: Hairetu BANZAI
	  ・
	  ・
	  ・
	song6: Saraba Kozoutai
	CD2 Title: Love Love C
	Artist: etc etc
 \end{verbatim}
\end{quote}
プログラム中のCDデータの取り扱いには、構造体を使うこと。
\end{itembox}
%
%---------------------------------------------------------------------
\subsection{プログラム例}
%---------------------------------------------------------------------
この問題のプログラム例%
\begin{rawhtml}
(<a href="http://www.akita-nct.jp/~yamamoto/lecture/2005/2E/4th/index.html#cdwrite">CD.c</a>)
\end{rawhtml}
をリスト\ref{prog:CD_write}に示す。
%
\input{program/CD_c.tex}
%
\begin{latexonly}
\begin{lstlisting}[caption=CDのデータをファイル出力,label=prog:CD_write]
#include <stdio.h>

/* ---- 構造体 ---- */
struct cd_data{
  char title[64];    /* タイトル名を入れる配列       */
  char artist[64];   /* アーティスト名を入れる配列    */
  char song[6][64];  /* 曲名をいれる配列 6曲まで入力可 */
};

/* ---- プロトタイプ宣言 ---- */
int data_input(struct cd_data CD[]);
int write_file(struct cd_data CD[]);

/*==================================================================*/
/*           メイン関数                                              */
/*==================================================================*/
int main(void){
  struct cd_data CD[10];

  data_input(CD);           /* CDのデータを入れる関数呼び出し         */
  write_file(CD);           /* CDのデータをファイル出力する関数呼び出し */

  return 0;
}

/*==================================================================*/
/*           データの入力                                             */
/*==================================================================*/
int data_input(struct cd_data CD[]){
  int i,j;

  for(i=0; i<10; i++){

    printf("\n--------------------------------------------------\n");
    printf("%d番目のCDについてです。\n", i+1);

    printf("タイトル?\t");
    fgets(CD[i].title,64,stdin);     /*  空白を含めてタイトル読み込み */

    printf("\nアーティスト?\t");
    fgets(CD[i].artist,64,stdin);    /*  空白を含めてアーティスト読み込み */

    for(j=0; j<6; j++){
          printf("\n\t%d番目の曲目?\t",j+1);
	  fgets(CD[i].song[j],64,stdin);  /*  空白を含めて曲名読み込み */
    }

  }

  return 0;

}

/*==================================================================*/
/*           データのfile出力                                        */
/*==================================================================*/
int write_file(struct cd_data CD[]){
  FILE *wfile;
  int i,j;

  wfile = fopen("CDdata.txt","w");    /* 書き込み用fileのオープン */


  /* ---- 10個のCDタイトルの書き込み ---- */
  for(i=0; i<10; i++){


    fprintf(wfile, "CD%d Title: %s", i+1, CD[i].title); /* タイトル */
    fprintf(wfile, "Artist: %s", CD[i].artist);         /* アーティスト*/
 
    for(j=0; j<6; j++){                                 /* 曲名 */
          fprintf(wfile,"song%d: %s", j+1, CD[i].song[j]);
    }

  }

  fclose(wfile);                     /* 書き込み用のファイルのクローズ */

  return 0;

}
\end{lstlisting}\vspace{5mm}
\end{latexonly}
%
%
%=====================================================================
\section{Lesson 8-3 データをまとめて管理する2}
%=====================================================================
%---------------------------------------------------------------------
\subsection{問題}
%---------------------------------------------------------------------
%
\begin{itembox}[l]{Lesson 8-3}
 Lesson 8-2で作成したテキストファイルを読み込み、曲名を入力するとその曲が入って
 いるCDの名前と何番目かを表示してくれるプログラムを作成しなさい。
\end{itembox}
%---------------------------------------------------------------------
\subsection{プログラム例}
%---------------------------------------------------------------------
この問題のプログラム例%
\begin{rawhtml}
(<a href="http://www.akita-nct.jp/~yamamoto/lecture/2005/2E/4th/index.html#cdread">findCD.c</a>)
\end{rawhtml}
をリスト\ref{prog:find_CD}に示す。
%
%
\input{program/findCD_c.tex}
%
\begin{latexonly}
\begin{lstlisting}[caption=曲名検索,label=prog:find_CD]
#include <stdio.h>
#include <string.h>

/*---- 構造体 ----*/
struct cd_data{
  char title[64];           /* タイトルを入れる配列 */
  char artist[64];          /* アーティストを入れる配列 */
  char song[6][64];         /* 曲名を入れる配列(6曲分) */
};

/*---- プロトタイプ宣言 ----*/
int read_file(struct cd_data CD[]);
int read_title(int cdnum, FILE *rfile, struct cd_data CD[]);
int read_artist(int cdnum, FILE *rfile, struct cd_data CD[]);
int read_song(int cdnum, FILE *rfile, struct cd_data CD[]);
int find_song(char song[], struct cd_data CD[]);

/*==================================================================*/
/*           メイン関数                                              */
/*==================================================================*/
int main(void){
  char song[64];                 /* 検索する曲名を入れる配列 */
  int nc, find;
  struct cd_data CD[10];         /* CDのデータを入れる構造体 */

  /*----- 検索する曲名の入力 ---------*/

  printf("探したい曲名?\t");
  fgets(song, 64, stdin);        /* キーボードから曲名入力 */
  nc=strlen(song);               /* 曲名の文字数+1(\n) */
  song[nc-1]='\0';               /* 改行(\n)を文字終了(\0)に変更 */
  printf("\n");                  /* 改行 */


  /*----- ファイルの読み込みと検索 ---------*/
  read_file(CD);                   /* CDのデータの読み込み */
  find = find_song(song,CD);       /* 曲名の検索 */

  /*----- 見つからなかった場合のメッセージ ---------*/
  if(find==0){
    printf("お探しの曲はありません。\n");
  }

  return 0;
}

/*==================================================================*/
/*           データのfileの読み込み                                    */
/*==================================================================*/
int read_file(struct cd_data CD[]){
  FILE *rfile;
  int i;

  rfile = fopen("CDdata.txt","r");   /* CDのデータファイルのオープン */

  for(i=0; i<10; i++){
    read_title(i, rfile, CD);     /* タイトル名を読み込む関数のコール */
    read_artist(i, rfile, CD);    /* アーティスト名を読み込む関数のコール */
    read_song(i, rfile, CD);      /* 曲名を読み込む関数のコール */
  }
  
  fclose(rfile);                  /* ファイルのクローズ */

  return 0;

}

/*==================================================================*/
/*           タイトル名の読み込み                                      */
/*==================================================================*/
int read_title(int cdnum, FILE *rfile, struct cd_data CD[]){
  int nc, nc1, nc2;
  char temp, c1[64], c2[64];

  sprintf(c1,"CD%d",cdnum+1);     /* CD番号 CD1, CD2, CD3 ...をc1へ */
  nc1=strlen(c1);                 /* CD番号の文字数 */

  do{                             /* CD番号の検索 */
    fscanf(rfile, "%s",c2); 
    nc2=strlen(c2);
    if(nc1<nc2){
      nc=nc2;
    }else{
      nc=nc1;
    }
  }while(strncmp(c1,c2,nc)!=0);
  
  temp=fgetc(rfile);              /* 空白の読み飛ばし */
  
  sprintf(c1,"Title"); 
  nc=strlen(c1);
  
  do{                             /* Title: の検索 */
    fscanf(rfile, "%s",c2);
  }while(strncmp(c1,c2,nc)!=0);
  
  temp=fgetc(rfile);               /* 空白の読み飛ばし */
  
  fgets(CD[cdnum].title,64,rfile); /* タイトルの読み込み */

  nc=strlen(CD[cdnum].title);
  CD[cdnum].title[nc-1]='\0';     /* 改行(\n)を文字終了(\0)に変更 */
  
  return 0;

}

/*==================================================================*/
/*           アーティスト名の読み込み                                   */
/*==================================================================*/
int read_artist(int cdnum, FILE *rfile, struct cd_data CD[]){
  int nc, nc1, nc2;
  char temp, c1[64], c2[64];

  sprintf(c1,"Artist:");          /* "Artist:"をc1へ格納 */
  nc1=strlen(c1);

  do{                             /* "Artist:"の検索 */
    fscanf(rfile, "%s",c2);
    nc2=strlen(c2);
    if(nc1<nc2){
      nc=nc2;
    }else{
      nc=nc1;
    }
  }while(strncmp(c1,c2,nc)!=0);
  
  temp=fgetc(rfile);                 /* 空白の読み飛ばし */
  
  fgets(CD[cdnum].artist,64,rfile);  /* 空白付きアーティストの読み込み */

  nc=strlen(CD[cdnum].artist);
  CD[cdnum].artist[nc-1]='\0';     /* 改行(\n)を文字終了(\0)に変更 */
  
  return 0;

}

/*==================================================================*/
/*           曲名の読み込み                                           */
/*==================================================================*/
int read_song(int cdnum, FILE *rfile, struct cd_data CD[]){
  int i, nc, nc1, nc2;
  char temp, c1[64], c2[64];

  for(i=0; i<6; i++){              /* 6曲分ファイルから読み込む */
    sprintf(c1,"song%d:", i+1);    /* "song?:"をc1へ格納 */
    nc1=strlen(c1);
    
    do{                            /* "song?:"の検索 */
      fscanf(rfile, "%s",c2);
      nc2=strlen(c2);
      if(nc1<nc2){
	nc=nc2;
      }else{
	nc=nc1;
      }
    }while(strncmp(c1,c2,nc)!=0);
    
    temp=fgetc(rfile);    /* 空白の読み飛ばし */
    
    fgets(CD[cdnum].song[i],64,rfile);  /* 曲名の読み込み */
    
    nc=strlen(CD[cdnum].song[i]);
    CD[cdnum].song[i][nc-1]='\0';     /* 改行(\n)を文字終了(\0)に変更 */

  }

  return 0;

}

/*==================================================================*/
/*           曲名検索                                                */
/*==================================================================*/
int find_song(char song[], struct cd_data CD[]){
  int i,j;
  int nc, nc1, nc2, fnd;

  fnd=0;

  nc1=strlen(song);

  for(i=0; i<10; i++){             /* CD番号のループ */
    for(j=0; j<6; j++){            /* 曲番号のループ */
      
      nc2=strlen(CD[i].song[j]);   /* 曲名の文字数 */
      if(nc1<nc2){                 /* 文字数の多い方で比較 */
	nc=nc2;
      }else{
	nc=nc1;
      }


      /* ---- 曲名が一致したら画面へ出力 ---- */

      if(strncmp(song, CD[i].song[j], nc)==0){
	if(fnd==0){
	  printf("%sが見つかりました。タイトルと曲番は以下の通り。\n", song);
	  fnd=1;
	}
	printf("\t%s    %d\n", CD[i].title, j+1);
      }

    }
  }

  return fnd;     /* 0; 見つからない場合　　1:見つかった場合 */

}
\end{lstlisting}\vspace{5mm}
\end{latexonly}
%
\fbox{実行結果}

\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	探したい曲名?   song1

	song1が見つかりました。タイトルと曲番は以下の通り。
	        title5    1
	        title6    1
 \end{verbatim}
\end{quote}
%
%=====================================================================
\section{レポート}
%=====================================================================
%---------------------------------------------------------------------
\subsection{内容}
%---------------------------------------------------------------------
練習問題のうち、「Lesson 8-1 アンケート集計」と「Lesson 8-2 データをまとめて管理
する1」のプログラムを完成させること。実行の確認ができたならば、それをプリントア
ウトして、レポートとして提出する。さらに、使われている構造体のデータの内容を説明
すること。

自宅のパソコンでプログラムを作っても良い。そして、実行の確認がとれたならば、それをプリント
アウトし、レポートとして提出しても良い。
%
%---------------------------------------------------------------------
\subsection{レポート提出要領}
%---------------------------------------------------------------------
提出方法は、次の通りとする。
% 
\begin{quote}
 \begin{tabular}{ll}
  期限 & 6月2日(木)PM5:00まで \\
  用紙 & A4 \\
  提出場所 & 山本研究室の入口のポスト \\
  表紙 & 表紙を1枚つけて、以下の項目を分かりやすく記述すること。\\
       & \qquad 授業科目名「情報工学概論」\\
       & \qquad 課題名「課題1　構造体」\\
       & \qquad 2E\quad 学籍番号\quad 氏名\\
       & \qquad 提出日\\
  内容 & ソースプログラム(プリントアウトのみ、手書きは不可)\\
       & 使われている構造体の説明
 \end{tabular}
\end{quote}
%
%======= 参考文献 ====================================================
\bibliographystyle{junsrt}
\bibliography{reference} 
%=====================================================================
\end{document}
