%=====================================================================
% 秋田高専 5E 計算機応用 テキスト
%テーマ 練習(5) 関数
%    本テキストの内容
%        ・関数
%          ・関数とは
%          ・関数の作り方と使い方
%          ・データを渡す方法
%          ・戻り値を返す方法
%          ・グローバル変数によるデータの受け渡し
%          ・main関数への引数渡し
%          ・再帰コール
%
% last updated 2005.5.25
%    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}}
\newcommand{\diff}[0]{\mathrm{d}}
\newcommand{\pdiff}[3]{
 \if 1#1 \frac{\partial #2}{\partial #3}
 \else \frac{\partial^{#1} #2}{\partial #3^{#1}}\fi
}
%
\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{htmlonly}
\usepackage{verbatimfiles}
 \providecommand{\lstinputlisting}[2][]{\verbatimlisting{#2}}
\end{htmlonly}
%
\begin{document}
\title{C言語の学習\\標準ライブラリー関数・その他のライブラリー関数}
\author{山本昌志\thanks{独立行政法人　秋田工業高等専門学校　電気工学科}}
\date{2004年6月23日}
\maketitle
%
%=====================================================================
\section{本日の学習内容}
%=====================================================================
本日の内容は、教科書の16章と17章である。コンソール入出力と数学関数について、学習
する。
%
\begin{list}{}{\leftmargin=5zw \rightmargin=2zw \labelsep=1zw
 \labelwidth=5zw \itemindent=0pt}
 \item[\textbf{16章}]\textbf{コンソール入出力関数}
 \item[\textbf{17章}]\textbf{入出力以外の標準ライブラリー関数}
\end{list}
%
%
%=====================================================================
\section{コンソール入出力関数(16章)}
%=====================================================================
コンピューターのもっとも基本的な入出力装置であるキーボードとディスプレイをコンソー
ル(操作卓)と呼ぶ。これらのコンソール入出力を利用した関数のプログラムの学習をする。
とは言え、諸君はこれらの関数はかなり使ってきている。ここではそれら内容を整理して、
これらの使い方の復習を行う。
%---------------------------------------------------------------------
\subsection{標準ライブラリー関数(p.282)}
%---------------------------------------------------------------------
%-------------------------------------------------
\subsubsection{プログラマー作成の関数とライブラリー関数}
%-------------------------------------------------
これまでの学習で、C言語のプログラムは関数の集まりであることが理解できていると思
う。この関数には、プログラマーが作成する関数ともともとコンパイラーが用意している
関数がある。例えば、リスト\ref{prog:my_std_fun}のプログラムでは、
%
\begin{itemize}
 \item \tw{printf()}は、コンパイラーが用意している関数
 \item \tw{main()}と\tw{plus\_print()}はプログラマーが作成した関数
\end{itemize}
である。
%
\lstinputlisting[caption=加算結果を表示。,label=prog:my_std_fun]
{program/my_std_fun.c}
%
%---------------------------------------------------------------
\subsubsection{標準ライブラリー関数とコンパイラー依存のライブラリー関数}
%--------------------------------------------------------------
これまでの学習で、\tw{printf()}や\tw{scanf()}など、コンパイラーが用意している関
数をしばしば使用した。これらの関数を、一般にライブラリー関数と呼ぶ。ライブラリ関
数には、ANSI Cで定められている関数と、それ以外に処理系ごとに特別に用意された関数が
とに分けることができる。前者は、ANSI Cの規格にもとづいたC言語のコンパイラーには
必ず用意されている関数で、\tw{printf()}や \tw{scanf()}、\tw{sin()},
\tw{cos()}などがこれに含まれる。一方、後者はコンパイラーに依存する関数である
\footnote{コンパイラーが異なると、その関数は使えない可能性がある。}。例
えば、マイクロ秒単位でプログラムの実行を停止する関数\tw{usleep()}が、これにあた
る。例えば、リスト\ref{prog:usleep}のプログラムでは、
%
\begin{itemize}
 \item \tw{printf()}は、標準ライブラリー関数
 \item \tw{usleep()}は、コンパイラーに依存するライブラリー関数
\end{itemize}
である。
%
\lstinputlisting[caption=標準ライブラリー関数でない\tw{usleep}を使った例,
label=prog:usleep]{program/usleep.c}
%
%---------------------
\subsubsection{まとめ}
%---------------------
これまでの関数の種類について、まとめると次のようになる。プログラムの構成を関数の
種類から考えると、図\ref{fig:classfication_function}のように分類できる。

\begin{screen}
 \begin{itemize}
  \item C言語のプログラムは関数から構成される。
  \item プログラムで使われる関数は3種類ある。
  \begin{itemize}
   \item プログラマーが作る関数
   \item 全てのC言語のコンパイラーが用意しているANSI Cで規格が決められている標準
	 ライブラリー関数
   \item コンパイラーに依存するライブラリー関数
  \end{itemize}
 \end{itemize}
\end{screen}

本講義では、標準でないコンパイラーが独自に用意した関数を使うことはない。諸君は、
教科書の付録(p.408-466)に書かれている標準ライブラリー関数を使って、プログラムを
作成することに心がけよ。

%
\begin{figure}[hbtp]
 \begin{center}
  \includegraphics[keepaspectratio, scale=1.0]
  {figure/classfication_function.eps}
  \caption{C言語のプログラムで使われている関数の分類}
  \label{fig:classfication_function}
 \end{center}
\end{figure}
%
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]標準ライブラリーにどのようなものがあるか、教科書p.408〜
			 466を軽く眺めよ。
 \end{itemize}
\end{quote}
%
%---------------------------------------------------------------------
\subsection{標準入力と標準出力}
%---------------------------------------------------------------------
コンソール入出力のことを、標準入出力と言うことがある。この標準入出力には、ファイ
ルの入出力先に指定ができ\footnote{C言語では、キーボードやディスプレイもファイル
として取り扱われる。}、そのために名前が付いている。標準入力を\tw{stdin}、標準出
力を\tw{stdout}と言う。これらの関係を、以下に示す。
\begin{center}
 \begin{tabular}{lclcl}
  キーボード & $\rightarrow$ & 標準入力 & $\rightarrow$ & \tw{stdin} \\
  ディスプレイ & $\rightarrow$ & 標準出力 & $\rightarrow$ & \tw{stdout}
 \end{tabular}
\end{center}
%---------------------------------------------------------------------
\subsection{書式付き出力\tw{printf}(p.320)}
%---------------------------------------------------------------------
書式付き出力(\tw{printf})を使うと、任意の形でデータを出力できる。教科書のP.320〜
325を読み、以下の練習問題を実施せよ。
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]円周率を、いろいろなフォーマットで出力せよ。ただし、円
			 周率は\tw{math.h}の中で\tw{M\_PI}で定義されている。それ
			 は、リスト\ref{prog:M_PI}のようにすれば表示できる。
			 \begin{itemize}
			  \item 通常の\tw{\%lf}で表示せよ。
			  \item 小数点以下、3桁で表示せよ。
			  \item 小数点以下、10桁で表示せよ。
			  \item 指数形式で表示せよ。
			 \end{itemize}
  \item[\textbf{[練習2]}]整数の\tw{22446688}を8進数で表示せよ。また、16進数で表
			 示せよ。
  \item[\textbf{[練習3]}]円周率と円周率の2乗の両方を小数点以下、10桁で表示せよ。た
			 だし、2つの数値の間はタブ区切りとする。
 \end{itemize}
\end{quote}
%
%
\lstinputlisting[caption=$\pi$の表示,label=prog:M_PI]{program/M_PI.c}
%
%---------------------------------------------------------------------
\subsection{書式付き入力\tw{scanf}(p.326)}
%---------------------------------------------------------------------
キーボード入力の場合、書式付入力のscanfという関数を使う方法が最も簡単である。こ
の関数の引数は、ポインター\footnote{値を代入する変数のアドレスのこと。}で、キー
ボードからのデータを入れる変数のアドレスを指定する。

データを入力する場合、データを入れた後に、完了を示す\tw{[Enter]}キーを押す。この
\tw{[Enter]}キーをしめす文字'\tw{\textbackslash n}'も読み込まれようとして、悪さ
をすることがある。この、改行コード'\tw{\textbackslash n}'を読み捨てる必要がある。
そのためには、4通りの方法がある。
\begin{itemize}
\item ダミーの文字型変数を用意して、それに改行コード'\tw{\textbackslash n}'読み
      込む方法。
\item 代入を抑止する方法。
\item \tw{fgets}で読み込む方法。
\item \tw{rewind}関数\footnote{ファイル位置指定子を先頭に設定する関数}でバッファー
      の内容を捨てる。
\end{itemize}
私は、最初の方法をよく使いますが、どれを使っても良い。

以下に、実際に、書式入力(\tw{scanf})を使ったキーボード入力を示す。
%
%-------------------------
\subsubsection{1文字の場合}
%-------------------------
キーボードから1文字を入力し、変数\tw{a}に格納する。変数宣言は
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
char a;
char temp;
char dmystr[128];
 \end{verbatim}
\end{quote}
とする。\tw{[Enter]}キーの問題を回避した4通りの入力方法は、以下の通りである。
\begin{quote}
 \begin{itemize}
  \item \tw{scanf("\%c\%c", \&a, \&temp);}
  \item \tw{scanf("\%c\%*c", \&a);}
  \item \tw{scanf("\%c", \&a);\\
	fgets(dmystr, 128, stdin);}
  \item \tw{scanf("\%c", \&a);\\
	rewind(stdin);}
 \end{itemize}
\end{quote}
%
%-------------------------
\subsubsection{文字列の場合}
%-------------------------
キーボードから文字列を入力し、配列\tw{a[]}に格納する。変数宣言は
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
char a[128];
char temp;
char dmystr[128];
 \end{verbatim}
\end{quote}
とする。\tw{[Enter]}キーの問題を回避した4通りの入力方法は、以下の通りである。配
列名はアドレスを示すので、\tw{\&}をつける必要はない。文字列の中に空白があると
\tw{scanf()}は使えない。空白はデータの区切りと解釈さ留殻である。そのときは、
\tw{gets()}を使う。
\begin{quote}
 \begin{itemize}
  \item \tw{scanf("\%s\%c", a, \&temp);}
  \item \tw{scanf("\%s\%*c", a);}
  \item \tw{scanf("\%s", a);\\
       	fgets(dmystr, 128, stdin);}
  \item \tw{scanf("\%s", a);\\
       	rewind(stdin);}
 \end{itemize}
\end{quote}
%
%-------------------------
\subsubsection{整数(10進数)の場合}
%-------------------------
キーボードから整数を入力し、変数\tw{a}に格納する。変数宣言は
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
int a;
char temp;
char dmystr[128];
 \end{verbatim}
\end{quote}
とする。\tw{[Enter]}キーの問題を回避した4通りの入力方法は、以下の通りである。
\begin{quote}
       \begin{itemize}
       \item \tw{scanf("\%d\%c", \&a, \&temp);}
       \item \tw{scanf("\%d\%*c", \&a);}
       \item \tw{scanf("\%d", \&a);\\
       	fgets(dmystr, 128, stdin);}
       \item \tw{scanf("\%d", \&a);\\
       	rewind(stdin);}
\end{itemize}
\end{quote}
       
%
%-------------------------
\subsubsection{倍精度実数の場合}
%-------------------------
キーボードから倍精度実数を入力し、変数\tw{a}に格納する。変数宣言は
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
double a;
char temp;
char dmystr[128];
 \end{verbatim}
\end{quote}
とする。\tw{[Enter]}キーの問題を回避した4通りの入力方法は、以下の通りである。
\begin{quote}
       \begin{itemize}
       \item \tw{scanf("\%lf\%c", \&a, \&temp);}
       \item \tw{scanf("\%lf\%*c", \&a);}
       \item \tw{scanf("\%lf", \&a);\\
       	fgets(dmystr, 128, stdin);}
       \item \tw{scanf("\%lf", \&a);\\
       	rewind(stdin);}
\end{itemize}
\end{quote}
       
%
%-------------------------
\subsubsection{2個以上読み込むの場合}
%-------------------------
キーボードから2個の倍精度実数を入力し、変数\tw{a}と\tw{b}に格納する。変数宣言は
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
double a, b;
char temp;
char dmystr[128];
 \end{verbatim}
\end{quote}
とする。\tw{[Enter]}キーの問題を回避した4通りの入力方法は、以下の通りである。
\begin{quote}
     入力データの区切りは、空白あるいはtab、改行です。
       \begin{itemize}
       \item \tw{scanf("\%lf\%lf\%c", \&a, \&b, \&temp);}
       \item \tw{scanf("\%lf\%lf\%*c", \&a, \&b);}
       \item \tw{scanf("\%lf\%lf", \&a, \&b);\\
       	fgets(dmystr, 128, stdin);}
       \item \tw{scanf("\%lf\%lf", \&a, \&b);\\
       	rewind(stdin);}
\end{itemize}
\end{quote}

%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]2つの整数をキーボードから読み込み、その和と差、積、商を
			 表示せよ。
  \item[\textbf{[練習2]}]整数と倍精度実数をキーボードから読み込み、積を指数形式
			 と小数点以下8桁で表示せよ。
 \end{itemize}
\end{quote}
%
%=====================================================================
\section{入出力以外の標準ライブラリー関数(16章)}
%=====================================================================
%---------------------------------------------------------------------
\subsection{数学関数(p.351)}
%---------------------------------------------------------------------
教科書p.351の表に書かれているような数学関数を使うときには、ヘッダーファイル
\tw{<math.h>}を以下のように書いて、インクルードする必要がある。
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
#include <math.h>
 \end{verbatim}
\end{quote}

さらに、さらにコンパイルする場合には、\tw{libm}というライブラリーをリンクして、
実行ファイルを作成する必要がある。このライブラリーが数学関数の実行ファイルである。
数学関数が使われているソースコードをコンパイルするときには、
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
gcc -lm -o 実行ファイル名 ソースファイル名
 \end{verbatim}
\end{quote}
のようにする。
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]倍精度実数を読み込み、以下の関数の値を指数形式と小数点
			 以下、8桁で表示せよ。
			 \begin{itemize}
			  \item 三角関数($\sin, \cos, \tan$)
			  \item 指数関数
			  \item 自然対数関数と常用対数関数
			  \item 平方根と立方根
			 \end{itemize}
  \item[\textbf{[練習2]}]$\pi^\pi$を計算して、指数形式と小数点以下、8桁で表示せよ。
 \end{itemize}
