ATMELのAT-Tiny26,ATmega,R8Cなどのワンチップマイコン,C言語,JAVAなどのプログラミング言語の入門のためのページです.サンプルプログラムを中心に紹介します.他にもLinixや数学ソフトなどの紹介も行います.

このブログを検索

あなたは 番目のお客様です.

2008年6月23日月曜日

Visual C++ Express Editionを用いたプログラミングメモ

以下は軽量で最低限の機能(授業で使う基本的なC言語のプログラミングなど)を使う例です.
Visual C++ はC:\Program Filesに,C言語のプログラムはc:\testに作成するものとする.使用したパソコンはWindowsXP.
MicrosoftのVisual C++ Express Edition のサイトにアクセスする.Visual C++ Express Edition をWeb インストール (ダウンロード)する.このソフトを実行しますかと聞かれたら,実行をクリックする.
ライセンスに同意する.
インストールオプションのチェックボックスを全部空にする.
Visual C++ Express Editionがインストールされる.

実行方法
すべてのプログラム>>アクセサリ>>コマンドプロンプト
でコマンドプロンプトの窓を開く.
cdコマンドでC言語のソースプログラムが入っているフォルダに移動する.
Visual C++ Express Editionをインストールしたディレクトリの下のVCフォルダに含まれているバッチファイルの「vcvars32.bat」を実行する.
"C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat"
(「vcvars32.bat」のアイコンをコマンドプロンプトにドラックしても良い.)
cl test.cでコンパイルするとtest.exeが作られる.
test.exeをタイプしてプログラムを実行する.

2008年6月18日水曜日

Fedora,Vine,Debian,KnoppixでLinux一本勝負?

KnoppixをUSBにインストールする方法(2010.08.19)
CD版knoppixのisoファイルをダウンロードする.
CDライティングソフトで,knoppixのisoファイルをCDに書き込む.
PCにCDをセットし,立ち上げ前にBIOSの設定を,HDよりCDを優先させると
CD版Knoppixが起動する.
1GBのUSBメモリを接続する.
システムツールメニューにInstall Knoppix to flash diskがあるので,
インストール先にUSBを選択して実行すれば出来上がり.

いくつかのLinaxの比較(2008)
最近のLinuxの状況を知らなかったので,いくつかのLinaxをHDにインストールして,日本語環境,OpenOfficeの使い勝手などを調べました.KnoppixのみCD-ROMから起動します.
使用したマザーボード:AOpen s651m
メモリ:256M

CDの作り方
CDの作り方はみんな同じ.CdManipulatorでCDにisoファイルを焼く.(書き込めばよい)
CdManipulatorをダウンロードし解凍する.インストールしなくてもCdManipulator.exeをダブルクリックで実行できる.









下の左から二番目のCDのマスタリング又はイメージのマスタリングを選択する.
トラックリストを開き,トラック>>isoファイルの挿入を選択し,ダウンロードしたisoファイルを選ぶ.あとはCDへ書き込みボタンを押すだけで,CDが作れる.

いずれも設定など特に問題なく,インストールおよび起動できました.

Debian GNU/Linux 4.0
Debianはそのままでは日本語が使えなかった. 原因究明を断念し,引き続きFedora9を試す.
Fedora9
日本語環境がデフォルトで準備されていない以外は,OpenOfficeなど必要なものが揃っている.
FedoraはインストールCDが3枚になった.
Fedora-9-i386-disc1.iso
Fedora-9-i386-disc2.iso
Fedora-9-i386-disc3.iso
HDが5Gぐらい埋まった.もはやWindowsに比べて軽いOSというイメージは無い.
そのままでは日本語が使えなかったが比較的簡単に日本語化が可能.
端末を開き,スーパーユーザとなり次の命令を実行する.
yum groupinstall 'Japanese Support' --exclude=xorg-x11-server-Xorg

システムメニュー>>設定>>ユーザ向け>>入力メソッドを選択し
入力メソッド設定ツールを実行する.
入力メソッド設定ツールウィンドウの入力メソッドの機能を有効にするのチェックボックスをチェックし,入力メソッド設定ツールを閉じる.

Vine4.2
Vineはそのまま日本語が使える.
Openofficeは後でインストールする必要がある.Synapticというインストールソフトを使えば良い.

KNOPPIX5.3
OpenOfficeなど最低限必要なものが揃っている.
KNOPPIX5.3(日本語版),CDから簡単にLinuxが使えるのは便利だが,CDドライブが回り続けるのはちょっと不安である.やはりUSBメモリにインストールしたものが良いかもしれない.

2008年6月12日木曜日

Windows版 Mathematicaの使い方
(覚え書き)


Windowsでは式を入力してShiftキーを押しながらEnterキーを押す.(Shift+Enter)

Mathematicaの基礎知識
式を入力すると入力(In)に対する結果(Out)が表示される.

関数は[]でくくる.関数の最初は大文字である.
よく使う定数
E(自然対数の低),PI(円周率),I(虚数),Infinity(無限大)

たとえば x^3 + y^3(Shift+Enter)で式が記憶される.
この式の因数分解を行いたい場合
Factor[%]
ここで%は直前の式をあらわす
今度は,上の結果を展開したい場合
Expand[%]
でもとに戻る.

方程式の解法
Solve[4x-1==0,x]
Solve[a x^2+b x+c==0,x]
(注)Solve[ax^2+bx+c==0,x] とすると正しい結果が出ない.これはMathematicaではaxやbxも変数とみなすためである.異なる変数の間にはスペースが必要.スペースの代わりに*を使っても良い.
Solve[a x^2+b x+c==0,x]
Solve[{x-4y==-2,2x+y==5},{x,y}]
上の問題は逆行列を使った行列演算でも解くことができる.
A={{1,-4},{2,1}}
Y={-2,5}
Inverse[A].Y

関数の極限
Limit[(1+1/x)^x,x->Infinity]
矢印や無限大は,右のリストから選んでもよい

式の微分
x^3-4x^2+Exp[-x^2]+Sin[2x]
D[%, x]

