忍者ブログ
RoboCup Junior Japan Rescue Kanto OB

             2005~2013
[1]  [2]  [3
実はそろそろ機械語が読めるようになってきつつあるLuzです。


最近、またASM始めました。

ASM、アセンブラ、どこぞのBrainなんたらよりはマシですが、これもこれで難しい部類の言語ですね。

正式にはアセンブリ言語と呼ぶそうです。テストでアセンブラって書いたら×されました。
アセンブラには「アセンブリ言語を機械語に翻訳するプログラム」という意味を有るそうです。

アセンブリ言語とは所謂C言語等の高級言語と機械が理解する機械語のちょうど中間に位置する言語です。

コンパイルをした先に行き着く言語というのが正しいでしょうか。

アセンブリ言語の特徴は機械語をそのまま人間の読める文字に変換しているだけという点です。

C言語だと、例えば足し算だったら

i=i+j;

という風に、これひとつでなんか色々な処理を行なって、足し算を行なってくれますね。


でもアセンブリ言語の場合は、iという変数の値をメモリから引き出して、jという変数の値をメモリから引き出して、

それでようやく足し算をして結果をメモリの中のiに保存して・・・

という一連の動作が全てバラバラの命令になっています。

つまり、足し算をするだけでもC言語より莫大な量のプログラムを書き込む必要があります。


これがアセンブリ言語です。だから中身は機械語と同じだけど、01の数字を文字に置換しているというだけのものです。

つまり・・・命令文は複雑になってややこしくはなるけど、

その分かなり細かいところまでプログラムをいじることができるという訳です。

だから簡単に言うと、ROBOLABからC、に移行した際に、プログラムの設定を細かく行なうこと出来たという経験。

Cとアセンブリ言語の違いはアレと同じ感覚ですね。



で、僕は以前興味本意でコイツに手をつけたことがあるのですが、結局面倒になって、またCに戻ってきていたのですね。
I2Cの時は死ぬかと思った・・・。

で、それから何年か経って、今度はアセンブリ言語の需要が生まれてしまったのです。

要するに前回はやる必要性がなかったのでテキトーだったけど、今回はやらねばなるまい。ということです。


という訳でテスト期間中にも関わらず、こうしアセンブリ言語と格闘しているわけです。

時の流れって怖い。完全に忘れてますねー。


そんな感じで今日の記事はこの辺で。

あれ?今日だと思ったら明日になってる?あれ?今日が明日で、だけど今日は今日で・・・?


(^・ω・)ノ RadiumProduction in RoboCup Junior
うちの学校、8月10日にも普通に授業があるのですが、毎年毎年この日周辺は遅刻者がとても多い気がします。

その理由というのがまぁ・・・コミケ会場が地理的に・・・関係しちゃったりしてるからなんですけど・・・。

通学する電車に乗れないんだって。りんかい線組は大変だなぁ。

うちの学校大体コミケの一日目と授業が重なってりんかい組が登校できなくなる惨事が発生しているんです。

いい加減授業日避ければいいのに・・・



さて、一体いつからまともに部活をしていないでしょう。

恐らく7月になってから何もしていないような気がします。


今日も5時半には部室を出発今月は極端に部活をしていません。

でも、帰ってよくよく考えてみると・・・今、出ているレポートは3つ。提出は全部来週以降。

まだ慌てるような時間じゃない。



・・・と、言うわけで散々引き伸ばしにしてきたLineSumilatorの改良を行うことにしました。

LineSumilatorというのは産技祭で出品予定のなまら凄くないシュミレーターと言う名のプログラムゲームです。

ゲーム要素があるかと言われると返答に困りますが、シュミレーターかと聞かれても返答に困ります。

3月のジャパンオープン前に作成したのですが、どうにも動作が重くなりすぎて、

i7クラスの性能のパソコンでないと、重すぎてまともに動作しないという欠点がありました。


と・・・言うわけで。今日はそれを修正するために4ヶ月ぶりのに開いた6000行と睨めっこしていました。

それで成果なのですが、まぁatom270くらいの性能でなら何とか動くぐらいにまで持って行くことができました。
celeron?pentium?知らん!

Intel基準なのはAMD Sempron SI-42だとサクサクになったよ!と言っても何処までの人に通じるかわからないからです(笑)


ノートパソコンだとちょっと前ならAMDは多かったのに、

CPUで言われると途端にIntelのモノ以外はどれくらいの性能なのかがわからない。

結構そういう人って多いのではないでしょうか?

僕自身、AMDのPCは一台しか持っていないものあってAMDのCPUは殆どわかりません(笑)

そもそもAMDは去年の末にIntelに対して敗北宣言出していますから、まぁ当然といえば当然なのか・・・。

CPUで世界で初めて1GHzに到達したりと、昔はIntelと対になるような立派なものだったんですけどねぇ・・・時の流れか・・・。


因みにSempron SI-42はクロック2.0GHzのシングルコアです。Core2duoより大分格下のCPUですね。

という訳で今日はそんなLineSumilatorの改良を行なって遊んでいました。それでは今日はこの辺で。


コミケといえば、C82でGoogleが出店をやらかすそうですね。一体何をする気なんでしょう・・・。

(^・ω・)ノ RadiumProduction in RoboCup Junior
凄いな、感動的だ。




―だが無意味だ。


そんな言葉が似合う、そんな課題が出されたんです。

出された教科はアルゴリズム、内容はプログラム。

実はプログラム自体はただ単純な整列のプログラム、非常に簡単な構造で、あっという間に書くことができます。


でも・・・。

そのプログラム、実行するのにかかる時間がとんでもないんです。


なんとi3搭載のノートPCでも半日かかるという鬼畜っぷり。

そしてそれをレポ―トに記録するんだとか。

とりえあず言えるのは・・・「落ち着きましょうよ。」

そんなとんでもない課題が出されてしまった今日この頃でした。


因みにうちでやってみたら流石はi7 940、2時間もせずに終了しました(笑)

(^・ω・)ノ RadiumProduction in RoboCup Junior

大会、レポート、レポート、課題、授業、レポート、研究室。

とてもじゃないけど部活なんてムリでした(笑)

まぁ特に今日なんか授業が終わった時点で19:30でしたからどうしようもありませんね。


それで今一体そんなに詰めて、研究室で何を作っているのかといいますと、

将棋のプログラムです。それもなんかHSPで作らないといけないんだとか。

一度Cで作って完成させてしまったのですが、なんか色々あって今度はHSPで作ることになりまして・・・。


まぁ僕自身が新しく書くという残念な事態を避ける事には成功したのですが、

他の研究室生の補助ということで立ちまわることになりました。

本当は将棋の方のAIを作るという流れにしても良かったのですけど、

どうにもやる気スイッチが見つかりませんでしたので、こういう形となりました。


まぁ多分作るにしても、AIをちゃんと作るのは面倒なので、

実際に対人戦で打ったデータを記録してそれを基に作っていこうかと考えています。


変に学習とかさせるよりその方が実際問題何倍も楽ですからね。きっと・・・。


という訳で今はそんな感じで部活関連のことは一切行なっていないのでした(笑)


(^・ω・)ノ RadiumProduction in RoboCup Junior

ずいぶん前の続きで、ポインタによる文字列のお話です。

前回は配列による文字列格納というものを行いました。

只、これだとscanfで文字を読み込んだりはできるものの、変数に値を入れるように、後から文字列を代入するということはできません。

じゃあ後からの代入を行いたい時はどうするか。
専用関数もあるのですが、まぁ面倒なので、一般にはポインタが使われています。

使い方はこんな感じ。

char *p;
p="abc";

特に問題はないかと思います。

これでポインタpに文字列を、正確には文字列のアドレスを格納することができます。

実際にはこれを組み合わせてポインタ配列というものを使うことが結構あったりします。


なので次回はこのポインタ配列について書いて行こうと思います。

(^・ω・)ノ RadiumProduction in RoboCup Junior
ロボカップ研究部の一年生の数です。激励会効果があったのかわかりませんが、また増えたようですね。

今年もすごい人数ですが、まぁなんとか頑張っていこうと思います。


と言っても最近は忙しくて部活ができなくなっているのですけど・・・

特に今日なんかはずっと研究室の活動で殆どこれませんでした。


その研究室の活動なのですが、なぜかゲームを作っています。それも某ボードゲームの電子化。


前回から行なって次回までに完成、たった6時間でプログラミング初心者たちは

自分の知らない言語でゲームを作らなくてはならない。そんなとんでもない内容だったのですが・・・。

さすがにムリそうだってことが発覚(いやとっくにわかってたことなんですけど・・・)、方針転換して


4人でHSPを使ってそのゲームを分担して作ることになりました。

HSPは齧ったことぐらいならあるのですが、実際に使って何かしたか・・・と言われると微妙なレベルの知識しかありません。

なんか楽にしたつもりが逆にハードルが上がっているような気がしますが、とりあえず来週までなのでやらざるを得ません。

さて、今週は電通の大会もあるのに、体力と気力そしてSAN値は保つでしょうか・・・


かなりギリギリいっぱいの一週間がまた幕開けの模様です。


(^・ω・)ノ RadiumProduction in RoboCup Junior

ということなので、うちの部活も駆り出されることになりました。

参加される方は何処かでお会いするかもしれませんね。


今日は研究室での活動が凄かったです。

今日の活動は・・・ゲーム作り(笑)

あれ?本来の研究の趣旨からだいぶ脱線しているような・・・どんどん違う方向に突っ走っている今日この頃でした。

しかも今日は言うことを聞く気配がまるで感じられないびすたん(vistaの通称)に

プログラミング環境を構築するだけで終わりました。っていうかVisual C++全然インスト-ル終わらないし・・・



しかも今回、4人で作ることになったのですが、なんと4人全員が違う言語で書かないといけないなんて制約が。

とりあえずCとJavaとHSPとRubyに別れましたが、

Rubyの子は環境構成が終わらず、HSPの子はプログラムの書き方の勉強止まり、Javaの子は何もできず・・・。

Cの自分は若干でもプログラムが進んだので良しとしましょう。


やっぱり研究室で使うPCにびすたん割り当てたのはまずかったかなぁ。funキーなんか浮いてるし。


因みに部活の方はと言いますと、今週のノルマが終わって部品がないので何も出来ずに終わりました。

とりあえず明日学校行く前に部品買って、先に進みたいと思います。

それでは今日はこのへんで。


(^・ω・)ノ RadiumProduction in RoboCup Junior
今回は文字列の扱い方についてです。

前回の記事で、文字列は、配列やポインタで表現するという説明を致しました。

今回はその続きからです。


例えば、配列を使う場合、これに関しましては、前回の記事でも触れましたが、

char型の配列要素一つにつき、半角英数一文字が格納できるようになっています。

つまり、配列を使って文字列を格納する際には、

納する文字の数だけの要素のある配列を用意すれば良いということになるかと思うのですが・・・


実際にはちょっと違います。

実は、文字列と文字いうものは、それそれ1セットで一つの情報という扱いですが、

これだと文字と文字列との区別がつきません。

ということで、文字列であることを示すために、文字列には最後の文字の次に\0という記号が含まれます。

これはNull文字と呼ばれ、NULLとも表記されます。

つまりNULL文字の分を含めて

最低でも、格納したい文字数+1個の要素数の配列が必要になるわけです。


例えば、配列sにrobocupという文字列を格納しようとするとこうなります。

char s[8]="robocup";

ここで注意しないといけないのが、この文が変数の宣言文だという点です。

実は、配列に文字列を格納する場合は%sを使ってscanfで読み取るか、初期化の際に代入するか、

または専用の関数を使用するかしかありません。

つまり普通の変数のように、後から

s=" robocup";

という感じにはできないということです。


また、文字の時は'でくくりましたが、文字列の場合は"でくくわれています。ここも注意すべき点ですね。

これはなんで変わってくるかといいますと、ポインタがまた関わってきます。

まぁこの件は配列とポインタの関係の理解が必要なので今回は割愛します。


と、いう訳で、これが配列における文字列の扱い方です。

次回はポインタにおける文字列の扱い方について紹介します。

(^・ω・)ノ RadiumProduction in RoboCup Junior
今回は文字列についての記事です。

まずは文字について、

例えば、文字といえば、a、b、cこんな感じですよね。

C言語における文字というのは半角英数一文字を指します。

この文字というもの、0と1しか理解出来ないコンピューターに理解させる為にはどうしましょうか。

0と1となると2進数、2進数は数字ですよね。

つまり文字を数字に置き換えてやればいいですよね。

という訳でCに限らず、プログラミングにおいては、文字は数字で表現します。

だから例えばaをコンピューターで表す時には0を使って、bを表す時は1を使って・・・と決めることで、コンピューター上で文字を扱えるようにしている訳ですね。


具体的には文字ひとつで1バイト、つまり0から255までの数字で表現されています。

この文字と数字の対応を決定しているのが、所謂文字コードというものです。
文字化けとかの原因はこの文字コードの設定の不一致によるものですよね。

まぁ文字コードにも色々ありますが、C言語だと、半角英数にはASCIIを、全角にはシフトJISが使われます。

だから、コンピューター上で文字を表す時はこの文字コードに従って数字を入力すればいいわけです。

まぁでも流石にそれはいちいちコードを調べなくてはいけないので面倒ですよね。

という訳で、C言語では、文字は'a'という風に、'で囲ってやることで、表現できるようになっています。


文字を変数に入れる場合はchar型の変数を使用します。

例えばこんなふうに

char c = 'a';

これでaが変数cに代入されました。

この状態で出力を行うと・・・

printf("%c",c);

aという文字が出力されます。char型変数を使う際には%cを使うところはもう大丈夫ですよね。


これが文字です。

では文字列とは何でしょうか。

文字の列、文字の集まり、

つまり、abc等の二文字以上の文字の並びのことですね。

この場合の扱いはどうなるでしょうか。

実はC言語には、文字を扱う変数はありますが、文字列を扱う変数はないんです。

つまり、他の変数のような使い方はできないんです。

ならどのようにするか、という話ですが、変数を使って順列のデータを操作する方法が2種類程ありましたよね。

例えば、配列、例えば、ポインタ

こういったものがそれに該当します。

と、いうことは・・・コンピューター上では文字列はchar型の配列やポインタで表現できるということです。

つまり、配列で考えると、1要素ごとに文字列の一文字分が格納されることになるわけですね。


只、ここで気をつけないといけない点は、配列を使う際とポインタを使う際では微妙に扱いが異なってきてしまうのです。

次回は、この配列の時とポインタの時の違いをプログラムを書きながら紹介していこうと思います。

それでは今回はこの辺で。

(^・ω・)ノ RadiumProduction in RoboCup Junior
今回はポインタの続きです。

前回までで、ポインタと変数の関係についてつらつらと書いていったかと思います。

今回の記事ではここら辺を実際のプログラムを使ってもう一度書いていこうと思います。

と、いう訳で早速プログラムです。

int main(void)
{
int x=5;
int y=2;
int *p;
printf("%d",x);
printf("%p",&x);
p=&x;
printf("%d",*p);
printf("%p",p);
p=&y;
printf("%d",*p);
printf("%p",p);

return 0;
}

例えばこんなプログラムがあったとしましょう。

まず一番目のprintfでは、xの値である5が出力されるのは大丈夫ですね。

じゃあ二番目のprintfは何でしょう。

二番目のprintfは変数xのアドレスになりますので、


わかりません(笑)


変数のアドレスがどうなるかは、その時のメモリーの空き具合によって変わりますので、

プログラムを実行する度に変わってきてくるのです。

因みにアドレスを出力する際には%pを使います。

そして三番目のprintf、ここでは前にpにxのアドレスを代入していることから、これはxの値である5が出力されます。

同様に四番目のprintfは・・・xのアドレスなので此方も不明ですね。

まぁ、二番目のprintfの結果と同じ値が出力されることになります。

そして五番目、ここでは、既にpに新たな変数yのアドレスが代入されていますね。

ということは、ここで出力されるのは、yの値である2になる訳です。

同様に六番目のprintfは変数yのアドレスになります。これもxと同様に数値そのものはわかりませんが、

xのアドレスとyのアドレスが一致することはありませんので、二番目、四番目の値とは異なる値になるはずです。

また、こんなプログラムになると出力はどうなるでしょう。

int main(void)
{
int x=5;
int y=2;
int *p;

p=&x;
*p+=y;
printf("%d",*p);
printf("%d",x);

return 0;
}

このプログラムの場合、まずはポインタpに変数xのアドレスを代入しています。

そしてさらに、そのポインタpの示す値に変数yの値を加えています。

ということなので、一番目のprintfが出力するのは5+2なので7となります。

二番目はと言いますと、pにはxのアドレスがありますので、pがxのアドレスと一致している間は必ず
*p=xとなります。

よって二番目の出力も7ということになります。


こんな感じで、片方が変わればもう片方も変わる。

こういった同期する仕様になっているので、ちゃんと使えば非常に便利ですが、

やっぱり値の変動とか、そもそも今どのポインタがどの変数を示しているのか等、

一目ではわかりにくい部分がどうしても出てきてしまいます。


だから難しい、だからわからない。こうなる訳です。

まぁこれに関しては、正直慣れが一番の特効薬ではないでしょうか。

最初のうちはわかりません。常識です。でもやっていればそのうち慣れてくると思います。



さて、ここまできて一つ疑問に思うのが、「これ、何に使うんだ?」というところでしょう。

だって変数のアドレスがわかったって・・・ん?

ってなりますよね。

実はこのポインタ、例えば関数とか、配列とか、文字列とか、構造体とか、

そこら辺と兼ね合わせて使うことが殆どになります。

まぁこれらの話は後程するとして、まずは先程ちょろっと出てきた文字列や構造体について紹介していこうと思います。


まぁそんなところで今日は終了です。

(^・ω・)ノ RadiumProduction in RoboCup Junior
以前に、変数について紹介した記事があったかと思います。


その時に、変数の値を計算する場合についてのことが書かれていました。

単純な四則演算、つまり足す、引く、掛ける、割る、の4つの計算の方法ですね。


この時は、この4つの演算についてしか記述しませんでしたが、

実はC言語で行うことのできる演算はまだまだ他にも沢山あったりするのです。


今日はそのことについて紹介していこうと思います。


・・・とその前に。まずは演算子と言う言葉の話から。

演算子と言うのは、「この演算をしますよ」という一種の命令みたいなものです。例えば足し算だったら+だし、引き算だったら-になりますね。

普通の計算でもそうですが、

演算子は演算をする際には必ず必要になってくる上、行う演算によって表記も変わってきますので、

この演算子をまず理解できないと、実際にどういった演算が行われているかが理解できなくなってしまうのです。


と云うわけで、これから紹介する演算では、演算と演算子、合わせて紹介を行っていくことにします。

まぁ今回紹介するのは演算子のなかでもほんの一部、特にメジャーな演算子のみとさせていただきます。


まずはインクリメント演算子。++とかです。

これらは何かというと、要するに今の変数に1足しますよ。という命令です。実際に書いてみると、

x++;

このような感じになります。これだと、変数xに1足すと言う意味になります。

既存のxの値に1足すという命令なので、xに元々何かしらの数字が入っていないと多分エラーか警告を吐くと思います。


因みにこのインクリメント演算子、前置式と後置式がありまして、前置式は++x;、後置式はx++;と表記します。

これはまぁどちらも変数xに1を足すという意味になるのですが、実はほんのちょっとだけ意味が変わってきます。

変わってくるのは例えばこういった場合。

int X=0;

printf("%d",++x);

例えばこの場合、表示される数は、xに1足されるので1になります。


でもこっちの場合はというと・・・

int X=0;

printf("%d",x++);


なんと0になるのです。


というのも、実は++xの場合は演算を実行してからprintfにxの値を送信しているので

xは1の状態でprintfに送られているのですが、

x++の場合はprintfにxの値を送信してから演算を実行しているのです。

つまり最終的にプログラムではxの値はどちらも1になっているのに、

printfの出力結果はx++と++xで変わってきてしまうのです。

こういった演算子がインクリメント演算子です。

また、同様に--で表記するデクリメント演算子と言う演算子もあります。

これはインクリメント演算子とは真逆で、元の値から1引くと言う演算になっています。


次に紹介するのは論理演算子と言う演算子です。

論理演算子にも色々ありますが、今日紹介するのは&&と||です。

前者が論理&演算子、後者が論理OR演算子と呼ばれる演算子です。

文章で説明するのもいいですが、結構面倒なので実際のプログラムで説明します。


まずは論理&演算子です。例えば論理&演算子だとこんなプログラムが書けます。

if((x==5) && (y==2))

これだと、&&演算子を使うことで、ifの条件が、xが5のときとyが2のとき、両方が成立している場合になります。

このように、論理&演算子では、

「複数の条件が同時に成立している」という条件を作り出すことができる演算子と言うことになります。


同様に論理OR演算子の場合はこのようなプログラムが書けます。

if((x==5) || (y==2))

これだと、||演算子を使うことで、ifの条件が、xが5のときとyが2のとき、どちらかが成立している場合になります。

このように、論理OR演算子では、

「複数の条件のどちらかが成立している」という条件を作り出すことができる演算子と言うことになります。


つまり、この演算子を使うことによってROBOLABやNXT-Gでいう、複合分岐がたった一行で書くことができると言う訳です。

特にロボット等の組み込みプログラムだと、あれやこれやと意味不明な条件の複合が大量に出現しますので、

これを使用することで非常に便利にプログラムを記述することができるようになります。


と云うわけで今日は演算子と演算の紹介でした。演算にはまだまだ沢山の種類が存在しますし、

演算によって優先度なんかも発生したりしますので今後はこういった内容についても記述していこうと思います。
例えばさんすうの世界でも、+より×の方が、×より更に()の方が優先度が高いですよね。

という訳で今日の記事はこの辺で。

(^・ω・)ノRadiumProduction in RoboCup Junior
前回の記事では、ポインタってなんなんだ?というお話をしましたね。

今回の記事は、ポインタの宣言の仕方や使い方について書いていこうと思います。


まずはポインタの宣言の方法から、

例えば、ポインタpを宣言するにはこんな風に記述します。

int *p;

変数の宣言と似ていますね。というか、間に*を入れるだけです。

これで、int型のポインタpを宣言することができました。

ここで注意するところは、ポインタを宣言する際は、使用する型の扱いについてです。

これは、実際にポインタに代入するアドレスの指し示す変数の型に合わせる必要があります。

つまり、今宣言したポインタpは、int型の変数のアドレスを格納できるということになります。


次は変数のアドレスの表現方法です。

例えば、変数xのアドレスは以下のように表現できます。

&x

つまり、変数名の前に&をつけてやることで、その変数のアドレスは表現することができる訳です。

だから、ポインタpに変数xのアドレスを代入しようと思ったら、

p=&x;

となりますね。

逆に、ポインタを使って変数の値を表現することもできます。

さっきの続きで、例えば、ポインタpが指し示す変数の値を示す時は、

*p

となります。だから今度はポインタの前に*をつけてやることで、そのポインタが指し示す変数の値、

つまりこの場合、変数xの値になる訳です。


だからこの場合、xと*p、&xとpはそれぞれ同じ値を示すことになります。


まずはここがちょっとややこしいですね。変数が&でポインタが*で・・・

宣言だけでこんなややこしいのがポインタです。

Cの中でも、特に難しいと言われる理由がわかって頂けたのではないかと思います。


次回の記事では、実際にポインタを使ったプログラムを書いてみようと思います。

それではまた次回ー。


(^・ω・)ノ RadiumProduction in RoboCup Junior
今日はイオンの5%OFFの日ですね。


今回の記事はポインタについてです。

今回は一回目なので、また例の如く、ポインタってなんなんだ!?という概念的な説明を行います。


ポインタはC言語の基本のなかでは最上級に難しい部類に入りますので、

ここが理解できるかどうかで、C言語が出来るようになるかどうかが決まると言っても言い過ぎではないと思います。

というわけで内容に入る訳ですが、まずポインタの前に、アドレスというものについて紹介します。


アドレスとは、端的にいうと、変数の格納場所を示す数列です。住所みたいなものですね。

コンピューターの場合、変数は一次元で配列されていますので、

上から何番目の変数かが分かればそこが指し示す変数は一つに特定されます。

実際にはアドレスは、メモリ内における変数の値の保存場所だと思って頂ければ大丈夫です。


それでポインタというのは、そのアドレスを保存する変数という位置づけけになります。だから変数の仲間のようなものです。

このアドレスをポインタに格納することによってプログラムをもって効率的に走らせることが出来るのですが・・・

ちょっと複雑なので、今まで以上に記事を分けて紹介することになるかと思われます。

という訳で、今日の記事はこのくらいで。

最近NXTやってないなぁ。


(^・ω・)ノ RadiumProduction in RoboCup Junior
今回の記事はbitとbyteについてです。


まずはbitについて。

bitとは引数プログラムのデータに構造における最小単位のことです。

この単位は2進数でいう一桁に相当するもので、中には0か1かの数字が入っています。

なので1桁の2進数なら1bit、2桁の2進数なら2bitに相当する訳です。

だからよくプログラムでは、2進数の何桁目かを何bit目と呼ぶことが多いです。

そして、8bit、つまり2進数8個で1byteになります。

つまり2byteで16bitになる訳ですね。

これがbitとbyteの概念です。


因みにbyteの上位にwordというものもありますが、

定義が場合によって2byteだったり4byteだったりして、わかりにくいのであまり使われません。



基本的にレジスタのサイズだとか、変数のサイズだとか、

コンピューターにおけるデータのサイズはだいたいこのbitとbyteで表現されます。
HDDも○○G byteですからね。

特にレジスタにおいては、どこでもかしこでもbit単位で表記がされていますので、非常に重要になってきます。


という訳で、今回はbitとbyteについて紹介しました。

このbitとbyteにはデジタル回路だと、信号線の数にも相当させることもできます。

このことに関しましては、また今度紹介しようと思いますのでよろしくお願いします。


それではまた次回の記事でー。

(^・ω・)ノ RadiumProduction in RoboCup Junior
最近更新速度が右肩あがりなので久しぶりに思えますが、実はまだ二週間も立っていない配列の記事の続きです。

前回は、基本的な配列の使い方についての紹介を行いました。

今回は、タイトルにもあるように、配列についての実践的な使い方について紹介します。


まずはカウンタ変数を使った配列の実践例

例えば、配列の要素全てを連続で読み出したい、または書き込みたい場合に使われます。

配列の要素は数字で番号が振られていて、[ ]内に書かれますよね。

実はその数字、そのプログラム内で数字と判断できるものは何を書いてもいいんです。

従って当然、変数の名前を書いてもそれは有効なんです。

たがらこういうこともできます。

#include"stdio.h"
#define NUM 5

int main(void)
{
  int i;
  int data[NUM]


  for(i=0;i<NUM;i++)
    {
    data[i]=i;
    }

  for(i=0;i<NUM;i++)
    {
    prinft("%d",data[i]);
    }

}



このようにfor文を利用することで、いちいち全ての要素のプログラムを記述しなくとも

要素の書き込みや読み込みを連続して行うことが出来るのです。


次は関数の引数に配列を使う実践例です。

前に関数の引数の話はしましたが、普通の変数の場合は引数となった変数のデータは関数にコピーされます。

従ってどんなに関数にコピーされた引数が変更されようと、元の変数に影響はありません。


しかし、配列の場合はそうではありません。

配列の場合、要素単体を引数とする場合は変数と同じように関数側の値を変えても要素に影響はありませんが、

配列そのものを引数とする場合は、引き渡した関数側の配列の中身を変えると、元の配列の中身も変化してしまうのです。

これにはアドレスというものが深く関わっていますが、ここでは一先ず触れないことにしておきましょう。

つまりプログラムにすると、

#include"stdio.h"
#define NUM 5

void input(int a;int x[])
{
  x[1]=5;
  a=5;
}

int main(void)
{
  int i;
  int data[NUM]


  for(i=0;i<NUM;i++)
    {
    data[i]=i;
    }

  input(data[0],data);

  for(i=0;i<NUM;i++)
    {
    prinft("%d",data[i]);
    }

}

この時、関数inputの前ではdata[0]=0、data[1]=1になっていますね。

しかし、関数inputの後ではdata[0]は0のままですが、data[1]は5に変わってしまっているのです。

配列の名前が違うのでややこしいですが、配列の場合は、引数として引き渡すと、

元の配列と引渡し先の関数の配列名前は違っても要素の中身は同じになるのです。


これが配列の大きなな特徴です。これは非常に意味があって、アドレスを習ったり、配列をもっと複雑に使うようになると

この重要さが理解できるようになると思います。

因みに配列を引数として呼ぶ場合は、メイン文の方の引数の部分(実引数)は配列名だけにしてください。

それで関数の方(仮引数)は普通に配列の定義と同じように記述して下さい。一次元配列の場合は要素の所は空でも大丈夫です。



最後に紹介するのは多次元配列です。

C言語では、多次元配列と言って、配列の中に配列配列IN配列を作成することができます。

多次元配列の定義はこんな感じ。

int x [4][5];

こんな風に[]の数を後ろから増やしていく形式を取ります。これでx[4]を一つの要素とした要素5個の配列を作った訳です。

要素の総数は4×5で20個ですね。


forの2重ループで2次元平面での座標取りなんかをする場合に非常に便利です。

この他の使用方法は他の配列をまぁ大差ありません。同じように使うことができますね。

また、2次元だけでなく、3次元、4次元と、同じようにすればもっと大きな多次元配列も作成できます。



配列の実践的な用法はこんな感じでしょうか。実践と言いつつ、実用的なプログラムが一切出て来なかったのは仕様です。

「実用なんたら・・・って名前の授業ほど実用性がない」という例の高専の法則に肖ってみたつもりです。内輪ネタですね。


という訳で名ばかりの実践編は以上です。配列についてはひと通り書いたつもりですが、まだ、色々残ってはいるので、

この先もっと他の構文についての説明が終わった辺りでまた紹介したいと思います。

それでは今回はこのへんで


(^・ω・)ノ RadiumProduction in RoboCup Junior

さて、いつ以来でしょうか。

去年の後期中間で一人勝ちした電磁気以来のようですね。


という訳で配列の記事です。前回の記事は此方


前回は、配列とは、複数の変数を要素という形で同時に宣言して便利に使えるよーというものであることを説明しました。

今回は実際に配列の宣言の方法、使い方について説明します。

まずは配列xを宣言してみましょう。

配列は変数と同じように名前を持っていて、変数と同じように宣言をすることができます。


基本的な配列の宣言方法はこんな感じです。

int x[5];

これでint型の配列を5個宣言することができました。配列の型はそのまま配列の要素の型になります。

そして配列に値を入れるときはこのようにします。

x[0]=1;

これで配列xの番目の要素に1が入りました。

配列に値を入れるというより、配列の要素に値を入れるという方が正しい表現ですね。

実は配列そのものは抽象的な概念なので実体を持つものではありません。

要するに配列名(ここでいうx)というのは電車の名称で、配列の要素というのは電車の車両という訳です。

皆さんは電車に乗るとき、電車の車両に乗りますよね?車両以外の部分には乗らないはずです。

それと同じで、配列も値を代入するときには「要素」に代入するんです。

そしてここで注意するべきなのは、要素の番号です。

電車の場合は一号車、2号車という風に、番号は1から始まっていますが、

配列・・・というより一般的にプログラムの世界では、数字の始まりは0からなのです。

つまり配列も、0番目の要素、1番目の要素・・・という風になっています。


なのでint x[5];で配列を5個定義すると、使える要素は

x[0]、x[1]、x[2]、x[3]、x[4]

の5個なのです。x[5]は5番目ですが、6個目なので使えません。


まぁこれが配列で注意するべきところでしょうか。これさえわかれば配列はもう自由に使うことができると思います。


只、例えば普通の変数だと、int x=5;のように、変数の宣言と同時に初期値を代入することができましたが、

配列はint x[5]=5;で初期化はできません。値が実際に格納されるのは要素の方ですからね。

配列で宣言時に値を代入するときには次のような方法を用います。

int x[5]={0,1,2,3,4};

このように、中括弧でくくってカンマで分けます。これで0から順番に要素の初期値を代入することができます。


基本的な配列の使い方は以上です。

まぁでもこれだけだと、「複数の変数をまとめて定義出来るだけ」ですよね。

次回の記事ではこの配列のメリット、実践的な使い方について説明します。

という訳で今日はこのへんで。


(^・ω・)ノ RadiumProduction in RoboCup Junior
今日は一日中Cのプログラムで遊んでいたらいつの間にか終わっていました。

どういうことなの・・・?

因みに明日も期末試験です。教科は政経と情報

(^・ω・)ノ RadiumProduction in RoboCup Junior
全滅が危惧された電磁気ではまさかの一人勝ちをしました。



今日は久しぶりにプログラムについての記事を書いて見ることにしました。

今日は配列についてです。

まぁまずは配列ってなんぞやというお話だけして今日は終わろうと思います。

まぁ例えば、複数の値を格納しておきたい時、

普通の変数を使うとなると・・・格納したい値の数だけ変数を宣言しなくてはなりませんよね。

int a,b,c,d,e,f,g;

みたいな感じで。


でもこれ、面倒ですよね。

というのででてくるのが配列です。

配列というのは配列の名前とその配列の番号(要素)がセットになっていて、

配列を宣言すると、その配列の1番目の要素、2番目の要素、3番目の要素・・・

という感じで複数の要素が一気に定義できます。

それでその要素それぞれが全て変数となっています。


つまり複数の変数を同時に宣言できてしまう。というのがこの配列です。

本来はもっと重要な意味があるのですが、今のところはこういうことにしておきましょう。



まぁこんなのが配列です。

次の記事ではちゃんとした宣言の仕方、使い方についてお話しします。

それでは


(^・ω・)ノ RadiumProduction in RoboCup Junior
前回までのあらすじ。

前回は関数ってなんだろなーという話から進展し、

Cにおける関数作成の流れのようなものを説明致しました。

といってもなんのこっちゃかわからない説明になりましたが・・・

という訳で今日は前回告知したように、実際に適当に関数を作って説明でもしようと思います。


今日は一先ず、与えられた値の2倍の値を返すtimeという関数でもつくってみることにしましょう。地震だー

まず、関数の宣言、これはこのように宣言します。茨城北部かぁ

int time(int num);

これでint型の関数timeが宣言されました。震度3?うそこけ!

変数の宣言と似ていますよね。茨城で震度4?


因みに()内のint numですが、

これは仮引数といってmainの関数からデータを受け取るときに受け取り先となる変数です。

この関数内であれば普通の変数として使用ができます。震源は茨城南部かぁ


次に関数の定義です。今回は与えられた数を2倍にする関数なのでこのような感じになります。

int time(int num)
{
      return num*2;
}

関数はこんな感じに定義することになります。M4.1ね
returnというのは戻り値といってこの関数がmainに返す値・・・つまり結果的に示す値となります。

この場合はnum*2となっていますのでnumの値の2倍の値が返されることになります。


最後に関数の呼び出し。

このように表記されます。

x=time(x);

変数xにtime関数の値を代入するということになります。

ここで()内のxは実引数といって、ここのxの値が引数として関数の方に(ここでは変数numに)送られます。



ここでこれを実際のプログラムにしてみましょう。23区は震度3ですね

このような感じになります

#include "stdio.h"

int time(int num);

int main(void)
{
      int x;
      printf("xの入力");
      scanf("%d",&x);
      x=time(x); 
      printf("x=%d",x);
      return0;
}

int time(int num)
{
      return num*2;
}


外部から整数xを入力することで、xの2倍の数を表示するプログラムになります。

まず関数timeを最初に宣言して、次にmain関数がきて、その中で変数xを定義、scanfで入力、

そして関数timeを呼び出します。そして関数time内で引数として送られてきたxの値を変数numに代入し、

そのnumの値を2倍したものを関数timeの値としてreturnでmain関数に返します。

それをまたxに再代入して、pirntfで出力しています。


とりあえず関数の使い方としてはこんな感じです。

また、複数の変数を引数として使いたい場合は

int time(int a,int b)

のような具合にプログラムします。

また、変数と同じように戻り値として使用したい数字の型によって関数の型を変更することができます。

戻り値を使わない関数の場合はvoid型という型を使用することも出来ます。

というわけで関数の説明は以上になります。


次は・・・なんだろう、配列ってやったっけ?(笑)

配列かポインタのどちらかになるかと思われます。

それではまた。

(^・ω・)ノ RadiumProduction in RoboCup Junior
此方も一ヶ月以上経過していますね(笑)

とりあえず前回のお話は関数って何?という定義的なことを説明した、よくわからない内容でした。

今日はCにおける関数の作り方ということで書かせて頂きます。


C言語における関数というのは、所謂命令の塊のようなものです。


例えば、関数にaという数字が入ると、様々な動作をして、最終的にbという値を返す。みたいな関数もあれば

関数にcという数字が入るだけでdのような処理をする。というような関数もあります。

ロボットでいうと、前者がセンサーの値を取得する関数。後者がモーターを動かす関数等に例えられますね。

今まで普通に使っていたセンサーの値を取得する命令や、モーターを動かす命令といったものも

まぁ要するにすべて関数だと、云う訳です。

まぁそんな関数ですが、関数はいったいどうやって作ってどうやって使うのか。

これは基本的に3つのプロセスに分けて考えられます。


まずは関数の宣言。

このプログラムでは、このような関数を使いますよー、ということを最初に定義する必要があるのです。

まぁこの定義を宣言と言ったりするので関数の宣言と表記しています。


次が関数の定義

上の定義とごっちゃになりますが、此方の定義は関数そのものの定義です。

この関数はどういった関数なのか。どういう動作をするのかということを定義する関数です。

つまり、モーターの関数ならモーターを動かすのに必要な命令が、

センサーの関数ならセンサーの値取得に必要な命令がすべて詰まっているという訳です。

関数制作の上で一番の中心となっているのがこの部分でしょう。


そして最後は関数の呼び出し。

これは簡単で、関数を使いたい時に使う呼び出しです。

ROBOLABだったらあのタイルその物がそれに該当するし、NCXだったらOnFwd等の文章全てがそれに該当します。

C言語においては、これは関数名を使って呼び出すことになるので、

関数宣言や定義のところで決めることになる関数の名前はとても重要になってきます。



まぁここまで聞けばわかるでしょうが、実はROBOLABってプログラミングソフトというより、

関数の呼び出しを羅列するだけのソフトだったりするんですね。
まぁ普通はどんなソフトでもそうなんですが・・・ROBOLABは特にその傾向が・・・


だからROBOLABはあまり関数そのものを作ったりすることには適していないような作りになっています。

まぁできなくもないといえばできなくもないんですけどね。ROBOLABだと新たに関数を作るメリットは少ないかな・・・

ROBOLABは普通のプログラミングソフトとはだいぶ異なり、

ジャンプ主体になりがちなのでどっちかっていうとアセンブラに近いプログラムになるんですよね。

C言語の概念とはまた違ったものでプログラムを組む必要があるので

ROBOLABからのCの乗換は結構大変だったりします。逆にNXT-Gからの方が楽かもね。



まぁという感じで関数の組み方のお話は以上です。


といってもこれじゃなんのこっちゃかわかりゃしないので次の記事で実際に関数をC言語で作ってみようと思います。

それでは。

(^・ω・)ノ RadiumProduction in RoboCup Junior
ずいぶん前になりますが、前回のプログラムの記事の中で、ヘッダのお話をいたしました。

これはどういうものかというと、ディレクティブのひとつで、#includeというものがあったと思うのですが、

これを使って別のファイルから関数を読み出す・・なんてことを書きました。

今日はその関数ってなんぞやという話です。


関数というのは、元々函数という漢字で書かれていて(函館の函ですね)

その名の通り何かを入れる函という意味のものです。(現在では函が当用漢字でなくなったため関になりました。)

数学的な定義を言うと、「ある変数に依存して決まる値、あるいはその対応を表す式」ということになります。
数の集合に値を取る写像、という定義の方が今は使われるようですが、
色々説明要素が多そうなので上のもので説明することにします。


某ライなんとかさんがそれを提唱して、今ではそれが一般化、様々なものに応用されてきています。

例えばsinとかcosとかtanとか、logとかΣとか∫とか、こういったものは全て関数です。

もっと簡単にいえば、y=ax+b。せんけー方程式の、一次方程式の一般式ですね。

これは、定数a、bが分かっていれば、変数yの値は変数xに依存して決定されます。

こんなことは小学校でもやる常識ですが、このy、これは実は関数なのです。

上記した、関数の定義、「ある変数に依存して決まる値、あるいはその対応を表す式」

ここでのある変数というのがx、依存して決まる値というのはy、

そしてその対応を表す式というのはy=ax+bという式そのもの。

つまりyは関数であることが分かります。

そしてyはxによって変化されます。なのでyとxの関係を示すために「yはxの関数」と言うのが一般的です。

そしてその関数の中の式、つまりyの中身を表す式がy=ax+bとなるわけです。

だって=というのは数学では等価という意味ですからね。


これが本来の関数というものです。

そしてこれはプログラムにも応用されています。

プログラムでは主に関数はプログラムの簡略化、高速化、小型化等を目的としていて、

数学の関数と違い、プログラムでの関数というものは、「関数の作成」が主となっています。

数学では、一般の人は既存の関数を使って計算をすることが殆どですからね。

そもそも今の時代だと数学での関数の作成→プログラムでの関数の作成という構図ができていますから、

プログラム使わずに関数を作るなんてことはそうそうないでしょう。それってもう数学の概念を作ることに等しいですからね。
上記したものも含め、数学上の一般的な関数はもう概念といってもいいようなものばかりですよ(笑)


なんて話はさておき、プログラムでは、そういった関数を自分で作るということが非常に大切になってくるわけですね。

とりあえず今日の記事はこれくらいにしておきましょう。

次の記事ではちゃんとした関数の作り方を紹介しようと思います。

(^・ω・)ノ RadiumProduction in RoboCup Junior
今日の記事はプリプロセッサについてです。

プリプロセッサってなんでしょう、という話から始まるのですが、

別に難しいものではありません。

というより、C言語を齧ったことがあって、この単語を知らない人は、

十中八九名前を知らずに使っている場合が殆どでしょう。

Cの場合(でなくとも)、使わないとほとんど何もできないに等しいですからね。



ところで、これは何かというと


・・・。

コンパイラです。

というより今のコンパイラに付属されている機能といった方が正しいでしょう。

じゃあこのプリプロセッサはどういう機能なのかと言いますと、「ある処理を実行する機能」という答えになります。

では、それはどういう処理かと言いますと、

例えば、
#include

例えば、
#define

このあたりがC言語だと一番有名でしょうね。(というより主なものを挙げるとこれしかないような・・・)

まぁあとは#ifとか#ifdefとかその類のものがあったり・・・します。

どちらも単体で意味は知っていたりするものでしょうね。



#includeは日本語にすると、「含む」とか「組み込む」という意味になります。

これは要するに別のファイルで定義した関数や定数等をプログラムで使いたいときに使用するものですね。

例えばプログラム内に、#include"stdio.h"

と書くと、stdio.hのファイル内に定義された関数等をそのプログラムで使用することができます。

この.hの拡張子のファイルはプログラムにおける、定義ファイルのようなもので、

ライブラリファイルとかヘッダファイルなどと呼ばれています。

ここにC言語の時と同じように関数や定数を定義することで、プログラムの方で#includeを記述すると

プログラム内でヘッダファイルで定義した関数等が使えるようになるというものです。

ただヘッダを作る際には場合によって、環境変数をいじらなくてはならないのでちょっとめんどくさいです。

ちなみに記述方法は2通りあって、

#include"ヘッダ名"

#include<ヘッダ名>

の2通りです。どちらでも意味は変わりません。


また、#defineは日本語にすると「定義」になります。これはそのままの意味、つまり定数を定義するのもので

#define X 10

などと書くことで数字を文字に置換することができるものです。

プログラム内にこれを記述することで、そのプログラム内ではXという文字は数字の10と同様の扱いになります。

例えば上の#defineと変数xが定義されたプログラムなら、

if(x==10)と、

if(x==X)は、同一のものとなります。



まぁこのような処理を行うものをプリプロセッサといいます。

これには大体最初に#が入っているのですぐにわかるようになっていると思います。

まぁなんでこれらが総称して、このように呼ばれているかと言いますと、

プリプロセッサに該当するものはすべて、プログラムをコンパイルした時に、

ソースそのものがコンパイルされる前に、「前処理」という形で処理されます。

まぁ要するに一番最初にコンパイルされる、という言い方が分かり易いでしょうか。(ちょっと違う気がするけど・・・)

この「前処理」を英訳すると、

前→pre

処理→process

前+処理=pre+process=preprocess

これを名詞にしてみると→preprocessor

∴ プリプロセッサという訳です。


また、このプリプロセッサを行う命令、

つまり#include#defineのことをディレクティブとか言ったりします。(この単語絶対使わないな・・・)


というわけで今日は前処理についてのお話でした。

このディレクティブについてですが、

基本的に関数の外、プログラムの一番上に宣言部としてまとめて宣言するのが通例ですね。


ちなみに僕の場合、このディレクティブ、宣言部だけで

副部長のプログラムの総量(約140行)を超えています(笑)



(^・ω・)ノ RadiumProduction in RoboCup Junior
最後に残ったC言語の主な条件文がこのswitch文です。

ちょっと前に紹介したif文の派生系みたいなものでしょうか。

基本的なswitch文のプログラムはこんな感じになります。


#include <stdio.h>
int main(void)
{
     int x;
     printf("数字を入力してください。");
     scanf("%d",&x);

     switch(x){
  
       case 1:
       printf("入力された数字は1です。/n");
       break;

       case 2:
       printf("入力された数字は2です。/n");
       break;

       case 3:
       printf("入力された数字は3です。/n");
       break;

      default:
       printf("1、2、3以外の数が入力されました。/n");
      }

     return 0;
}


数字を入力し、それが1か2か3だったら「入力された数字は~です。」と出力し、

それ以外の数字なら、「1、2、3以外の数が入力されました。」と出力するプログラムです。

switch文はこのようにcaseというものとセットで使います。

switchのカッコ内に入れた値とcaseと:の間に入れた値が等しければ、

それ以下のプログラムを実行するようになっています。

なのでxの値が1ならcase1以下の文を、2ならcase2以下の文を、3ならcase3以下の文を、それぞれ実行します。

xの値がcaseのどれにも該当しない場合はdefault以下の文を実行することになります。

このdefaultは省略することもできます。

そして最後にbreak;をつける。これがswitch文の定型となります。(defaultには無くても良い)


このbreak;という文ですが、これはbreak文といって、これもひとつの構文になっています。

これはどういう命令かというと、「一番中側の中括弧から抜ける」命令です。

例えばさっきのswitch文ですが、

あのプログラムでは例えば、case1のときの処理とcase2の間にbreakがありました。

あのプログラムだと、case1の処理が終わったら、breakを使って、switch文の中括弧から抜け出ているのです。

もしあそこでbreakをいれなかったら、xの値が1だったときに

case1の処理を行った後でcase2の処理を行ってしまうことになります。

もっと単純な例を出すと、whileでの無限ループの例、

int x=0;
while(1){
     if(x==100)
           break;
     x++;
}

このようなプログラムがどこかにあったとします。

これはwhile文で無限ループをしていますが、xが100になると、if文に入って、breakします。

つまり、このwhileループを抜けでるのです。

このようにbreakはswitch文以外でも、様々な条件文で使用することができます。


「一番中側」という定義があるのは、

こういった場合は、永遠にループから出られないということです。

int x=0;
while(1)
{
      while(1)
      {
           if(x==100)
            break;
      x++;
      }
}

中側のループはbreakで出られますが、直ぐ外側のループによってまた戻ってしまいますからね。


このような文がbreak文です。似たようなもので、continue文というものがあります。

これはbreakと逆で、ループの一番最初に戻ると言う構文です。

なのでプログラム内で、これがあれば、一番中側の中括弧の部分の一番最初に戻ると言うわけです、

つまりこれも無限ループです。


#include <stdio.h>
int main(void)
{
     int x;
     printf("数字を入力してください。");
     scanf("%d",&x);

     switch(x){
  
       case 1:
       printf("入力された数字は1です。/n");
       continue;

       case 2:
       printf("入力された数字は2です。/n");
       continue;

       case 3:
       printf("入力された数字は3です。/n");
       continue;

      default:
       printf("1、2、3以外の数が入力されました。/n");
      }

     return 0;
}

最初に1,2,3以外の数字を入力しないと、無限にループします。

コンパイラによってはこれだとエラーがでるかもしれませんけど・・・

こっちはbreakと違って、結構使いどころが限られそうな構文ですね。


とりあえず今日はswitch文とbreak文とcontinue文についての紹介でした。


次は・・・フリプロセッサかなぁ。まぁなにかしら紹介すると思います。


それでは今日はこの辺で・・・


(^・ω・)ノ RadiumProduction in RoboCup Junior
条件文の続きです。

今日は前回の予告通りに「何回ループを行うか」というループを、

while文やdo~while文より簡単に作れる条件文を 紹介します。


その条件文の名前はfor文。

while文やdo~while文と同じようなル―プ形の条件文です。


ちょっと簡単なプログラムを書いてみましょうか。

#include <stdio.h>
int main(void)
{
     int i;
     for(i=1;i<=5;i++){
           printf("%d回目のループです。/n",x);
      }
     return 0;
}

例えば、こんなプログラム。

これは前回のwhile文の時にサンプルとして書いた、

このプログラムと同じ出力結果になります。


#include <stdio.h>
int main(void)
{
     int i;
     i=1;
     while(i<=5){
           printf("%d回目のループです。/n",x);
           i++;
      }
     return 0;
}


確かこれの出力結果は

1回目のループです。
2回目のループです。
3回目のループです。
4回目のループです。
5回目のループです。

となりましたよね?

上のfor文を使ったプログラムでもこれと同じ出力結果になります。

上のプログラムと下のプログラム、結果的には同じですが、書き方は全然違います。

じゃあまずどこが違うかを探してみましょう。

まずループに入る前のi=1;つまり最初にiに数字を入れる代入の式の有無があります。

while文ではありますが、for文にはありません。


その代わり、for文の条件の括弧の中に似たようなものがありますよね。

for(i=1;i<=5;i++){

この一番左の部分に

そしてこの真ん中の部分はwhile文の時の条件と同じであることがわかります。

そして一番右、i++というものですが、これはwhile文のどこかで見覚えがありませんか?


while文の下から4行目にありますよね?i++;って。確かこれはiに1を足すという、

インクリメント演算子とかいうやつでした。

これ、for文の方ではありませんよね?


違いといえば、こんなものでしょうか。この違いはどういうことかといいますと、

つまりwhile文で回数ループを行うときは、プログラム内で最初のiの値を代入する文を書いたり、

ループごとにiの値を増やすような文を個別に書かなくてはなりませんでした。


でもfor文では、それを一個一個代入したりする文をプログラム内に書く必要はなく、

全部for文の条件の中にまとめてかけるという訳です。

ここでもう一回for文の条件の部分を確認しましょう。

for(i=1;i<=5;i++){

このようになっていて、i=1とi<=5とi++がセミコロン(;)で分けられていました。

これはそれぞれ全く別の命令を示していて、

一番左の部分は「初期化」の部分と言われ、ループ前の変数の値を定義します。

そして真ん中の文がwhile文と同じ条件の文になります。

この「iが5以下である」という条件が成立する間この文を繰り返すという命令になります。

そして一番右端がループ内の処理が1回終わるごとに行う命令を記述する部分です。

今回はここにi++とありますが、これによって、このループ処理が一回行われるごとにiに1足していく処理になります。


要するにこのプログラムの場合、ループは最初i=1の状態でスタートし、iが6になるまでループを繰り返します。

そして一回ループ内の処置が終わるごとに、iの値が1ずつ増えていくようなプログラムになるのです。


これがfor文の基本構造です。

また、条件の確認の位置はwhile文と同じになるので、図にするとこのようになります。
for文の構成です。while文と全く同じですね。
実はwhile文の使いまわしだったり(笑)

とりあえずfor文は駆け足でしたが以上で終了です。


次はもうひとつだけ条件文を紹介します。

今度はif文を発展させたようなものになります。

それではー。

(^・ω・)ノRadiumProduction in RoboCup Junior
今日はなんとなくプログラムの記事の続きを書こうという気分になりました。

前回のif文の記事で記載したように、 今日はwhile文について、

それとよくwhile文と対をなして示されることの多いdo~while文について書こうと思います。

これらもif文と同じように、条件文の1種なのですが、if文はある条件が成立したらこっちの文、しなかったらこっち・・・

という風に「分岐」を作る条件でした。

でもこれからやるwhile文やdo~while文は「ある条件が成立している間この文を繰り返す」という

繰り返し、ループを作る条件文になります。


例えばこんな感じで、

#include <stdio.h>
int main(void)
{
     int i;
     i=1;
     while(i<=5){
           printf("%d回目のループです。/n",x);
           i++;
      }
     return 0;
}


またはこんな風に、

int main(void)
{
     int i;
     i=1;
     do{
           printf("%d回目のループです。/n",x);
           i++;
      }while(i<=5)
     return 0;
}


この二つのプログラムはどちらも実行の結果は

1回目のループです。
2回目のループです。
3回目のループです。
4回目のループです。
5回目のループです。

という風になります。

iが1から5の間、つまり5回分ループ回数の表示を行うプログラムです。

whille文で変数iの値と、5という数字を比較して

iの方が小さければ{ }内の命令文を繰り返すようなプログラムになっています。

iの方が大きい場合は、{ }内の処理は行われなくなるので、{ }の下のプログラムに移動します。

といってもこのプログラムの場合、return 0; とあるのでこのままプログラムは終了します。


因みに7行目のi++;という命令は変数iに1を足す。という命令で、この++をインクリメント演算子といいます。

逆の--というのもあってこれはデクリメント演算子といいます。

今、上のプログラムと下のプログラムは同じだという説明をしました。

whileとdo~while、違うものを使っているはずなのに同じになるなんておかしくありませんか?

同じになるならなぜ2つも同じものがあるのだろう。まぁこれにはちょっと訳がありまして、


この二つにある違いがあるのですが、このプログラムでは、その違いが出力結果に表れないのです。

じゃあ違いを出すにはどうするか、こうすればでてきてくれますよ。

#include <stdio.h>
int main(void)
{
     int i;
     i=10;
     while(i<=5){
           printf("%d回目のループです。/n",x);
           i++;
      }
     return 0;
}




int main(void)
{
     int i;
     i=10;
     do{
           printf("%d回目のループです。/n",x);
           i++;
      }while(i<=5)
     return 0;
}


この2つのプログラム、どこが変わったかといいますと、4行目。

i=1;がi=10;に変わっています。つまりどちらの条件式も満たさない、

つまり当てはまらないようなiの値をあらかじめ示したという訳です。


この場合、上のプログラムの実行結果は




つまり何も実行されないのですが、下のプログラムの場合、このように出力されます。

10回目のループです。

条件に当てはまっていないのに条件文内のプログラムが1回だけ実行されています。

これの原因は条件を調べるタイミングが大いに関係しています。

ちょっと図を使いましょうか。

これがwhile文の構成です。

while文の構成です。
まず最初に条件を確認し、条件が成立するなら、下の条件文を実行し、赤矢印を通って条件の確認に戻ります。

この時、条件が不成立になった時は青矢印を通って条件の外の文にジャンプします。これがwhile文です。


ところがdo~while文はこのようになっています。
do~while文の構成です。

do~while文では、先に条件内の文を実行してから、条件の確認を行い、

条件が成立すれば赤矢印のように条件内の文の最初に飛びます。

不成立の場合は青矢印のようにそのまま下の文を実行します。

つまりdo~while文はwhile文と違い、条件がどうであろうと、最低一回は必ず条件内の文を実行するのです。

これが2つの違い、先程のプログラムの出力結果の違いの訳です。



これがwhile文とdo~while文です。

また、while文の使い道としては、こんなのがあります。

#include <stdio.h>
int main(void)
{
     while(1){
           printf("お腹がすきました。/n");
      }
     return 0;
}

このプログラムは

お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
お腹がすきました。
(以下無限)

という出力、つまり無限ループを行うプログラムです。

なぜ条件の部分に1を入れると、こうなるのでしょうか、

C言語では、1というものは「真」というものを意味していて、これは「常に正しい」という意味と捉えることができます。

なので条件の中に 1 とだけ入れておくと、「この条件は常に正しい」という意味になります。

常に正しいのだから、ずっと繰り返し続ける→無限ループ、という訳です。

因みに0は「偽」、常に正しくないという意味を持っていますのでこれを条件に入れちゃうと・・・


因みにこれはdo~while文でも、もちろん行ううことができます。

以上でwhile文とdo~while文の説明は以上です。

次もまた条件文の説明です。今度は先程の一番最初のプログラムで説明したような、

変数を条件とするとこで指定した回数ループを行うようなプログラムをもっと作りやすくするための条件文を紹介します。


それでは今日はこの辺で。

(^・ω・)ノRadiumProduction in RoboCup Junior
カレンダー
07 2019/08 09
S M T W T F S
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
最新CM
[09/25 ONE RoboCuper]
[11/19 big]
[11/11 お馬さん]
[08/08 うまごやぐらし!]
[04/20 匿名(にさせてw]
かうんた
らじぷろ目次
らじぷろ検索機
プロフィール
HN:
Luz
年齢:
25
性別:
男性
誕生日:
1994/02/15
職業:
大学生
趣味:
ラボ畜
自己紹介:
初めまして。Luzと申します。
某大学の情報学科に入りました。のんびりと生活を送るのが今年の夢です。
めーる
radiumproduction☆yahoo.co.jp
※☆を@に変更して下さい。
バーコード

PR

忍者ブログ 2007-2018,Powered by Radium-Luz-Lα+-Rescatar in RadiumProduction [PR]


Related Posts Plugin for WordPress, Blogger...