\end{quote}
%
%---------------------------------------------------------------------
\subsection{数学に関係すること諸々}
%---------------------------------------------------------------------
%---------------------
\subsubsection{複素数}
%---------------------
以前のC言語は複素数がサポートされていなかった。数値計算をする場合、複素数が使え
ないとかなり不便を強いられる。そのため、複素数が使える FORTRAN から抜け出せない
人が多くいた。新しいC言語では、複素数がサポートされるようになってきている。

その使い方は、教科書のp.471を参考にして欲しい。
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]$1+i$の複素数の絶対値を計算せよ。複素数の絶対値
				を計算する関数は\tw{cabs()}である。
  \item[\textbf{[練習2]}]$2+i\pi/4$の三角関数の値を計算せよ。複素数の三角
				関数は、\tw{csin(), ccos(), ctan()}を使う。
 \end{itemize}
\end{quote}
%
%-------------------
\subsubsection{乱数}
%-------------------
乱数も数値計算ではよく使われる。乱数の発生については、教科書のp.440(\tw{rand})と
p.449(\tw{srand()})を見よ。
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]諸君が使っているシステムの乱数発生のプログラムで、
				発生できる最大の乱数を調べよ。
  \item[\textbf{[練習2]}]乱数の一様性を調べたい。どうすれば良いか考えよ。
 \end{itemize}
\end{quote}
%
%======= 参考文献 =====================================================
\bibliographystyle{junsrt}
\bibliography{reference} 
%=====================================================================
\end{document}