微分方程式
DSolve[{x''[t]+x[t]==0,x[0]==1,x'[0]==0},x[t],t]
DSolve[{x''[t]+x'[t]+x[t]==0,x[0]==1,x'[0]==0},x[t],t]
DSolve[{x''[t]+x'[t]+x[t]==2Cos[t],x[0]==1,x'[0]==0},x[t],t]
Plot[式,{t,a,b}]で結果をグラフ表示することも可能である.a,bは横軸の範囲.

式の積分
1/x-4x^2+Exp[-x]+Sin[2x]
Integrate[%, x]

定積分
Integrate[Exp[-x^2],{x,0,1}]
式の値を数値で与えるには
N[%]
表示桁数を指定することもできる.
N[%,100]
N[]を忘れた場合,とりあえず1.0を式に掛けておいてもよい.
例えばIntegrate[Exp[-x^2],{x,0,1}]*1.0

複素数の絶対値と偏角
z = (1 + I)/Sqrt[2]
Abs[z]
Arg[z]

行列
行列やベクトルの定義
A={{1,-4},{2,1}}
B={{a,b},{c,d}}
C={-2,5}
行列の演算
A.B (内積)
B.B
Cross[A,B] (外積)
A^3
逆行列
Inverse[A]
行列式
Det[A]
行列の固有値と固有ベクトルを求める.
A={{3,-5,-5},{-1,7,5},{1,-9,-7}}
Eigenvalues[A]
Eigenvectors[A]
固有値と固有ベクトルが条件を満たすか確認する
固有値-2に対する固有ベクトルがB = {1, -1, 2}のとき
A.B と -2Bが同じ結果になる
A={{2,0,-1},{0,2,0},{-1,0,2}}

グラフ描画
Plot[Sin[4x] Exp[-x^2],{x,-5,5}]
ParametricPlot[{Sin[5t],Cos[3t]},{t,0,2Pi}]
ParametricPlot3D[{Sin[15t], Cos[15t], t}, {t, 0, 2Pi}, PlotPoints -> 400]
Plot3D[Exp[-(x^2 + y^2)], {x, -5, 5}, {y, -5, 5}]
ContourPlot[Exp[-(x^2 + y^2)], {x, -5, 5}, {y, -5, 5}]
グラフの上下が削られる場合には以下のようにオプションを追加する.
Plot[Sin[10x] Exp[-x^2], {x, -5, 5}, PlotRange -> {-1, 1}]
Plot3D[Exp[-(x^2 + y^2)], {x, -5, 5}, {y, -5, 5}, PlotRange -> All]
Plot3D[Exp[-(x^2 + y^2)], {x, -5, 5}, {y, -5, 5}, PlotRange -> {0,1}]
グラフを細かく(精密に)書きたい場合には,Plotpointsで関数のサンプリング数を変える.
Plot3D[Exp[-(x^2 + y^2)], {x, -5, 5}, {y, -5, 5}, PlotRange -> All,PlotPoints->100]

関数の定義
f[x_]:=x^2 Sin[x]
Plot[f[x],{x,-10,10}]
変数への値の代入
x=10
x^2

最も簡単な形式を返す
FullSimplify[1/(Sqrt[2] - 1)]

値のクリア
Remove["x"]

2008年6月10日火曜日

C言語のプログラミング入門


C言語の学習を行うための自習テキストです.例題を通して配列までの範囲を学習できます.

プログラミングⅠ資料No.1
第1回

今日の課題
簡単なCのプログラムを実行してみる.

例題1
C言語では,スペース,タブ,改行は適当に入れて構いません.プログラムの内部が見やすいよう右にずれていますが,Tabキーを使っています.ずらさなくても,スペースを入れても構いません.コンパイラが全角スペースを認識できませんので,全角スペースを入れるとプログラムが動きません.
#include <stdio.h>
int main(void)
{
printf("ABC");
}
(注)プログラムで全角文字が使えるのは,コメントや文字列のみで,それ以外の場所に全角文字を入れるとエラーがでます.

Cygwinの使い方
CygwinのアイコンをWクリックする.
gcc test1.c とタイプするとa.exeというファイルができる.
バグがある場合には,エラーメッセージが出る.
./a.exeとタイプするとプログラムが動く. (./ の意味は?)
exitとタイプするとCygwinが終了する
Cygwinで最低限知っておいた方が良いコマンド
↑:前の命令を呼び出す
↓:後の命令を呼び出す
ls:ファイルのリストを出す
ls -l:ファイルのリストを詳細情報付で出す
その他知っておいた方がよいコマンド
(mv,cp,rm,pwd,mkdir,cd,cat,vi)
cygwinは一度開いたら授業の間ずっと開きっぱなしで構いません.
このウェブの画面とメモ帳とCygwinを見やすいように並べてください.

例題2
#include <stdio.h>
int main(void)
{
int i,j=0;
for(i=1;i<=10;i++)j=j+i;
printf("%d\n",j);
}

思ったとおりに動かない場合
ファイルを右クリックし「編集」で,プログラムを確認し修正し,上書き保存し,
Cygwinで再度コンパイル>実行

例題3
#include <stdio.h>
#include <math.h>
int main(void)
{
int i;
float x;
for(i=0;i<10;i++){
x=sqrt(1.0*i);
printf("%d %f\n",i,x);}
}

例題4
/*鶴亀算,足は合計26本,全部で10匹*/
#include <stdio.h>
int main(void)
{
int turu,kame,ashi;
for(turu=0;turu<=10;turu++){
kame=(10-turu);
ashi=turu*2+kame*4;
if(ashi == 26)printf("鶴は%d匹 亀は%d匹\n",turu,kame);
}
}

例題5
#include <stdio.h>
int main(void)
{
char a;
a='A';
printf("%c\n",a);
putchar('B');
putchar('B'+5);
printf ("\n");
puts("xyz");
printf ("\n");
puts("abc");
}

本日のミニプログラム
#include <stdio.h>
int main(void)
{
printf("Hello");
}

Unix上のエディタviの使い方
起動  vi [ファイル名 ...]
指定されたファイルが無い場合は新規作成モードとなる.ファイル名にはワイルドカード('*', '?'など)も使用可能.
編集モード タイプした文字がそのまま反映される.Escでコマンドモードへ戻る.
コマンドモード 以下に示す各種コマンドが使える.起動直後はこのモード.(iで編集モードへ)
コマンドモードにおける各種コマンド (各コマンドの前に数字を打つと,その回数分だけ同じ動作を繰り返す)
:q セーブせずに終了
:q! 変更した行もセーブせずに終了
:w セーブするが終了しない.
:wq セーブして終了
編集モードへ移るためのキー
i 現在のカーソル位置から挿入.
R 現在のカーソル位置から置換.
A 現在行の末尾に追加.
O 現在行の前に行挿入.
o 現在行の次に行挿入.
カーソル移動キー h(←) 左  j(↓) 上  k(↑) 下  l(→) 右
0 行頭へ
$ 行末へ
[Enter] 次の行の先頭へ
w 次の単語へ
b 前の単語へ
ctrl + f 次画面へ
ctrl + b 前画面へ
1G 文頭へ
G 文末へ
nnG nn行目へ
変更キー
x 1文字削除
dd 1行削除(カット)
cw(Change Word) 1語変更
c$ カーソル位置から行末まで変更
dw(Delete Word) 1語削除
d$ カーソル位置から行末まで削除
検索 /正規表現 前方検索
?正規表現 後方検索
n 次の候補
N 前の候補
カット/コピー&ペースト
yy 1行コピー
dd 1行カット
p ペースト(張り付け)
その他 .(ドット) 直前の変更操作の繰り返し
u 直前の変更操作の取り消し(何回でも戻れる)
gccのオプション
-Wunused 未使用の変数をチェック
-Wreturn-type 関数の返却値と型の整合性
[例]main関数の終了が exit関数,或いは return文でないと次の warning が出る.
  control reaches end of non-void function
-Wformat printf や scanf の変換指定子のチェック
-Wimplict 関数や引数の暗黙的宣言のチェック
-Wuninitialiezed  変数の初期化チェック(但し,最適化用オプション利用時)
-Wall 上記オプションを含む warning用オプションのすべて.
どのオプションが含まれるかはコンパイラのマニュアルを.
-O 処理の最適化.最適化については,他のオプション -O2 などあり.
どのような最適化が行われるかはコンパイラのマニュアルを.
-o 実行ファイル名を指定.
-c オブジェクトファイルの生成.
-S 翻訳処理のみ.アセンブリ言語ファイルが生成される.

Cygwinのインストール
Cygwinのサイトにアクセスする. http://www.cygwin.com/
Install or update now!をクリックする.
ファイルのダウンロード>実行を選択する.
次へをクリックしてInstall from Internetを選択する.
Choose A Download Siteで日本のサイトFtp://XXXXXXX.jpを選ぶとダウンロードが早い.
このままインストールするとgcc(Cコンパイラ)がインストールされないので,
SelectPackagesの画面でDevelDefaultをクリックする
Packagesのリストの中にgcc-core:C compilerというのがあるのでチェックを入れる.
あとは次へを続けてクリックしていけばCygwinがインストールされてgccが使えるはずです.

プログラミングⅠ資料No.2
今日の課題
文字の表示.コメント.特殊文字の表示.実行結果のファイルへの出力方法.実行結果の送信メールへの取込み方法.

作成ファイルの整理
作成ファイルには以下の例のように,授業の回数や演習の日付で系統的な名前をつけておきましょう.
例 2007年5月11日のプログラム 0511a.c 0511b.c 0511c.c

Cygwin環境のコンパイルと実行
「UNIX環境ではfccを使いコンパイルする」と書かれているものもありますが,Cygwin環境ではgccを使います.プログラムの実行は ./a.exe です.(./は「今見ているフォルダの中からa.exeを探しなさい」という意味があります)


例題
/* 学籍番号xxxx 氏名xxxx 日付xxxx
例題 */

#include <stdio.h>
int main(void)
{
printf("学籍番号\t氏名(読み)\n");
printf("xx年xx月xx日\n");
printf("今日はよい天気です\n");
}
プログラムは,半角スペースやTabを使って見やすいようにずらしてください.(インデント)

コメント
プログラム中で/*から始まって*/で終わるまでの部分は,実行されません.(コメント)
またC++では文の//より右側はコメントとして実行されません.
(注意)全角文字はコメント(/*...*/)文字列("...")以外では使えません.まず全角以外の編集をしてから,最後に全角の部分を追加するのが良いでしょう.

拡張表記
printf("")でダブルクオーテーションに囲まれた中に,以下の記述を入れると,改行などの表示が出来ます.
\n:改行 \t:タブ \\:「\」円記号
\0:ヌル文字 \":「"」ダブルクォテーション

注 ヌル文字は,文字列の終端であることを表す特殊な文字で表示されません.
\n や\tのように/の逆の文字(バックスラッシュ)を使っている本もありますが,実際には半角の円記号"\"を使ってください.

実行結果のファイルへの出力方法と表示のコピー
リダイレクトを使うと結果が画面に表示されるのではなく,新しいファイルができ書き込まれます.
./a.exe>output.txt
.txtはテキストファイルを示す拡張子です.
ウィンドウズ上で,作成したテキストファイルをワードパッドで開くことができます.
またCygwinでは上のバーを右クリックし編集>範囲指定で範囲を指定し,編集>コピーで,指定した範囲をコピーし,ワードやメールに貼り付けることができます.

練習問題1 例題で文字列から\nを除いて実行してみましょう.
練習問題2 例題でprintf文の最後のセミコロン;を除いて実行してみましょう.
練習問題3 例題を次のように書き換え実行してみましょう.
#include <stdio.h>
int main(void)
{
printf
("hello , world ");
}

練習問題4例題と以下のプログラムの実行結果を比較しましょう.
#include <stdio.h>
int main(void)
{
printf("hello");
printf(" , ");
printf("\n");
}
printf()で表示を行う場合には,最後に改行\nを入れましょう.

例題
#include <stdio.h>
int main(void)
{
printf("C言語では\"\\n\"は改行をあらわします\n");
printf("\\nがないと");
printf("改行されません");
}

Cygwinでは日本語を表示する場合に,文字が化けることがあります.

本日のミニプログラム

#include <stdio.h>
int main(void)
{
printf("\tTab"); /*Tab*/
}


プログラミングⅠ資料No.3
今日の課題
変数,値の型,データの表示printf(),データの読み込みscanf()

例題3-1
#include <stdio.h>

int main(void)
{
int math,phys,wa,heikin;
math=60;
phys=70;

wa=math+phys;
heikin=wa/2;

printf("点数の和=%d\n",wa);
printf("平均=%d\n",heikin);
}

math,phys,wa,heikinは整数型の変数です.変数の名前は自分で決められます.
math=60;は変数mathに60を代入します.
wa=math+phys;は変数mathの値と変数physの値を足した値を変数waに代入します.
heikin=wa/2;は変数waの値を2で割った値を変数heikinに代入します.

変数の定義と型について
C言語では,プログラムの中で値を保存するのに変数を使います.最初に使いたい変数がどのような型(整数,実数など)なのかを決めておく必要があります.これを変数の定義と呼びます.

int i,j; /*iとj は整数型の変数である*/
double x; /*xは倍精度の実数である */
変数の定義と同時に,変数に値を代入することもできます.
int k=3; /*kは整数型の変数である またkに3を代入する*/
通常i,j,k,m,nなどの変数は,整数型の変数として使うことが多いです.
C言語では,次のような変数が使えます.
整数型 int 実数型 float 倍精度実数型 double 文字型 char

関数printf()について
この関数を用いて標準出力(画面)にデータ(文字列)を表示できます.
%dは整数型の書式指定子と呼ばれ,後に続く整数の値が%dに置き換わって表示されます.

練習問題3-1
例題3-1で赤字の部分を1行に置き換えることができます.
heikin=(wa=(math=60)+(phys=70))/2;
実行して,命令の意味について考えてみよう.

練習問題3-2
例題3-1で変数の定義と,変数への値の代入を同時に行うプログラムに書き替えよう.

例題3-2
#include <stdio.h>

int main(void)
{
int a,b,c;
printf("Aの点数?\n");
scanf("%d",&a);
printf("Bの点数?\n");
scanf("%d",&b);
printf("Cの点数?\n");
scanf("%d",&c);

printf("A,B,Cの和=%d\n",a+b+c);
printf("平均=%d\n",(a+b+c)/3);
}
3,4,5と入力した場合と3,4,4と入力した場合の結果を比べてみましょう.

関数scanf()について
scanf("%d",&x)の文では,整数型の書式指定子%dが使われているので,キーボードに入力した値が,整数として変数xに代入されます.
scanf("%f",&a)では,実数型の書式指定子%fが使われているので,キーボードに入力した値が,実数として変数aに代入されます.
実数型でprintf(),scanf()を使う場合には,%dではなく,%fになることに注意しましょう.
scanf()では変数の先頭に&(アンパッサンド)が付くことに気をつけてください.また変数の型と書式指定子%○が一致しなくてはいけません.

例題3-3
#include <stdio.h>
int main(void)
{
float a,b,h,s;
printf("台形の面積を求めます\n");
printf("上底?\n");
scanf("%f",&a);
printf("下底?\n");
scanf("%f",&b);
printf("高さ?\n");
scanf("%f",&h);
s=(a+b)*h/2.0;
printf("台形の面積=%f\n",s);
}
実数の表示について
実数型の書式指定子は%fなのでprintf("台形の面積=%f\n",s);のように,実数を表示することができます.
printf()を使って実数型の値を表示する場合,printf("%10.5f\n",x); のように全桁数(ピリオドの前の数)と小数点以下の桁数(ピリオドの後の数)を指定することができます.桁の指定は%とfにはさまれる事に注意しましょう.指定しないで%fとした場合には,デフォルト(コンパイラで定義された状態)で表示されます.
大文字と小文字について
プログラムの中で同じアルファベットでも大文字と小文字は別の文字として扱われます.またscanf,include,intなどのC言語で決められた単語で大文字と小文字を間違えるとエラーになります.
次のプログラムでは変数aとAが別の変数として扱われています.
#include <stdio.h>
int main(void)
{
int a,A;
scanf("%d",&a);
A=a*3;
printf("%d",A);
}

演算による結果
整数同士,実数同士の演算では,結果の値の型は変わりません.整数と実数が混ざった演算では,結果の型は実数になります.
また整数同士の乗除では小数点以下が切り捨てられることに注意しましょう.

例題
#include <stdio.h>
int main(void)
{
int a,b,c;
float d;
scanf("%d",&a);
scanf("%d",&b);
c=a+b;
d=c/2.0;
printf("%d\n",c);
printf("%f\n",d);
}

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int x,y; /*変数の定義*/
scanf("%d",&x); /*入力*/
y=x*2; /*代入*/
printf("%d",y); /*出力*/
}
printf()は値を表示することができる.scanf()は,入力した値の格納先を示す.(変数の前に&が必要)


プログラミングⅠ資料No.4
今日の課題
文字型変数,文字の入出力getchar(),putchar(),色々な演算(z=5%2,x*=3,i++など)

整数と実数が混ざった計算の注意
整数と実数が混ざった計算では,頭で考えたとおりの結果にならないことがあるので注意しましょう.例えば
1/9.0=0.1111111
0.1111111*9=0.9999999 この値を整数に変換すると0になる!
次の例でも結果が0になることがあります.
int i;
float x;
x=1/100.0;
i=x*100.0;
printf("%d\n",i);

例題4-1
/*小文字を大文字に変換する */
#include <stdio.h>
int main(void)
{
char moji;
printf("小文字");
scanf("%c",&moji);
moji=moji-'a'+'A';
printf("%c\n",moji);
}

文字とASCIIコード
'a','@','6'のようにシングルクオーテーション(')で囲まれたものは文字(文字型の値)です.文字は計算機の中では数値として扱われるので,足し算や引き算が出来ます.文字と数値との関係を決めた代表的なものに,ASCII(アスキーと呼ぶ)コードがあります.付録に,ASCIIコードを示します.
"abc","文字"のようにダブルクオーテーション(")で囲まれたものは文字列です.'a'と"a"は違うものなので気をつけてください.

文字型の変数と文字の入出力
charは文字型の変数を定義します.文字型の変数は整数として扱うことができます.上の例題で「char」を「int」に変えて実行してみましょう.scanf()やprintf()で文字を入出力する場合には,%cの書式指定子を使います.文字の入出力には,getchar()とputchar()も使えます.

練習問題4-1
例題では文字'b'がどのように文字'B'に変換されるかを考えて,今度は大文字を読み取り小文字に変換するプログラムに修正してください.

練習問題4-2
moji=getchar();で1文字を変数mojiに読み込むことができます.putchar(moji);で変数mojiの値(1文字)を表示することができます.
getchar()とputchar()を使って例題4-1を書きかえてください.

練習問題4-3
次のプログラムを実行しましょう.
(注)for(i=0;i<128;i++)...は変数iの値を0から127まで繰り返すという処理ですが,詳しくは後ほど勉強します.
#include <stdio.h>
int main(void)
{
int i;
for(i=0;i<128;i++){
printf("%d\t",i);
putchar(i);
putchar('\n');
}

}

例題4-2
#include <stdio.h>
int main(void)
{
int x;
float y;
x=10;
x++;
printf("%d\n",x);
x=20;
x%=7;
printf("%d\n",x);
y=8.0;
y/=2.0;
printf("%f\n",y);
y/=2.0;
printf("%f\n",y);
y/=2.0;
printf("%f\n",y);
}

剰余算
%は整数を整数で割ったときの余りを求める演算です.(x=20%6;)書式指定子の%とは違うので気をつけましょう.

自己代入型演算子,インクリメント,デクリメント
変数に演算処理を行いその結果を同じ変数に代入するものを自己代入型演算子とよびます.また変数の値を一つ増やすのがインクリメント,一つ減らすのがデクリメントです.
加 x=x+a; x+=a; (x++ x=x+1;)
減 x=x-a; x-=a; (x-- x=x-1;)
乗 x=x*a; x*=a;
除 x=x/a; x/=a;
剰余 x=x%a; x%=a;

練習問題4-4
例題4-1を自己代入型演算子を使ったプログラムに書き換えましょう.

一歩進んで
インクリメント,デクリメントでは,演算子が変数の前にある書き方(前置型)と,変数の後ろある書き方(後置型)があります.i++ ++i j=i++ j=++i
前置型は全体の式の計算(代入)より先に,インクリメント,デクリメントを行います.

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int x=2;
x+=3;
printf("%d",x);
}


ASCIIコード 10進数と16進数の対応についてもよく理解しておきましょう.
文字 10進 16進 文字 10進 16進 文字 10進 16進 文字 10進 16進
NUL 0 0x00 SP 32 0x20 @ 64 0x40 ` 96 0x60
SOH 1 0x01 ! 33 0x21 A 65 0x41 a 97 0x61
STX 2 0x02 " 34 0x22 B 66 0x42 b 98 0x62
ETX 3 0x03 # 35 0x23 C 67 0x43 c 99 0x63
EOT 4 0x04 $ 36 0x24 D 68 0x44 d 100 0x64
ENQ 5 0x05 % 37 0x25 E 69 0x45 e 101 0x65
ACK 6 0x06 & 38 0x26 F 70 0x46 f 102 0x66
BEL 7 0x07 ' 39 0x27 G 71 0x47 g 103 0x67
BS 8 0x08 ( 40 0x28 H 72 0x48 h 104 0x68
HT 9 0x09 ) 41 0x29 I 73 0x49 i 105 0x69
NL* 10 0x0a * 42 0x2a J 74 0x4a j 106 0x6a
VT 11 0x0b + 43 0x2b K 75 0x4b k 107 0x6b
NP 12 0x0c , 44 0x2c L 76 0x4c l 108 0x6c
CR 13 0x0d - 45 0x2d M 77 0x4d m 109 0x6d
SO 14 0x0e . 46 0x2e N 78 0x4e n 110 0x6e
SI 15 0x0f / 47 0x2f O 79 0x4f o 111 0x6f
DLE 16 0x10 0 48 0x30 P 80 0x50 p 112 0x70
DC1 17 0x11 1 49 0x31 Q 81 0x51 q 113 0x71
DC2 18 0x12 2 50 0x32 R 82 0x52 r 114 0x72
DC3 19 0x13 3 51 0x33 S 83 0x53 s 115 0x73
DC4 20 0x14 4 52 0x34 T 84 0x54 t 116 0x74
NAK 21 0x15 5 53 0x35 U 85 0x55 u 117 0x75
SYN 22 0x16 6 54 0x36 V 86 0x56 v 118 0x76
ETB 23 0x17 7 55 0x37 W 87 0x57 w 119 0x77
CAN 24 0x18 8 56 0x38 X 88 0x58 x 120 0x78
EM 25 0x19 9 57 0x39 Y 89 0x59 y 121 0x79
SUB 26 0x1a : 58 0x3a Z 90 0x5a z 122 0x7a
ESC 27 0x1b ; 59 0x3b [ 91 0x5b { 123 0x7b
FS 28 0x1c < 60 0x3c \ 92 0x5c | 124 0x7c
GS 29 0x1d = 61 0x3d ] 93 0x5d } 125 0x7d
RS 30 0x1e > 62 0x3e ^ 94 0x5e ~ 126 0x7e
US 31 0x1f ? 63 0x3f _ 95 0x5f DEL 127 0x7f



プログラミングⅠ資料No.5
今日の課題
色々な型の変数(char,int,float,double),if文

例題5-1
標準入力からアルファベットの小文字を1文字読み込み,何番目の文字かを示すプログラム
#include <stdio.h>
int main(void)
{
char komoji;
printf("アルファベットの小文字を入力してください ->");
komoji = getchar();
printf("この文字は %d番目です.\n", komoji - 96);
printf("この文字は %d番目です.\n", komoji - 'a' + 1);
}
文字型の変数は,整数型の変数と同じように加減などの演算ができます.

例題5-2
文字型変数の扱い方と表示の例題
#include <stdio.h>
int main(void)
{
char a1,a2;
int b1,b2;
a1=65;
b1='A';
printf("文字型変数:65 ->文字%c\t65 ->数字%d\n",a1,a1);
printf("整数型変数:'A' ->文字%c\t'A' ->数字%d\n",b1,b1);
a1+=5;
b1+=5;
printf("文字型変数:65+5 ->文字%c\t65+5 ->数字%d\n",a1,a1);
printf("整数型変数:'A'+5 ->文字%c\t'A'+5->数字%d\n",b1,b1);
a2=b2=127;
printf("a2=%d\tb2=%d\n",a2,b2);
a2++;
b2++;
printf("a2=%d\tb2=%d\n",a2,b2);
}
文字型変数も整数型変数も同じように使えますが,違いは扱える数の範囲です.文字型変数(8ビット)の下限は-128,上限は127になっています.

練習問題
色々な変数のバイト数を表示します.8ビットで1バイトになります.
#include <stdio.h>
int main(void)
{
char x1;
int x2;
float x3;
double x4;
printf("%d %d %d %d\n",sizeof(char),sizeof(int),
sizeof(float),sizeof(double));
printf("%d %d %d %d\n",sizeof(x1),sizeof(x2),
sizeof(x3),sizeof(x4));
}
長い文では,一つの文を複数行に分割しても構いません.
コンピュータにおける数値の扱い
整数型や実数型の変数は,それぞれすべての整数や実数を扱えるわけではなく,使用できる数値の範囲に制限があります.この制限は,使用しているコンピュータやコンパイラによって異なるため,あらゆるシステムに対して明確に範囲を示すことはできません.
整数として扱う型
char -128~127 (127=2^7-1)
int -32768~32767 (32767=2^15-1)
charは1バイトの大きさであり,‐128~127の範囲の数を表します.文字型と呼ばれると特別な変数のように感じますが,-128~127の範囲の整数を扱う整数型の変数と考えた方が良いでしょう.

実数(浮動小数点)として扱う型
float 単精度の実数(7桁程度)
double 倍精度の実数(14桁程度)
floatとして宣言する実数型は,浮動小数点を10進7桁分の精度で扱えるようになっています.double型はfloat型以上の精度を持つ実数型と定められており,浮動小数点を10進15桁程度の精度で表現できるものが多くなっています.この数の制限は,主にコンピュータの最も基本的な演算命令が何ビット(2進数の桁数)の数を扱うように設計されているかによって異なってきます.
数値の範囲は処理系によって異なるので,新しい型を初めて使うときには,実際に数値を代入してテストした方が安全です.

条件判断
プログラミングでは,if文を使った条件判断は,繰り返しとともに重要なものです.
if文では括弧の中の条件が満たされる場合,後ろの文を実行します.{}を使えば,複数の文を実行することが可能です.
if(a==10)b=3; /*aが10ならbに3を代入する*/

if(a*10>30) {b=3;
c++;
d=0;}
/* a*10が30より大きいとき,bに3を代入し,cを1増やし,dに0を代入する*/

関係演算
a==b aとbが等しい a>b aはbより大きい
a!=b aとbが等しくない a<=b aはb以下である
a>=b aはb以上である a<b aはbより小さい

例題
if文を使った例題
#include <stdio.h>
int main(void)
{
char moji;
printf("一文字入力してください");
moji=getchar();
if(moji=='A')
printf("入力した文字はAです\n");
}

例題
読み込んだ数値で条件の判断を行う
#include <stdio.h>
int main(void)
{
int num;
scanf("%d",&num);
printf("入力した値=%d\n",num);
if(num)printf("条件が満たされる\n");
}
-1,0,1,5などを打ち込んで実行してみましょう.実際にはif文の括弧の中の数値が0以外のときに,ifに続く文が実行されます.

練習問題
標準入力から整数を入力し,数値が自然数(1以上の整数)のときには「入力した値は自然数です」と表示するプログラムを単純なif文(elseなどを使わない)で作ってみましょう.

練習問題
標準入力から文字(アルファベット)を入力し,文字が'A'でない場合,入力した文字を表示するプログラムを単純なif文(elseなどを使わない)で作ってみましょう.

本日のミニプログラム
#include <stdio.h>
int main(void)
{
if(3>2)printf("OK");
if(3<2)printf("NG");
}

プログラミングⅠ資料No.6
今日の課題
複合条件,else,else if,ブロック

例題6-1
複合条件を使って入力した文字が大文字の場合小文字に変換するプログラム
#include <stdio.h>
int main(void)
{
char moji;
printf("一文字入力してください>>");
moji=getchar();
if(moji>='A' && moji<='Z'){
printf("%c -> %c\n",moji,moji-'A'+'a');
}else{
putchar(moji);
putchar('\n');
}
}
この例題でputchar(moji);putchar('\n');とprintf("%c\n",moji);は同じ処理になります.

複合的な条件
演算 演算子 条件式 意味 例
AND && a && b aかつbである i>0 && i<=10
OR || a || b aまたはbである i==-10 || i==10
NOT ! !a aでない !(i>10)

elseを使ったif文
if(条件式)文1;
else文2;
条件が成立した場合(真)文1を実行し,成立しない場合(偽)文2を実行する.
if文で複数の命令を実行させたい場合,ブロックを使います.
if(条件式)
{文1; 文2; 文3;...}
else
{文A; 文B; 文C;...}
条件が成立した場合(真)文1,文2...を実行し,成立しない場合(偽)文A,文B...を実行する.

ブロック
複数の文を{}に入れると,1つの文と同じように扱えます.これをブロックと呼びます.ブロックでは,見やすいところに改行を入れてください.

練習問題6-1
標準入力から整数を読み込み,その整数が20以下の自然数である場合に,その値を表示するプログラムを作りましょう.

例題6-2
整数を読み込み,奇数か偶数かを判定する.
#include <stdio.h>
int main(void)
{
int num;
printf("整数を入力してください ->");
scanf("%d",&num);
if(num%2 == 0){printf("この整数は偶数です.\n");}
else{printf("この整数は奇数です.\n");}
}
この例題でif()とelseには1文しかありませんので,{}は省略して構いません.

例題6-3
文字を読み込み,大文字の場合小文字に変換し,小文字の場合大文字に変換する.それ以外はそのまま表示する.
#include <stdio.h>
int main(void)
{
char moji;
printf("一文字入力してください>>");
moji=getchar();
if(moji>='A' && moji<='Z'){
printf("%c -> %c\n",moji,moji-'A'+'a');
}else if(moji>='a' && moji<='z'){
printf("%c -> %c\n",moji,moji-'a'+'A');}
else{
printf("%c\n",moji);
}
}

練習問題6-2
入力された自然数を4で割った際の剰余で分類し,その分類を表示するプログラムを,else ifを使って作りましょう.

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int i=-10;
if(i<0)printf("マイナス");
else if(i==0)printf("ゼロ");
else printf("プラス");
}


プログラミングⅠ資料No.7
今日の課題
複雑な条件分岐,#define,数学関数,場合分け(swichとcase)

例題7-1
#include <stdio.h>
#define AP 90
#define A 80
#define B 70
#define C 60
#define D 50
int main(void)
{
int a,b,c,gokei;
printf("中間試験の得点");
scanf("%d",&a);
printf("期末試験の得点");
scanf("%d",&b);
printf("出席回数");
scanf("%d",&c);
gokei=(int)(a*0.4+b*0.6);
if(c<10)printf("不合格");
else if(gokei>=AP)printf("A+\n");
else if(gokei>=A)printf("A\n");
else if(gokei>=B)printf("B\n");
else if(gokei>=C)printf("C\n");
else if(gokei>=D)printf("D\n");
else printf("不合格");
}

#define文
#define文ではAPを90に,Aを80に...置き換えます.つまりコンパイルする前に,置換機能を用いて,文字を置換したのと同じことになります.見かけ上変数APを定義して,90を代入するのと同じような働きをしますが,#define文では変数を使いません.
#define文では見かけ上変数のように扱うことができますが,メモリを必要としません.またプログラム中で頻繁に使う値を変更したい場合などに便利です.

型変換
(型)値とすると,値を違う型に変換できます.
整数から実数,または実数から整数への型変換はよく使われます.
(例) i=(int)(100.0*sqrt(2.0)); y=(double)i/250;  x=(float)1;

例題7-2数学関数を使う
#include <stdio.h>
#include <math.h>

int main(void)
{
float a=4.0,b=2.0;
printf("%f\t%f\n",sqrt(a),sqrt(b));
printf("%f\n",exp(1.0));
printf("%f\n",atan(1.0)*4.0);
}

数学関数を使うプログラムとそのコンパイルの方法
sqrt(a)のような平方根を求めるものは,数学関数として用意されています.これらの数学関数を利用するためには,int  main(void)の行の前に,予めこれらを利用することを記述しておく必要があります.例題のように,#include <math.h>
という行を書いてください.
コンパイラによっては,オプション -lm (マイナス,小文字のエル,エム)をつける必要があります.数学関数の引数は一般にdouble型(float型よりも扱う桁数が大きい)ですが,float型を使っても構いません.特に高い精度で計算を行いたい場合,float型よりもdouble型の変数を使って下さい.

例題7-3直角三角形の斜辺の長さを求める
#include <stdio.h>
#include <math.h>

int main(void)
{
float a,b,c;
printf("辺1\n");
scanf("%f",&a);
printf("辺1\n");
scanf("%f",&b);
c=sqrt(a*a+b*b);
printf("斜辺の長さ=%f\n",c);
}

倍精度実数の読み込み
double型の変数をscanf()で読み込むときは,scanf("%lf",&a);のようにパーセントエルエフとしてください.

例題7-4
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
int main(void)
{
float x;
x=0.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
x=15.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
x=30.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
x=45.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
x=60.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
x=75.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
x=90.0;
printf("%f,%f\n",x,cos(x/180.0*PI));
}

角度に関する関数の単位は度(degree)ではなくradian(180度=πrad)ですので気をつけてください.

switchとcase
switchを使うと括弧の中の値に対応するcaseに飛んで実行を行います.対応するcaseが無い場合,default:に飛びます.caseは行き先表示のようなもので文ではないので,最後はコロン:です.またcaseに飛んだあと,switchのブロックから抜け出す命令がbreakです.

例題7-5switchとcaseを使った場合分け
#include <stdio.h>
#define Y1 "子\n"
#define Y2 "丑\n"
#define Y3 "寅\n"
#define Y4 "卯\n"

int main(void)
{
int i,j;
printf("生年を西暦で入力してください\n");
scanf("%d",&i);
j=i%12;
switch(j){
case 4:
printf(Y1);
break;
case 5:
printf(Y2);
break;
case 6:
printf(Y3);
break;
case 7:
printf(Y4);
break;
default:
printf("子から卯以外ですね\n");
break;
}
}

本日のミニプログラム
#include <stdio.h>
#include <math.h>
#define PI 3.1415
int main(void)
{
printf("%f",sin(30.0/180*PI));
}


プログラミングⅠ資料No.8
今日の課題
whileを使った繰り返し,乱数,型変換

例題8-1whileを使った繰り返し
1から入力された数までの総合計を計算する
#include <stdio.h>
int main(void)
{
int i=1,n,total=0;
printf("1~nまで加えます,nを入力してください");
scanf("%d",&n);
while(i<=n){
total+=i;
printf("現時点の値=%d\t合計%d\n",i,total);
i++;
}
printf("最終的な合計=%d\n",total);
}
whileを使った繰り返し
while(条件){ブロック}
while文では括弧の中()の条件が正しいかチェックし,正しければ以下のブロック{}を実行します.条件が正しければ,何度でも繰り返してブロック{}を実行します.以下のように書くと,iが1からnまで処理を繰り返します.繰り返しの処理を終わったあと,iの値はn+1になっています.
i=1;
while(i<=n){
処理
i++;
}

練習問題1上の例題のプログラムでi++; の行を消してコンパイルし,実行してみましょう.何が起こるでしょうか.
ヒント:放置すればたぶん永遠に動き続けることでしょう.このように誤って終れなくなる場合,無限ループあるいはエンドレスループ(endless loop)におちいったと言います.Ctrl-Cを入力して中断しましょう.
練習問題2上の例題ををデクリメントi--;を使って書き替えなさい.
練習問題31~10までの各整数の2乗,3乗,平方根を求めて表示するプログラムを書いてみましょう.

例題8-2入力された数の階乗を計算する.階乗n!=n×(n-1)×(n-2)×…×1で,0!=1です.
マイナスの数が入力されたらエラーとします.

#include <stdio.h>
int main(void)
{
int n,i=1;
float a=1.0;
printf("nの階乗n!を計算します");
scanf("%d",&n);
if(n<0){printf("ERROR:nは0以上の整数\n");}
else{
while(i<=n){
a*=i;
i++;
}
printf("%d!=%f\n",n,a);
}
}
またprintf("%d!=%f\n",num,result);の%fを%eに書き替えて実行してみましょう.
%eは6.204484e+23=6.204484×1023のように,実数を指数表示します.

練習問題4実行結果をMathematicaで確認しましょう.
20!(Shift+Enter)
N[%](Shift+Enter)

例題8-3
rand()は整数型の乱数を作成します.#include <stdlib.h>を記述すると利用できます.乱数生成のされ方や周期はシステムによって異なります.乱数の最大値はRAND_MAXという定数に定義されています.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i;
float x=0.0;
srand(100);
while(x<=2.0/3.0){
x=(float)rand()/RAND_MAX;
if(x<1.0/3.0)printf("グー\n");
else if(x<2.0/3.0)printf("チョキ\n");
else printf("パー\n");
}
}
乱数から0-1の範囲の実数型の乱数を作り,0-1/3:グー,1/3-2/3:チョキ,2/3-1:パーを表示し,パーが出たら終了する.
srand()は乱数のseed(種)を決定するもので,srand()の引数カッコの中の数を変えることで乱数の条件を変えることができます.

型変換
(型)値とすると,値を違う型に変換できます.x=(float)rand()/RAND_MAX;の場合,乱数の値rand()は,整数ですが,実数に変換され,そのあとにRAND_MAXで割り算されます.x=1.0*rand()/RAND_MAX;としても同じ結果が得られます.(実数)/(整数)の結果は,実数となります.
型変換は,整数から実数,または実数から整数への変換などに使われます.
(例) i=(int)(100.0*sqrt(2.0)); y=(double)i/250;  x=(float)1;

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int i=1,a=0;
while(i<=10){
a+=i;
i++;
}
printf("%d",a);
}


プログラミングⅠ資料No.9
本日の課題
EOF,breakとcontinue,do while文

知っておくと便利なループの流れについて
break文
break文はswitch case文や,while文またはfor文などで作られる繰り返し処理(ループ)から抜け出すときに用いられます.多重の繰り返し処理の場合,break文で最も内側の繰り返し処理から脱出します.
continue文
continue文は,繰り返し処理の残りの部分を省略して繰り返し処理の先頭に戻ります.
無限ループ
繰り返し処理で条件が常に満たされる場合,無限ループとなりプログラムが終了しません.無限ループを止めたい場合,強制的にプログラムを終了する必要があります.

例題9-1入力した文字の終了EOFが来るまで文字の表示を続ける.
#include <stdio.h>
int main(void)
{
char c;
while((c=getchar())!=EOF){
printf("%cのコード番号%d\n",c,c);
}
}
このプログラムでは,半角文字が入力されるとその文字をそのまま表示する.
入力を終了したいときは,Ctrl+Z Enter(Windows),Ctrl+C(Unix)を入力する.
半角文字(ASCIIコード)は,0-127の数値に相当するので,文字が入力されれば0-127の数値がcに代入されます.
文章の最後を意味する信号が入力されると,cに-1が代入されます.C言語では以下のようにEOFが-1と定義されています.
#define EOF (-1)
従ってwhile((c=getchar())!=EOF)とすれば,文章の最後を意味する信号が入力されるとwhile文が終了します.
例題9-2入力した文字が数字の場合break文で読み込みを終了する

#include <stdio.h>
int main(void)
{
char c;
while((c=getchar())!=EOF){
if(c>='0' && c<='9')break;
putchar(c);
}
}

練習問題文字'x'が入力されたとき終了するプログラムを作ってください.

do while文while文は,ループの先頭で処理を繰り返すかどうかの判断を行いますが,これに対し,do while文はループの終末で繰り返すかどうかの判断を行います.do whileは文を実行した後で条件式を評価し,条件式が真である間,文を繰り返します.
繰り返し終了前に少なくとも1度は,ループ内の処理を実行させたい場合などに便利です.

例題9-3
1から100までの合計を表示する

#include <stdio.h>
int main(void)
{
int i=1,s=0;
do{
s+=i;
i++;
}while(i<=100);
printf("%d",s);
}

練習問題
例題をデクリメントi--を使って書き替えなさい.

練習問題do whileを使って,初期値と公差を入力しiが0から9番目までの等差数列の和を求めるプログラムを書きましょう.

例題9-4整数の入力を繰り返し,0が入力されたら合計を表示し終了する
#include <stdio.h>
int main(void)
{
int i,s=0;
do{
scanf("%d",&i);
s+=i;
}while(i!=0);
printf("合計は%d\n",s);
}

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int a=100,b=0;
do{
b+=a;
a--;
}while(a>0);
printf("%d",b);
}



プログラミングⅠ資料No.10
今日の課題
for文(forループ)

for文について
繰り返し回数があらかじめ決まっているループを実行させる場合には,for文が用いられます.for文の一般的な構造は次のようになります.
for(初期値設定; 継続条件 ; 更新式){文;文;...}
処理を行う文が一つしかない場合にはカッコ{}を省略して
次のように書けます.
for(初期値設定; 継続条件 ; 更新式)文;
for文の( )中の「初期値設定」と「更新式」を省略すると,while文と同じことになり,';'以外のすべてを省略すると無限ループになります.
for (i= 5; i < 10; i++)
iを5から始め,iを+1しながら10未満まで(9まで)の間繰り返す.
for (i= 10; i > 0; i--)
iを10から始め,iを-1しながらiが0より大きい間繰り返す.
for (c= 'a'; c <='z'; c++)
cを'a'から'z'まで繰り返す.
for ( x = 0.0; x <=360.0; x = x + 20.0)
xを0.0から始め,+20.0しながら360.0になるまで繰り返す.
for ( ; ; )
判断式がないので,無限ループとなる.

例題10-1
1から入力された数までの合計
#include <stdio.h>
int main(void)
{
int i,sum=0,n;
printf("整数nを入力してください");
scanf("%d",&n);
for(i=1;i<=n;i++){
sum+=i;
}
printf("1からnまでの合計=%d\n",sum);
}

練習問題2から入力された数までの偶数の合計を求めるプログラムを作りなさい.

例題10-2
aから入力した文字までの表示を行う.
#include <stdio.h>
int main(void)
{
char a,b;
printf("英小文字を入力してください\n");
scanf("%c",&a);
printf("aから入力した文字までの表示\n");
for(b='a';b<=a;b++)printf("%c\n",b);
}

練習問題
1~10までの各整数に関して各数の2乗,3乗,平方根を求めて表示するプログラムをfor文を用いて書いてみましょう.

例題10-31から100までの3の倍数の個数を求める
#include <stdio.h>
int main(void)
{
int i,s=0;
for(i=1;i<=100;i++){
if(i%3 == 0){printf("%d\n",i); s++;}
}
printf("1から100までの3の倍数の個数は%d\n",s);
}

練習問題
上のプログラムをwhile文を用いて書いてみましょう.
練習問題
上のプログラムをデクリメント(i--)を用いて書いてみましょう.

例題10-4入力された整数が素数かどうか判定する.
#include <stdio.h>
int main(void)
{
int i,n;
printf("整数nを入力してください\n");
scanf("%d",&n);
for(i=2;i<n;i++){
if(n%i==0){
printf("素数ではありません\n");
break;
}
}
if(i==n)printf("素数です\n");
}

(注)break文を実行しないで,繰り返しを最後まで終了した場合,,i==nになることに注意しましょう.


例題10-52重のforループ
鶴と亀が合計で10匹,足の数が合計で26本の場合の鶴亀算.
#include <stdio.h>
#define N 10
#define M 26
int main(void)
{
int i,j,hiki,ashi,turu,kame;
for(i=0;i<=N;i++){
for(j=0;j<=N;j++){
hiki=i+j;
ashi=i*2+j*4;
if(hiki==N && ashi==M){turu=i;
kame=j;
}
}
}
printf("正解 鶴は%d匹 亀は%d匹\n",turu,kame);
}

多重のループの場合カッコ{}の組み合わせが合っているか確認しましょう.
練習問題タコとイカが合計で100匹,足の数が合計で840本の場合のタコとイカの数を求めなさい.

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int i;
float s=1.0;
for(i=1;i<=10;i++)s*=i;
printf("%f",s);
}


プログラミングⅠ資料No.11
今日の課題
簡単な関数,main関数とユーザー関数,プロトタイプ宣言

例題11-1 2つの数の差を関数を使って計算する.
#include <stdio.h>

int sa(int x,int y){
int z;
if(x>=y)z=x-y;
else z=y-x;
return z;
}

int main(void)
{
int i,j;
printf("数を入力してください\n");
scanf("%d",&i);
printf("数を入力してください\n");
scanf("%d",&j);
printf("%dと%dの差は%d\n",i,j,sa(i,j));
}

関数
C言語のプログラムを実行したときに,必ず実行されるのがmain(){}の記述です.これをmain(メイン)関数と呼びます.
複雑な処理をプログラムで記述する場合や同じ処理を繰り返す場合,まとまった処理を好きなときに呼び出せると便利です.ユーザーが作った処理の手順をユーザー関数やユーザー定義関数と呼びます.
main関数からユーザー関数を利用する場合,ユーザー関数へいくつかの値が送られます.またユーザー関数からmain関数へ処理の結果を値として送ります.main関数からユーザー関数へ送る値を引数(ひきすう)と呼びます.ユーザー関数からmain関数へ送る値を戻り値と呼びます.
戻り値=関数の型
関数定義の中のreturn(式) の式の値が関数の戻り値となります.戻り値がどのような型なのかを関数の型として明確に宣言しておかなければなりません.return(式)の型と関数の型は一致していなければなりません.戻り値は1個または無し(void)です.
引数
main関数側で指定する引数を 実引数(じつひきすう),ユーザー関数側で指定する引数を仮引数(かりひきすう)と呼びます.関数を呼び出すと,仮引数に実引数の値が代入されると考えればよいでしょう.従って,実引数には,定数,変数,式(定数や変数を演算子で結合したもの) を書けますが,仮引数には,変数しか書けません.また,仮引数は関数を定義する際,型を宣言しておく必要があります.対応する実引数と仮引数には同じ名前を付ける必要はありませんが,型と個数は必ず一致させなければなりません.引数の無い関数(void)もあります.

異なる関数の中で定義される変数は,同じ名前でも,別なものですので注意しましょう.

練習問題
和を計算する関数wa(x,y)を使ったプログラムに書き換えましょう.

例題11-2 例題10-1を改良し,関数を使い1からiまでの合計を表示するプログラムです.
関数を使う場合,引数をどうするか?戻り値をどうするか?変数の定義が,引数と関数内で重複しないか,注意する必要があります.戻り値の型と関数の型が一致していることも確認しましょう.

#include <stdio.h>
int gokei(int n){
int i,sum=0;
for(i=1;i<=n;i++){
sum+=i;
}
return sum;
}
int main(void)
{
int i;
for(i=1;i<=20;i++)
printf("1から%dまでの合計=%d\n",i,gokei(i));
}

(参考)例題10-1
#include <stdio.h>
int main(void)
{
int i,sum=0,n;
printf("整数nを入力してください");
scanf("%d",&n);
for(i=1;i<=n;i++){
sum+=i;
}
printf("1からnまでの合計=%d\n",sum);
}

例題11-3 整数の階乗を返す関数
#include <stdio.h>

float kai(int n)
{
float x=1.0;
int i;
for(i=1;i<=n;i++)x*=i;
return x;
}

int main(void)
{
int i;
for(i=1;i<=10;i++){
printf("%dの階乗は%f\n",i,kai(i));
}
}
main()関数の中で変数iと関数kai()の中で使われている変数は,同じ名前でも,別なものですので注意しましょう.

例題11-4 プロトタイプ宣言を使った階乗を返すプログラム
#include <stdio.h>

float kai(int n);

int main(void)
{
int i;
for(i=1;i<=10;i++){
printf("%dの階乗は%f\n",i,kai(i));
}
}

float kai(int n)
{
float x=1.0;
int i;
for(i=1;i<=n;i++)x*=i;
return x;
}

関数のプロトタイプ宣言
普通はmain関数の前に,使用する関数を記述しておきます.そうしないと計算機は,main関数の中にあるユーザー定義関数の引数の型と戻り値の型が,どのようなものなのか分からないので,コンパイルできません.
しかしプログラムの流れとして,main関数を最初に書いた方が分かりやすい場合があります.このときに,関数の名前,引数の型,戻り値の型(関数の型)をmain関数の前に宣言しておき,詳細はmain関数の後に記述することができます.関数の名前と型をmain関数の前に宣言することを,プロトタイプ宣言と言います.
実際には,ユーザー定義関数の先頭の行の")"までをmain関数の前に置いて,最後にセミコロン";"を付ければ,プロトタイプ宣言になります.またプロトタイプ宣言では,関数の名前,引数の型,戻り値の型を定義すれば構いません.
int p(int x,int y); または int p(int,int); どちらでも構いません.

練習問題
上の例題でプロトタイプ宣言の行を削除してコンパイルしてみましょう.

練習問題
例題11-1をプロトタイプ宣言を使ったプログラムに書き換えましょう.

一歩進んで
printf()やgetchar()などの関数も,本当はプロトタイプ宣言が必要です.どこにあるのでしょうか?実はプログラムを書くときのおまじないとして扱っていた,#include<stdio.h>という部分です.実際は,stdio.hというファイルが用意されており,その中にprintf()やgetchar()などの関数のプロトタイプ宣言が書かれています.ところでmain関数も関数の一つですが,main関数はint型で定義されています.C言語の本によってはmain関数の最後にreturn 0;を入れて形式的に整数を返している書き方があります.

練習問題
xの絶対値を返す関数をプロトタイプ宣言を使って作ってみましょう.

練習問題
xのn乗を返す関数をプロトタイプ宣言を使って作ってみましょう.

本日のミニプログラム
#include <stdio.h>
int wa(int x,int y)
{
return x+y;
}
int main(void)
{
printf("%d",wa(2,3));
}


プログラミングⅠ資料No.12
本日の課題
関数その2(戻り値の無い関数,引数の無い関数,関数の内部の変数,グローバル変数)

戻り値のない関数
この場合,関数や引数の型の定義をvoidとします.戻り値の無い関数では,関数の型がvoidとなり,return文はなくなります.
例題12-1 戻り値の無い関数の例.値が4で割り切れるときに値を表示する関数を使い,100までの7の倍数の中から4の倍数を表示する.
#include <stdio.h>

void test(int x)
{
if(x%4==0)printf("%d\n",x);
}

int main(void)
{
int i;
for(i=7;i<=100;i+=7)test(i);
}

練習問題
プログラムをプロトタイプ宣言を使って書き直しましょう.
引数の無い関数
引数の無い関数では,引数の部分がvoidとなります.
例題12-2
関数の内部で整数の値を読み込み0以上なら平方根を返し,負なら0を返す関数
#include <stdio.h>
#include <math.h>

float test(void)
{
int i;
float x;
scanf("%d",&i);
x=(float)i;
if(i>=0)return sqrt(x);
else return 0.0;
}
int main(void)
{
printf("%f\n",test());
}

例題12-3関数における値の確認.main関数とユーザー関数内の変数の変化に注意しましょう.
#include <stdio.h>

int test(int x,int y)
{
int z=0;
x*=2;
y--;
printf("x=%d y=%d z=%d \n",x,y,z);
return x;
}

int main(void)
{
int x=3,y=4,z=0;
printf("x=%d y=%d z=%d \n",x,y,z);
z=test(x,y);
printf("x=%d y=%d z=%d \n",x,y,z);
}

局所的変数(ローカル変数)
今まで使ってきた変数は,一般にその関数内だけで有効であり,これを局所的変数(ローカル変数)と呼びます.main関数やユーザー関数内で同じ変数名が使用されていても,これらは別な物として扱われ,お互いに影響を与えることはありません.
グローバル変数(外部変数)
これに対し,main関数やユーザー関数の外側で定義した変数をグローバル変数(外部変数)と呼び,どの関数からも共通して呼び出せます.ユーザー関数からreturnで値を一つしか戻せませんが,ユーザー関数で得られた複数の値をmain関数でも使いたいときなど便利です.
しかし,プログラムが複雑になると,どこかで変数を書き替えたのに気がつかず,トラブルが生じることがあるので,注意が必要です.

例題12-4
グローバル変数を使う例題
#include <stdio.h>
#include <math.h>
int i;
void func(void)
{
float x;
x=cos(i*3.14159/180.0);
printf("%d %f\n",i,x);
}
int main(void)
{
for(i=0;i<=90;i++)func();
}

#include <math.h>ではM_PIとして円周率が与えられています.

例題12-5
グローバル変数a,b,cを用いて2次方程式の解を求める.
#include<stdio.h>
#include<math.h>
float a,b,c; /*グローバル変数*/
void kai(void)
{
float a1,a2,d;
d=b*b-4.0*a*c; /*判別式*/
a1=(-b+sqrt(d))/(2.0*a);
a2=(-b-sqrt(d))/(2.0*a);
printf("解1=%f\n解2=%f\n",a1,a2);
}

int main(void)
{
printf("係数aを入力してください");
scanf("%f",&a);
printf("係数bを入力してください");
scanf("%f",&b);
printf("係数cを入力してください");
scanf("%f",&c);
if(b*b-4.0*a*c>=0)kai();
else printf("解はありません\n");
}

変数をdoubleにしてscanf()を使う場合scanf("%lf",&a);のように%lfとしてください.
本日のミニプログラム
#include <stdio.h>
int i;
void test(void)
{
printf("%d",i);
}
int main(void)
{
i=5;
test();
}

プログラミングⅠ資料No.13
今日の課題
配列の使い方その1

配列について
同じ型の変数を多数使いたい場合に,一つ一つ異なる変数名を割り当てるのは大変です.プログラムが見にくく,エラーの原因にもなります.このような場合は,配列を用います.
例えば, int a[40]; と宣言すると,a[0],a[1],…,a[39]という40個の変数が用意されます.変数はデータを入れておく箱として考えることができます.配列の場合,図のように aという配列名と[ ]で囲まれた配列番号 (添字と呼ぶ) で管理されます.つまり,a[0]は0番目の箱,a[39]は39番目の箱という意味になります.i番目の箱はa[i]と書くことで指定できます.配列の添え字は必ずゼロからスタートします.

例題13-1
#include <stdio.h>
#include <math.h>
int main(void)
{
int a[11],i;
float b[11];
for(i=0;i<=10;i++){
a[i]=10-i;
b[i]=sqrt(10.0-i);}
for(i=0;i<=10;i++)
printf("a[%d]=%d\tb[%d]=%f\n",i,a[i],i,b[i]);

}

配列の定義
C言語における配列の宣言は,以下のようにして行います.
int suu[20]; /* 整数型の配列suu[0]- suu[19]*/
float data[5][15]; /* 単精度実数型の二次元配列data[0][0]- data[4][14]*/
char moji[20]; /* 文字型の配列moji[0]- moji[19]*/
型としては,int,float,double,charなど,これまで扱った変数と同じ型を指定できます.要素のカッコ[]が1つのものを1次元配列,2つのものを2次元配列と呼びます.
ここで特に注意しておきたいのは,指定する[要素の数]は添字の上限ではなく,要素の数であるということです.つまり,int a[40]; と宣言された配列は,a[0]~a[39]までの40個が用意されるのであって,a[40]という配列要素は確保されていません.

配列の初期化
int suu[20]; として配列を定義してから suu[18]++; とするとどうなるでしょうか?suu[18]が初めから0であるとは限りません.初めから配列に値を入れておくか(初期化),正しく配列に値を代入する必要があります.例えば配列に全て0を代入する場合でも,forループなどが必要です.しかし要素の数が小さい配列の場合,配列の宣言時に,{ }の中にデータを書いておけば,自動的にデータを初期設定することができます.

また,配列の宣言時に初期化データが置かれているときは,[]内の値を省略して
int a[]={3,2,1};
のように書くこともできます.


例題13-2
配列を使い平均,分散,標準偏差を計算する
平均   分散   標準偏差

#include <stdio.h>
#include <math.h>
#define N 5
int main(void)
{
float a[N]={1.0,2.0,3.0,4.0,5.0};
int i;
float s=0.0,heikin,bunsan;
for(i=0;i<N;i++)s+=a[i];
heikin=s/N;
printf("平均は%f\n",heikin);
s=0.0;
for(i=0;i<N;i++)s+=(a[i]-heikin)*(a[i]-heikin);
bunsan=s/N;
printf("分散は%f\n標準偏差は%f\n",bunsan,sqrt(bunsan));
}
例題13-3
配列の最大値を表示するプログラム
#include <stdio.h>
int main(void)
{
int data[8]={2,4,3,10,0,15,-3,1};
int i,max;
max=data[0];
for(i=1;i<8;i++){
if(data[i]>max)max=data[i];
}
printf("最大値は%d\n",max);
}

変数maxにdata[0]の値を入れておき,配列の要素が,maxを上回ったときに値を更新します.
同じ型の変数と配列の定義は,以下のように一緒にしても,分けてもどちらでも構いません.
int i,max,data[8]={2,4,3,10,0,15,-3,1};

例題13-4
素数(prime number)を計算する.
最初は配列s[]に全て1を入れておきます.
素数の倍数の場合s[i]=0としていくと,s[i]==1のiが素数となります.

#include <stdio.h>
#define N 1000
int main(void)
{
int i,s[N],sp;
for(i=2;i<N;i++)s[i]=1; /* 配列s[]を全て1で初期化*/
sp=2; /*最初の素数は2*/
while(sp<N){
for(i=2*sp;i<N;i+=sp)s[i]=0; /*素数spの2,3,4..倍を消していく*/
for(i=sp+1;s[i]!=1;i++); /*素数spの次の素数を探しspとする*/
sp=i;
}
for(i=2;i<N;i++)if(s[i]==1)printf("%d\n",i);
}


一歩進んだ例題
2次元配列を使った掃き出し法による逆行列の計算
#include <stdio.h>
int main(void)
{
int i,j,k,n=3;
float a,b,y[3][3];
float x[3][3]={{1.0,2.0,-1.0},{-1.0,-1.0,2.0},{2.0,-1.0,1.0}};
/* y[3][3]は単位行列*/
for(i=0;i<n;i++)for(j=0;j<n;j++)if(i==j){y[i][j]=1.0;}
else{y[i][j]=0.0;}
for(i=0;i<n;i++){a=x[i][i]; /* X の対角成分を1にする*/
for(j=i;j<n;j++)x[i][j]=x[i][j]/a;
for(j=0;j<n;j++)y[i][j]=y[i][j]/a;

for(j=0;j<n;j++)if(j!=i){b=x[j][i];
for(k=i;k<n;k++)x[j][k]=x[j][k]-x[i][k]*b;
for(k=0;k<n;k++)y[j][k]=y[j][k]-y[i][k]*b;
}
}
printf("%f %f %f\n",y[0][0],y[0][1],y[0][2]);
printf("%f %f %f\n",y[1][0],y[1][1],y[1][2]);
printf("%f %f %f\n",y[2][0],y[2][1],y[2][2]);
}

掃き出し法:
逆行列を求めたい行列Aと単位行列を横に並べ3×6行の行列[AE]を作る.
行基本操作を行い,行列Aを単位行列にすると,Eに相当する部分がAの逆行列になる.
行基本操作
1つの行にある数をかける.
1つの行にある数をかけたものを別の行に加える.
2つの行を入れ替える

本日のミニプログラム
#include <stdio.h>
int main(void)
{
int a[4]={1,2,3,4};
int i;
for(i=0;i<4;i++)printf("%d\n",a[i]);
}

プログラミングⅠ資料No.14
今日の課題
配列の続き,文字列と配列,プログラミングⅠのまとめ

例題14-1
文字型配列を使った,文字列の入出力.
#include <stdio.h>
#define N 20
int main(void)
{
char a[N];
int i;
printf("文字列を入力して下さい");
scanf("%s",a);
printf("%s\n",a);
for(i=0;i<N;i++)putchar(a[i]);
}

文字と文字列の違い
文字は文字型変数に代入することができ,整数と同じように加減算などができます.
文字は'z'や'\n'のようにシングルコーテーション「'」で囲みます.
文字列は"abc"のようにダブルコーテーション「"」で囲みます.実際には,文字列"abc"の場合,'a'+'b'+'c'+'\0'のように最後に,文字列の終端を意味するヌル文字'\0'が付きます.
一文字の文字列"a"と文字定数'a'は異なることに注意しましょう.
配列に文字列を代入する
単語のように文字数が決まっていない文字列を配列に格納する場合,文字列の終端を意味するヌル文字'\0'を使います.十分な大きさの配列を用意しておけば,文字数に関わらず必要な文字列の入出力ができます.ヌル文字より後ろの配列の値は無視されます.
例えば要素の数が5の配列a[]に文字列"abc"を代入すると,各要素は次のようになります.
a[0]='a'
a[1]='b'
a[2]='c'
a[3]='\0'
a[4]=?
5番目の要素a[4]には,何が入っているか未定です.

配列a[]に代入した文字列の表示は,次のように行います.
printf("%s\n",a);
このときヌル文字の前までの文字が表示されます.

例題14-2
scanf()で文字列を入力すると文字が一つずつ配列に代入され最後に'\0'が入ります.'\0'は文字列の終了を意味する文字(ヌル文字)です.'\0'までの数をカウントすることにより文字数を計算できます.
#include <stdio.h>
int main(void)
{
char a[20];
int i=0;
printf("文字列を入力して下さい");
scanf("%s",a);
printf("%s\n",a);
for(i=0;i<20;i++){
if(a[i]=='\0')break;
putchar(a[i]);
}
putchar('\n');
printf("文字数は%dです",i);
}
一歩進んだ説明
scanf()では,ポインタで値の保存先を指定します.&変数名で変数のポインタ(変数のアドレスを示すもの)となります.配列のカッコをはずすとポインタになるので,scanf()で配列に文字列を入力する場合&は不要です.


例題14-3wile,do while,forの比較1から10までの和
(wile)
#include <stdio.h>
int main(void)
{
int i=1,s=0;
do{s+=i;
i++;
}while(i<=10);
printf("%d",s);
}

(do while)
#include <stdio.h>
int main(void)
{
int i=1,s=0;
while(i<=10){
s+=i;
i++;
}
printf("%d",s);
}

(for)
#include <stdio.h>
int main(void)
{
int i,s=0;
for(i=1;i<=10;i++){
s+=i;
}
printf("%d",s);
}

例題
C言語の復習を兼ねた例題
#include <stdio.h>
#include <math.h>
#define PI 3.14159
int main(void)
{
int i=45,j=0;
float x;
printf("sin(%d)=%f\n",i,sin((float)i*PI/180.0));
for(i=1;i<10;i++)if((i%3==0) || (i<5))j+=i;
printf("%d\n",j);
i=4/5+4.0/5;
x=4/5+4.0/5;
printf("%d %f\n",i,x);
printf("アルファベットの小文字を入力してください\n");
scanf("%c",&i);
if(i>='a' && i<='z')printf("%cは%d番目の文字です\n", i,i-'a'+1);
else printf("アルファベットの小文字ではありません\n");
}