[Powered by Google Translate] [レビュー] [クイズ0] [レキシー·ロス、トミーMacWilliam、ルーカス·フレイタス、ジョセフ·オング] [ハーバード大学] [これはCS50です。] [CS50.TV] ねえ、みんな。 この水曜日行われているクイズ0の場合、レビューセッションへようこそ。 今夜はやろうとしている、私は、他の3つのTFSと一緒だ と一緒に、我々はこれまでのコースで何をしたのかを審査を通過しようとしている。 それは100%包括的であることを行っていないが、それはあなたの良いアイデアを与える必要があります あなたは既にダウンして持っているものの、何あなたはまだ水曜日の前の勉強する必要があります。 そして、私たちは一緒になるだろうとの質問に手を上げて自由に感じる しかし、我々はまたで少し時間がなければならないということを覚えておいてエンド 我々は、一般的な質問を行う - にスペアするために数分とを介して取得した場合、 そうということを忘れないでください、と私たちは週0で先頭から開始するつもりです。 [パート0] [レキシー·ロス] [0レビュー!クイズ]しかし、我々は、やる前にレッツトークに関すること クイズの物流。 [物流] [クイズ講義の代わりに水曜日10月10日に行われます] [(詳細はhttp://cdn.cs50.net/2012/fall/quizzes/0/about0.pdfを参照してください)​​]これは、10月10日(水曜日)にあります。 つまり、今週の水曜日だし、ここで次のURLにアクセスしている場合、 これはまたへのリンクCS50.net-そこ 'sからアクセス可能であること、 あなたは、に基づいて、どこに行ったらよいかについての情報を参照することができます あなたの姓や学校提携と同様に それは約まさにクイズがカバーする、あなたが得ようとしていることを質問の種類に伝えます。 あなたはまた、セクションでクイズについてのレビューする機会がなければならないということを覚えておいてください ので、あなたのTFは、いくつかの練習問題の上に行くべきである そしてそれはあなたがまだクイズを補う勉強する必要がある場所を確認するために別の良い機会です。 ビット 'n'のバイトで最初からスタートしてみましょう。 少しばかりの0または1であることを覚えている とバイトは、これらのビットの8の集合です。 右ここにこのビットのコレクションを見てみましょう。 我々はいくつあるかのビットを把握することができるはずです。 ここで、我々は、そのうちの8はちょうどそこの8つの0または1台を数える。 それ以来8ビット、1バイトだが、そこ とのは、16進数に変換してみましょう。 進は、ベース16であり、それは変換するのはとても簡単です バイナリ内の数字は、これは16進数の数値に、それが何であるかです。 我々が行うすべては、我々は4つのグループを見ている そして我々は適切な16進数字に変換します。 私たちはそう0011、4の一番右のグループで開始します。 それはとても共に3にかなっている、1 1、1 2になるだろう。 そして、4の他のブロックを見てみましょう。 1101年。つまり、1 1、1 4、1 8になるだろう。 一緒にDを作る13日になるだろうという そして、我々は、16進数で我々だけで、0〜9を行っていないことを覚えているだろう。 我々は、そう〜9、10に対応した後、Fを介して0に行く Bに11、Fは15であるとcetera。 ここで13は、Dである ので、それは我々が行うすべては、我々実際に10進数に変換する 2のべき乗として各位置を扱う。 それは、とcetera、4S 1 1、1 2、ゼロ、ゼロ8S、1つの16だ そしてそれはあなたの頭の中で計算するのは少し難しいですが、私達は次のスライドに移動した場合 我々はその答えを見ることができます。 基本的に我々は、右から左に戻ってから渡って行っている、 そして我々は2の対応力によって、各桁を乗じている。 そして、覚えている進のために、我々は先頭に0xでこれらの数値を示す ので、我々は10進数で、それを混同しないでください。 に引き続き、これは、ASCIIテーブルです そして我々はASCIIを使用する何文字から数値にマッピングすることです。 暗号のpsetで覚えている私たちは、ASCIIテーブルを多用しました 暗号化のさまざまなメソッドを使用するためには、 シーザーとVigenère暗号は、別の文字を変換する ユーザーによって指定されたキーに応じて文字列インチ のは、ASCII数学を少し見てみましょう。 Qあろう文字の形で、 "P"に+ 1を見ると、 と'5 '≠5を覚えています。 そして、どのように正確に我々はそれらの2つの形式の間で変換するだろうか? これは、実際にはあまりにも難しいことではありません。 5を得るために、我々は'0 'を引く' '0 'の間に5つの場所があるので、'と'5が。 ' 、我々は単に0を追加し、他の道を行くために 定期的な算術のようなものだそれはそう。 何かがそれを囲む引用符がある場合、それが文字だということだけを覚えている したがって、ASCIIコード表の値に対応する。 より一般的なコンピュータ科学のトピックに移動します。 我々は、我々が使用しているものプログラミングアルゴリズムがあり、どのように学んだ アルゴリズムを実装する。 アルゴリズムのいくつかの例は、のような本当にシンプルな何かです 数値が偶数か奇数かどうかをチェックする。 そのために我々は数を2でMODと結果が0かどうかチェックを忘れないでください。 もしそうなら、それもあります。そうでなければ、それは奇妙だ。 そして、それは本当に基本的なアルゴリズムの例を示します。 もっと関わっ1の少しは二分探索であり、 その我々がレビューセッションの後半で上に行くよ。 とプログラミングは、我々はアルゴリズムを取るために使用される用語です それはコンピュータをコードに変換することは読むことができます。 プログラミングの2つの例は、スクラッチです これは、我々は0週目にやったことです。 我々は実際にコードを入力していないにもかかわらず、それは実装の方法だ 数字は1から10まで印刷されているこのアルゴリズムは、 そしてここでは、Cプログラミング言語で同じことを行う。 これらは、単に別の言語や構文で書かれた、機能的に同等です。 次に、ブール値表現について学んだ とbooleanは、trueまたはfalseのいずれかの値です そしてここにしばしばブール式 もしそうであれば(X≤5)、条件の中に入り、 まあ、我々はすでにその条件がtrueに評価しようとしているx = 5で、ように設定してください。 それが本当なら、どんなコードでは、条件の下にある コンピュータによって評価されようとしているので、その文字列が印刷されようとしている 標準出力、および長期的条件に if文の括弧の中にある何を指します。 すべての演算子を忘れないでください。 、我々は2つ​​以上の条件を結合しようとしているとき|それを覚えている&&と| ==しない= 2物事が等しいかどうかを確認する。 ==ブール演算子であるのに対し、=は代入のためのものであることを覚えておいてください。 ≤、≥、その後最後の2は自明です。 ここでブール論理の全般的な見直し。 とブール式は、ループ内でも重要である その私たちが今以上行くよ。 私たちはしばらくのために、CS50でこれまでのループの約3種類を学び、やってます。 ほとんどの用途にしながらそれを知っておくことが重要です 私たちは実際に、一般的にループの任意の型を使用することができます 目的の特定の種類、または共通のパターンがあります 具体的には、これらのループの1つのために呼び出すプログラミングに それを作ることが最も効率的か、その方法でそれを記述するのがエレガント。 のは、これらのループの各々が最も頻繁に使用される傾向にあるものを渡って行こう。 forループでは、一般に、すでに我々は反復処理する方法を何度も知っている。 それは我々が条件に入れたものだ。 例えばのために、i = 0のときは、i <10、。 我々はすでに我々が何かを10回やってみたいことを知っています。 さて、whileループのために、一般的に我々は必ずしもない 我々は、ループが実行する方法を何度も知っている。 しかし、我々は、我々はそれがしたいという条件のいくつかの並べ替えを知っていますか 常に真であるか、常にfalseになる。 例えば、一方が設定されます。 レッツは、ブール変数だと言う。 それが本当なら、私たちは、コードを評価する一方で、 もう少し拡張可能で、forループよりも一般的な少しは、そう しかし、forループはまた、任意のwhileループに変換することができます。 最後に、すぐに理解することが最も難しいかもしれないループ、、やってます 我々は最初のコードを評価したい場合によく使用されている 初めての前に我々は状態を確認してください。 DO WHILEループの一般的なユースケース あなたがユーザー入力を取得したいときのものであり、あなたがユーザーに聞きたい知っている 入力のため、少なくとも一度は、しかし、彼らはあなたに良い入力を与えていない場合、直ちに あなたは彼らがあなたに良い入力を与えるまで、それらを求めておきたい。 whileループの中で最も一般的な用途は、それを行うだ そして、これらのループの実際の構造を見てみましょう。 彼らは通常、常にこれらのパターンに従う傾向がある。 内部用のループ上では、3つのコンポーネントがあります: 初期化、一般的に何かのようにint型私iはカウンタ= 0、 私たちはこの状態がまだ生きていている限り、このforループを実行して言いたい条件、 我々はどのようにインクリメントされ、最終的に次にi <10、かつ、更新、のような ループ内の各点でのカウンター変数。 そこを見るために、一般的なことは、ちょうど私が+ +は これは1で毎回iをインクリメントを意味します。 また、私+ = 2のような何かができる これは、iには、ループを通過するたびに2を加えることを意味します。 そして、これは実際には単なるループの一部として実行される任意のコードを意味しな​​い。 とwhileループのために、この時間は、私たちは実際には、ループの外で初期化を持っている そう、たとえば、のは、我々は、私が今説明したようループの同じタイプをやろうとしているとしましょう​​。 我々は、intはi = 0のループが始まる前に言うでしょう。 私は<10これを実行しながら、我々は言うことができる、 以前のようにコードのように同じブロック、 そして今回はコードの更新部分を、例えば、i + +は、 実際には、ループの内部に入る。 そして最後に、のために、それはwhileループに似ていながらやる、 しかし、我々はコードが一度評価されることを覚えておく必要があり 条件がチェックされる前なので、それは多くの方が理にかなっています あなたは上から下への順に見れば。 あなたも、while条件を見る前にループのコードが評価されながらやるで whileループのに対し、それは最初にチェックします。 ステートメントと変数。 我々は、新しい変数を作成したい場合は、まずそれを初期化したい。 たとえば、intバーが可変バーを初期化し、 それが今ではバーの値が何であるかので、値を与えていないのですか? 我々は知らない。 それは、以前にそこにメモリに格納されていたいくつかのゴミ値にすることができます そして我々は、その変数を使用する必要はありません 我々は実際にそれに値を与えるまで、 ので、我々はそれをここに宣言します。 その後、我々はそれが42以下であることが、初期化します。 さて、もちろん、我々は、これは1行目は、intバー= 42で行うことができます知っている。 しかし、ちょうど、起こっている複数のステップをクリアする 宣言と初期化は、ここでは別々に起こっています。 これは、1つのステップで行われ、次の1、INT = bazにバー+ 1 ので、このコードブロックの末尾に以下のこのステートメントは、その増分bazで、 私たちはバズの値を出力した場合、それは44だろう 我々は1>バーであることがそれを宣言して初期化しているため、 それから私達はでもう一度それをインクリメント+ +。 我々は、この非常に簡潔に渡ったが、それは一般的なを持って良いことだ 何であるスレッドやイベントの理解。 私たちは、主に、スクラッチでこれを使った そのため、複数のコードシーケンスとしてスレッドと考えることができます 同時に実行されている。 実際には、それはおそらく、同時に実行されていない しかし抽象的に一種の私たちはそのように考えることができます。 スクラッチでは、例えば、我々は複数のスプライトを持っていた。 それは同時に異なるコードを実行する可能性があります。 他の何かを言っている間に一つは歩くことができた 画面の別の部分インチ イベントには、ロジックを分離する別の方法です あなたのコードの異なる要素間、 とスクラッチで我々は、ブロードキャストを使用してイベントをシミュレートすることができました 私が受信すると、それは、私が聞こえない場合は、実際の が、本質的には、情報を送信する方法です 1つのスプライトから別。 たとえば、あなたがゲームを介して送信することもできます と別のスプライトはゲームオーバーを受信したときに、 それは特定の方法で応答します。 これは、プログラミングのために理解すべき重要なモデルだ。 ただ基本的な週0上に行くために、私たちはこれまで以上に行ってきた、 この簡単なCのプログラムを見てみましょう。 テキストはここから少し小さいかもしれませんが、私はその上に本当に速い行くつもりです。 我々は、上部の2ヘッダファイル、cs50.hとstdio.hをインクルードしている。 次に100と呼ばれる定数上限を定義しています。 次に私たちの主な機能を実装している。 我々はここでコマンドライン引数を使用しないので、私たちはvoidを配置する必要があります メインの引数として。 我々は、メイン上記のint型を参照してください。戻り値の型だね、それ故に下部に0を返します。 そして、我々はint得るCS50ライブラリ関数を使用している ユーザに入力を求め、私たちはこの変数xに格納するには、 ので、我々は上記のxを宣言し、そして我々は、x =場合、getIntを使用して初期化します。 我々は、ユーザーが私達によい入力を与えたかどうかを確認します。 それは≥LIMITの場合、私たちは、1のエラーコードを返すとエラー·メッセージを出力したい。 そして最後に、ユーザーが私達に与えられている場合、良好な入力 我々は数を二乗し、その結果をプリントアウトするつもりだ。 ちょうどそれらのすべてのヒットホームていることを確認する あなたはここでコードの異なる部分のラベルを見ることができます。 私は定数、ヘッダファイルに言及した。 ああ、int型xになります。ローカル変数であることを覚えていることを確認してください。 我々はについて話しますグローバル変数、からそれを対比し、その 少し後でレビューセッションで、 そして我々は、printfライブラリ関数を呼び出している 我々はstdio.hヘッダファイルが含まれていなかったので、もし 我々は、printf呼び出しすることができないだろう。 そして、私は、ここでオフ斬っ矢印は%dを指していると信じて これは、printf関数の書式文字列です。 それが数%dは、この変数をプリントアウトと言います。 そして、それは0週のためのそれである。 今すぐルーカスは継続する予定です。 ねえ、みんな。私の名前はルーカスです。 私は、キャンパス、マザー上で最高の家の中で二年生だ そして私は1週目と2.1について少しお話します。 [第1週と2.1!] [ルーカス·フレイタス] 我々はゼロからのC言語にあなたのコードを翻訳し始めたときにレクシーは、言っていたように、 私たちが気づいたことの一つは、あなただけではなくできることです あなたのコードを書いて、それはもう緑のフラグを使用して実行します。 実際に、あなたのCプログラムを作るためにいくつかの手順を使用する必要が 実行ファイルになります。 基本的には、プログラムを書いているときには何をすべきかというです あなたは、コンパイラが理解できる言語にあなたのアイデアを翻訳 ので、あなたがC言語でプログラムを書いているときに あなたが実際にあなたのコンパイラが理解しようとしていることを何かを書いているものをやっている、 その後、コンパイラはそのコードを変換しようとしている お使いのコンピュータが理解できるものに。 との事は、お使いのコンピュータは、実際には非常に間抜けである。 お使いのコンピュータでのみ、0と1を理解することができます ので、実際には最初のコンピュータで人々は通常、プログラムさ もう0と1ではなく、使用して、神に感謝します。 我々は、0と1の配列を覚える必要はありません forループまたはwhileループのためののように。 我々はコンパイラを持っている理由です。 どのコンパイラが行うことは、それは基本的にCのコードを変換している 私たちのケースでは、コンピュータが理解できる言語に、 どのオブジェクトコードであり、我々が使用しているコンパイラ 打ち鳴らすと呼ばれていますので、これは実際に打ち鳴らすためのシンボルです。 あなたのプログラムを持っているときは、2つのことを行う必要があります。 まず、あなたのプログラムをコンパイルする必要がありますし、あなたのプログラムを実行するつもりだ。 あなたのプログラムをコンパイルするには、そのための多くのオプションを持っている。 一つ目はカーンという音は、program.cを行うことです れているプログラムは、プログラムの名前です。 このケースでは、彼らはちょうど言っている見ることができる "ねえ、私のプログラムをコンパイルします。" あなたは、または何も "私は私のプログラムのためにこの名前にしたい"と言っていない。 二つ目のオプションは、あなたのプログラムに名前を与えている。 その後、打ち鳴らす-oとすることも、任意の名前と言うことができます 実行ファイルは、ファイルとして、次にprogram.cを名付けられる。 そして、あなたはまた、プログラムを作るのですか、そしてどのように最初の2つのケースでは見ることができます 私はCを入れて、3分の1に私はプログラムを持っている? ああ、あなたは実際に置くべきではありません。cをあなたが作るを使用するとき。 そうしないと、コンパイラは、実際にあなたに向かって怒鳴り起こっている。 君たちは覚えていれば、また、私は知らないが、 しかし、多くの時間は、我々はまた、または-LM-lcs50を使用していました。 それはリンクと呼ばれています。 それはちょうど、あなたがすぐそこにこれらのライブラリを使用することをコンパイラに指示します あなたはcs50.hを使用したいので、もしあなたが実際に入力する必要が カーンという音は、program.c-lcs50。 あなたがそうしない場合、コンパイラは知っているつもりされていません あなたはcs50.h.でこれらの関数を使用していること そして、あなたはあなたのプログラムを実行するときに2つのオプションがあります。 あなたはカーンという音は、program.cを行った場合、あなたのプログラムに名前を与えていない。 は。/ a.outを使用して、それを実行する必要があります。 a.outはあなたがそれに名前を付けない場合はカーンという音があなたのプログラムを提供し、標準の名前です。 あなたのプログラムに名前を与えたそれ以外の場合は。/プログラムをやろうとしている、 あなたがやった場合と、プログラムが取得しようとしていることをプログラム名を成す すでにcファイルと同じ名前をプログラムすることになるだろう。 その後、我々は、データ型とデータについて話しました。 基本的にはデータ·タイプは、彼らが使用する小さな箱と同じものです 値を格納するため、データ·タイプがちょうどPokémonsのように実際にされています。 彼らはすべてのサイズと種類があります。 そのアナロジーは理にかなっているかどうかは分からない。 データサイズは、実際にはマシンのアーキテクチャに依存します。 私がここで紹介するつもりですすべてのデータサイズ 私たちのアプライアンスの場合は32ビットマシン用に実際に だけでなく、あなたが実際にあなたのMacをコーディングしている場合、またはWindowsで おそらくあなたは、64ビットのマシンを持っているつもりです ので、私はここに紹介するつもりですデータサイズということを覚えておいてください 32ビットマシン用です。 我々が見たことが最初のものは、int型であった これはかなり簡単です。 あなたは、整数を格納するintを使う。 また、文字は、charを見ました。 あなたは手紙や少し記号を使用する場合は、おそらくcharを使用するつもりです。 charは、レキシーが言ったように8ビットを意味し、1バイトを持っています。 基本的に我々は256を持っているASCIIテーブルを持っている 0と1の組み合わせ、 そしてその後は、charを入力したときにそれが翻訳するだろう 文字が入力していますあなたレキシーのように、ASCIIテーブルに持っている数は言った。 また、私たちは小数を格納するために使用するフロートを持っています。 あなたは、例えば、3.14を選択したい場合は、floatを使用するつもりだ 以上の精度を持っている二重。 floatは4バイトを持っています。 doubleは8バイトを持っているので、唯一の違いは精度です。 また、整数に対して使用され、長いを持っている 、あなたは、32ビットマシンintと同じサイズでなければ長い間見ることができます ので、実際に32ビットマシンでlongを使用する意味がありません。 Macと64ビットのマシンを使用している場合でも、実際に長い、サイズ8を持っている ので、実際にアーキテクチャに依存します。 32ビットマシンの場合、それは本当に長いを使用しても意味がありません。 そして、長い長い間、その一方で、8バイトを持っている あなたが長い整数を持つようにしたい場合ので、非常に良いです。 そして最後に、我々は、実際にはchar *である、文字列を持っている これはcharへのポインタです。 これは、文字列のサイズがどのようになるだろうことを考えると非常に簡単です あなたがそこに持っている文字の数、 しかし実際にはchar *自体 4バイトであるchar型へのポインタのサイズを持っています。 char *のサイズは4バイトです。 あなたは小さな単語または文字か何かを持っているかどうかは関係ありません。 これは、4バイトになるだろう。 我々はまた、キャスティングについて少し学んだ あなたが持っている場合は、例えば、言うプログラムを見ることができるように int型のx = 3のその後のprintf( "%d"は、X / 2) あなたたちは、それが画面上に印刷するために何が起こっているか知っていますか? 誰か?>> [生徒] 2。 1 >> 1、うん。 あなたは3月2日を行うと、それは、1.5を得るために起こっている 我々は整数を使用しているので、それは、小数部を無視するようになるだろう 、あなたは1点を持っているつもりです。 例えば、あなたが何ができるか起こることを望まないのであれば floatを宣言されてy = xと。 3次になるために使用さxはyに3.000であることを行っている。 そしてあなたは、y / 2を印刷することができます。 実は、私は2を持っている必要があります。あそこ。 それは、3.00/2.00をやろうとしている そしてあなたは、1.5を取得するつもりだ。 そして、我々だけ小数部の2進数の単位を求めるために、この0.2 fを持っている。 あなたが0.3 fを持っている場合、それは実際に1.500を持つようになるだろう。 それが2であればそれは1.50になるだろう。 また、ここで、このケースを持っています。 あなたは、floatを行う場合、x = 3.14とその後のprintf X あなたは3.14を取得するつもりだ。 そして、あなたが行う場合、xのx = int型、 intとしてxを扱うことを意味し、あなたが今、xを印刷先 あなたは3.00を持っているつもりです。 それは意味をなさないか? あなたは、最初の整数としてxを扱っているので、小数部を無視しているので、 してから、xを印刷している。 そして最後に、あなたはまた、これを行うことができます int型の場合、x = 65、あなたはchar cを= xを宣言する その後は、cを印刷する場合は、実際に取得するつもりだ ので、基本的にここで何をやっている、 、文字に整数を翻訳している 同じようにASCIIテーブルはありません。 また、算術演算子について話しました。 それらのほとんどは非常に簡単ですので、+、 - 、*、/、 また、我々は、2つの数値の除算の余りであるMOD、について話しました。 例えば、あなたが10%3をお持ちの場合 それが3で10を割ることを意味し、残りの部分は何ですか? それは1になるだろうので、それは多くのプログラムのために実際には非常に便利です。 Vigenèreとシーザーのために私はあなたたちのすべては、modを使用したことをかなり確信している。 *と/を組み合わせたときの数学の演算子については、十分に注意すること。 たとえば場合は、(3/2)* 2あなたは何を得ようとしているのですか? [生徒] 2。 うん、2、3/2は1.5であることを行っているので、 しかし、あなたは2つの整数の間の操作をやっているので、 あなたは実際にちょうど1を検討するつもりだ、 その後1 * 2は2であることを行っているので、非常に、非常に注意してください ので、整数で演算を行う場合、 あなたは、その場合には、その2 = 3を得る可能性があります。 また、優先順位について非常に注意してください。 あなたは通常、あなたが何をやっているか知っていることを確認するために括弧を使用する必要があります。 いくつかの便利なショートカットは、当然のことながら、1は、i + +やi + = 1である または使用して+ =。 つまり、I = I + 1をやってと同じものです。 また、私が行うことができます - またはi - = 1、 これは、私は= I -1と同じものです 何かあなたたちは、少なくとも、forループで多くを使用します。 また、*のために、あなたが使用している場合* =と、例えば、あなたが行う場合 I * = 2 I = I * 2を言うのと同じことですが、 除算のと同じこと。 あなたは、i / = 2を行う場合、それはI = I / 2と同じことだ。 今関数について。 君たちは関数は、コードを保存するために非常に良い戦略であることを学ん あなたがプログラミングしている間なので、同じタスクを実行したい場合 コー​​ドの中で何度も何度も、おそらくあなたは、関数を使いたい ちょうどので、何度も繰り返しのコードをコピー&ペーストする必要はありません。 実際、メインは関数である、と私はあなたに関数の形式を表示するとき あなたはそれが非常に明白であることを確認するつもりだ。 我々はまた、いくつかのライブラリの関数を使用 例えば、printfは、CS50ライブラリからですGetIn、 やtoupperなどの他の機能。 これらの機能のすべては、実際には、他のライブラリに実装されています そして、あなたのプログラムの初めにそれらテザーファイルを置くとき あなたは私にそれらの関数のコードを記入してくださいすることができますと言っている ので、私は自分でそれを実装する必要はありませんか? そして、あなたはまた、あなたがプログラミングを開始するときに、独自の関数を作成することができます あなたは図書館があなたが必要とするすべての機能を持っていないことを認識しています。 最後のpsetには、例えば、我々は、スクランブルを描画して、ルックアップ書いた そして、それは関数を記述することができるように、非常に、非常に重要です 彼らは有用であり、我々はプログラミングのすべての時間にそれらを使用しているため、 そしてそれは、多くのコードを保存します。 関数の形式はこの一つです。 我々は最初に戻り値の型を持っています。戻り値の型は何ですか? それはあなたの関数が返すために起こっているときだけだ。 、階乗、例えば、あなたが機能を持っている場合 つまり、整数の階乗を計算するために起こっている おそらく、それはまた、整数を返すために起こっている。 戻り値の型はintになるだろう。 printfの実際の戻り値の型voidを あなたは何を返していないので。 あなただけの画面に物事を印刷している その後、関数を終了する。 そして、あなたは、あなたが選ぶことができる関数の名前を持っている。 あなたは、xyzのような名前を選択しないように、少し理性的であるべきだ またはX2Fような。 理にかなって名前を作ることを試みて下さい。 例えば、それは階乗の場合、階乗と言う。 それは何かを描画しようとしている関数とすれば、それを描くという名前を付けます。 そして、我々はまた、引数と呼ばれるパラメータを、持っている あなたの関数が必要とするリソースと同様にどのアール 独自に作成したコードから、そのタスクを実行することができます。 あなたは、数値の階乗を計算したい場合 おそらくあなたは、階乗を計算するための数値を持っている必要があります。 あなたが持って行っていることのいずれかの引数が数値そのものです。 そしてそれは何かをすると終了時に値を返すことになるだろう それはvoid関数でない限り。 例を見てみましょう。 私は整数の配列内のすべての数値を合計する関数を記述したい場合は、 まず第一に、戻り値の型はintであることを行っている 私は、整数の配列を持っているからです。 そして私は、sumArrayのような関数の名前を持っているつもりです そして、次に、それは、int型numsに、配列自体を取るつもりです その後、私は合計する必要がありますどのように多くの数字知っているので、配列の長さ。 それから私は0に、例えば、和と呼ばれる変数を初期化する必要があり、 と私は、配列内の要素を参照するたびに、私は合計に追加する必要がありますので、私はループのためにした。 レキシーが言ったように、あなたがやるのint i = 0のときは、i <長さとi + +。 と配列のすべての要素のために、私は合計+ = nums [i]のをやった、 その後、私は和を返したので、非常にシンプルだし、それは多くのコードを保存します あなたは、この関数を多くの時間を使っている場合。 その後、我々は条件を見ていた。 我々は、if、else、および他の場合があります。 それらの間の差であるのか見てみましょう。 これらの2つのコードを見てみましょう。それらの違いは何ですか? 最初のものは、基本的にしているコードは、お伝えしたいと思います 、または0 - 数は+である場合。 最初のものは、それが> 0の場合、それはポジティブだと言う。 それは0〜=の場合、それは0だし、それが<0の場合、それは否定的なのです。 そうでなければ、もしそうでなければ、あれば、もう一つはやっている。 両者の違いは、この1つは実際に起こっているということです チェックした場合> 0、<0または= 0三回、 あなたは数字の2を持っているそうだとすれば、例えば、それはここに来ると言うことになるだろう (X> 0)場合、それはイエスと言うために起こっているので、私は肯定的な印刷されます。 しかし、私はそれが> 0であることを知って、それが0または<0であることを行っていないにもかかわらず、 私はまだ何をするつもりだ、それが0である、それは、<0である ので、私は実際に私がする必要がなかったことをIFSの内側に行くよ 私はすでにそれがこれらのいずれかの条件を満たすことはないだろうことを知っているので。 私は他に、他の場合は、if文を使用することができます。 x = 0の私は肯定を印刷する場合、それは基本的に述べています。 それがない場合は、私もこれをテストするつもりです。 それが2なら、私はこれを行うつもりはない。 私はx = 2を持っていた場合、基本的にあなたは言うでしょう (x> 0の)場合は、[はい]を、ので、これを印刷してください。 今、私はそれは> 0であることを知っていることと、その場合には、まず満足 私もこのコードを実行するつもりはない。 あなたがこれを使用する場合のコードは3倍の速さ、実際には、高速に実行されます。 また知り、かつまたは。 レキシーは既にそれらについて話しましたので、私はこれを通過するつもりはない。 | |演算子それだけで&&とです。 私は言うだろう唯一のことは、3つの条件を持っている場合は注意があります。 それは非常に混乱するだから、条件を持っているときに括弧を使用します そして別の1つまたは別の1。 ちょうどあなたの条件は意味をなさないことを確認するために、括弧を使用します その場合には、例えば、あなたが想像できるので、その それは、最初の条件と1つまたは他のかもしれない または2に結合された条件と または3分の1は、これだけは注意してください。 そして最後に、我々はスイッチについて話しました。 変数を持っている場合、スイッチは非常に便利です。 Let 'sは、あなたがnのような変数を持っていることを言う それは、0,1、または2であり、それらの例ごとにすることができます してタスクを実行するつもりだ。 あなたは、変数を切り替えると言うことができます、そして、それはことを示しています 次に、この値が、value1のように私はこれを実行するつもりである そして私は私が他のいずれかの場合を見てするつもりはないことを意味し、破る 我々はすでにそのような場合を満たしているため その後value2とのように、私もデフォルトのスイッチを持つことができます。 それは私が持っていた場合のいずれかを満たさない場合を意味します 私は何か他のものをするつもりですが、これは必須だということ。 それは私のためにすべてです。今度はトミーを持ってみましょう。 すべての権利は​​、これは3週目っぽいことになるだろう。 これらは私たちがカバーすることでしょうトピックのいくつか、暗号化、スコープ、配列、エトセトラです。 クリプト上だけで簡単に単語。我々は、この家を酷使するつもりはない。 我々は、pset 2でこれを行っていましたがクイズのために、違いを知っていることを確認 シーザー暗号とVigenère暗号の間に、 どのようにこれらの暗号の仕事をどのように処理し、暗号化するようなものだ両方 それらの2つの暗号化方式を使用して復号化テキスト。 覚えておいて、シーザー暗号は単に、同じ量で各文字を回転させる アルファベットの文字の数でいいMODを作る。 とVigenère暗号は、一方では、各文字を回転させる 異なる量だけ、そうではなく、言って 3Vigenèreですべての文字を回転させ、各文字を回転させます いくつかのキーワードに応じて、異なる量だけ キーワードの各文字は、いくつかの異なった量を表し によってクリアテキストを回転させる。 変数のスコープについての最初の話してみましょう。 変数の2つの異なるタイプがあります。 我々は、ローカル変数を持っており、これらは、定義しようとしている メインまたは任意の関数やブロックの外側の外、 これらはあなたのプログラムのどこにアクセスできるようになります。 あなたは、関数を持っていて、その関数内でwhileループである場合 大きなグローバル変数はどこでもアクセス可能です。 ローカル変数は、他の一方で、それが定義されている場所にスコープが設定されます。 あなたがここに関数がある場合、例えば、我々は、この関数gを持っている とgの内部にyと呼ばれるここで変数が存在する そしてそれは、これはローカル変数であることを意味します。 この変数は、yと呼ばれるけれども、 そしてこの変数は、これら2つの関数をYと呼ばれる お互いのローカル変数が何であるか見当がつかない。 一方、ここまで我々は、int x = 5で言う これは、任意の関数の範囲外である。 これは、メインの範囲外なので、これはグローバル変数です。 またはx + +は - 私はxを言うとき、それは、これら2つの関数のその内部を意味 私は、このyとこのyは違う変数でありそれによって、同じxにアクセスしています。 グローバル変数とローカル変数の違いはあります。 限り設計が懸念している、時にはそれはおそらく良いアイデアだ いつでもあなたはおそらく可能な変数をローカルに保持するために グローバル変数の束を持って以来、本当に混乱して得ることができます。 あなたが関数の束を持っている場合はすべて同じものを修正する あなたは、この関数が誤ってこの地球を修正した場合にどのような忘れてしまうかもしれません そしてこの他の機能は、それについては何も知りません あなたがより多くのコードを取得するように、それはかなり混乱するかもしれません。 いつでもあなたはおそらく可能な変数をローカルに保存する ちょうど良いデザインです。 アレイは、覚えて、単に同じ型の要素のリストである。 CIの内側には、hello、1、2.0のようなリストを持つことができません。 私達はちょうどそれを行うことはできません。 我々はC言語で配列を宣言するときにすべての要素が同じタイプである必要があります。 ここで私は3つの整数の配列を持っている。 ここでは、配列の長さを持っていますが、私はちょうどこの構文で宣言している場合はどう ここで私は、すべての要素は、私は技術的にはこの3は必要ありませんが何であるかを指定します。 コンパイラは、配列がどの程度の大きを理解するのに十分スマートです。 今私は、配列の値を取得または設定したいとき これはそれを行うための構文です。 覚えている、ので、これは実際に、配列の2番目の要素を変更します 番号は1からではなく、0から始まります。 私はその値を読み込みたい場合は私のようなものを言うことができます。int x =配列[1]。 または私はここでやっているように私は、その値を設定したい場合は、 私は、[1] = 4の配列を言うことができます。 それらのインデックスで要素にアクセスするその時 またはそれらの位置やどこが配列内にある、 そのリストには、0から始まります。 我々はまた、配列の配列を持つことができます これは多次元配列と呼ばれます。 我々は、多次元配列を持っているとき 我々は、行と列のようなものを持つことができることを意味し これは、これを可視化する、またはそれを考えるのはただ1つの方法です。 私は必要が開始するつもりだ意味の多次元配列を持っているとき 私はグリッドを持っている場合ので、2つ以上のインデックス ちょうどあなたが何行目にいると言って私達に番号を与えるものではありません。 それは本当にちょうど私達に番号のリストを与えるために起こっている。 Let 'sは、私はここで、この配列を持っていると言う。 私はグリッドと呼ばれる配列を持っている、と私はそれの2行3列を、言っている ので、これはそれを視覚化するための一つの方法です。 私は[2] [1]にある要素を取得したいと言うとき これらは、最初の行、次に列であるため、ことを意味します 私は1を言ったので、1行目にジャンプするつもりです。 それから私は、列2にこっちに来るつもりです、と私は値6を取得するつもりです。 感覚を作る? 多次元配列は、覚えている、ただ技術的には、配列の配列です。 我々は、配列の配列の配列を持つことができます。 我々は考えるべき本当に一つの方法が、続けることができます これがレイアウトされていて、何が起こっている方法は、それを視覚化することです。 このようなグリッドインチ 我々は関数に配列を渡すとき、彼らは行動するつもりだ 我々は関数に通常の変数を渡すときよりも少し違った intやfloatを渡すように。 我々は、intやcharまたはこれらの他のデータ·タイプのいずれかに渡すと 私達はちょうど関数が変更される場合を見てみた 変化が伝播するまでするつもりはないことを、その変数の値 呼び出し元の関数に。 配列を使用して、その一方で、それは起こります。 私はいくつかの関数に配列を渡すと、その関数は、要素のいくつかを変更した場合 私はそれを呼び出した関数まで戻ってくるとき 私の配列には、現在は別のになるだろうし、そのための語彙です 我々は後で見るようである配列は、参照によって渡されます。 これはどのようにポインタの仕事は、これらの基本的なデータ型に関連している 一方、値によって渡されます。 我々は、いくつかの変数のコピーを作成してから、そのコピーを渡すようなことを考えることができます。 それは我々がその変数に何をするかは問題ではありません。 呼び出し元の関数は、それが変更されたことを意識することはありません。 アレイは、その点で少しだけ異なっています。 先ほど見たように、たとえば、メインは、単に関数です それは2つの引数に取ることができます。 メイン関数の最初の引数はargcであるか、または引数の数、 二番目の引数はargvと呼ばれ そしてそれらは、これらの引数の実際の値である。 Let 'sは、私がthis.cと呼ばれるプログラムを持っていると言う そして私はこれを作ると言うと、私は、コマンドラインでこれを実行するつもりです。 今、私のプログラムにいくつかの引数を渡すために、これを呼ばれる 私は何かのように言うことができます/これはCS 50です。 これは、我々は端末で毎日デヴィッドが何を想像するものです。 そのプログラムのしかし、今のmain関数の内部 これらの値を持っているので、argcは4です。 本当に我々はだけで渡しているので、それは少し混乱するかもしれないCS 50です。 それがわずか3です​​。 しかし、覚えているargvの最初の要素または最初の引数 関数自体の名前です。 だから我々はここに4つの事を持っていることを意味し、 最初の要素は、。/このことを行っている。 そして、これを文字列として表現さ​​れます。 その後、残りの要素は、我々はプログラムの名前の後に入力した内容です。 だから余談として、我々は、おそらくpsetの2で見たように、 ストリング50は整数50≠されていることを覚えています。 だから我々は、のような何か言うことはできない 'ます。int x = ARGV 3。' それはちょうど、これは文字列であるため、意味をなさないことはないだろう、これは整数です。 あなたが覚えて、2の間で変換したければ、我々はするつもりだ atoi関数と呼ばれるこのユニークな機能を持っています。 これは文字列を受け取り、その文字列の内部表現された整数を返します。 だから、クイズにするのは簡単間違いだ ただ、これは自動的に正しい型であることを考える。 しかし、これらは常に文字列になることだけを知っている 文字列だけで、整数または文字やfloatが含まれている場合でも。 だから今の時間を実行する方法について説明しましょう​​。 我々はすべてのこれらの狂気の事をするすべてのこれらのアルゴリズムを持っている場合、 それは、質問をするのは本当に便利になる "彼らはどのくらい時間がかかりますか?" 我々は、漸近記法と呼ばれるものであることを表しています。 よく、のは、我々は我々のアルゴリズムを与えることとしましょう​​ - だから、これはことを意味します いくつかの本当に、本当に、本当に大きな入力。 我々はどのくらいの時間がかかるとしている "、質問をしたいですか? それは、実行する私たちのアルゴリズムをどのように多くの措置を講じます 入力の大きさの関数としての? " だから我々は実行時間を記述することができます最初の方法は、ビッグOである そしてこれが私たちの最悪の場合の実行時間である。 だから我々は配列をソートしたい、と我々は我々のアルゴリズムの配列を与える場合 それは昇順でなければならないときには、降順での それは最悪のケースになるだろう。 これは、我々のアルゴリズムにかかる時間の最大の長さにバインドされている私たちの上限です。 一方、このΩはベスト·ケースの実行時間を記述するために起こっている。 だから我々はソーティングアルゴリズムにすでにソートされた配列を与えれば、 それをソートするためにどのくらいの時間がかかるのだろうか? そして、これは、その後、実行時間の下界を説明しています。 そこでここでは、いくつかの一般的な実行時間を記述するだけで単語がいくつかあります。 これらは昇順に並んでいます。 我々が持っている最速の実行時間は一定と呼ばれています。 我々は我々のアルゴリズムを与えるどのように多くの要素に関係なく、意味ないこと 私たちの配列がそれを並べ替え、どのくらいの大きさに関係なく または我々は配列にやっているものは何でもやって、常に同じ時間がかかります。 だから我々は定数1で、というだけのことを表すことができます。 また、対数の実行時に見えた。 だから二分探索のようなものが対数的である、 ここで我々は半分のたびに問題をカット その後の事はそこから高くなる。 そして、あなたは今までに何階乗アルゴリズムのOを書いているのであれば、 あなたはおそらく、あなたの一日の仕事としてこれを考慮するべきではありません。 我々は実行時間を比較したときに、それはこれらの事を心に留めておくことが重要です。 私はO(n)のアルゴリズムは、他の誰かを持っている場合 これらは実際に漸近的に等価であるO(2n)のアルゴリズムを持っています。 だから我々は百億兆万のような大きな数になるようにnを想像するなら: 私たちは百億兆万のようなもの+ 3に百億兆万を比較しているときに、 突然その3は本当にもう大きな違いを生むことはありません。 我々はこれらの事が同等であることを考慮して開始しようとしている理由です。 ここで、これらの定数のようなものだから、そこに2×これです、または3を追加 これらは単なる定数であり、これらは、最大ドロップしようとしている。 これらの実行時間のすべての3つは、彼らはO(n)だと言うように同じである理由ようだ。 我々が2つの他の実行時間があれば同様に、はO(n³+2 N²)は、我々が追加することができたとしましょう + N、+ 7、それから私達はちょうどはO(n³)の別の実行時間を持っています。 これらの同じではありません - これらがあるため、再び、これらは同じものです。 これらには、申し訳ございませんが、同じものです。したがって、これらは同じであるため、 このn³がこの2n個の²を支配しようとしている。 我々はO(n³)とはO(n²)のように時間を実行した場合はどうすればよいということではありませんすることは、 このn³がこのn²をよりはるかに大きいからです。 我々は指数を持っているなら、突然これは問題を開始し、 しかし、我々はここにアップしているように我々だけの要因を扱っているときに、 それは彼らがちょうどドロップアウトしようとしているので問題ではないだろう。 のは、我々がこれまで見てきたいくつかのアルゴリズムを見てみましょう とその実行時の話。 我々が見たリストの番号を探しているの最初の方法は、線形探索であった。 と線形探索の実装は超簡単です。 我々は、単にリストを持って、私たちは、リスト内のすべての単一の要素を見ていくつもりです。 我々は我々が探している番号を見つけるまで。 だから、最悪の場合には、これはO(n)のことを意味し。 要素がある場合、ここでは、最悪の場合は次のようになります。 最後の要素は、線形探索を用いて、我々は、一つ一つの要素を見ている 我々はそれがリストに実際にあったことがわかるように、最後の1に到達するまで。 我々は、ちょうど途中あきらめると言うことはできませんが、 "それはおそらくないです。" 線形探索で、我々は全体のことを見なければなりません。 ベストケースの実行時間は、他の一方で、定数である 最良のケースで我々が探している要素は、リストの中の最初のものであるためです。 だから、正確に1ステップ、リストがどんなに大きくて私たちを取るために起こっている 我々は最初の要素のたびに探している場合。 ですから、検索、覚えているとき、それは私たちのリストがソートされている必要はありません。 我々は、単に一つ一つの要素を上に見ていくつもりです、そして、それは本当に問題ではないので どのような順序、それらの要素インチアール よりインテリジェントな検索アルゴリズムは二分探索のようなものです。 あなたがしようとしているときのことを覚えて、二分探索の実装です リストの中央を見続ける。 私たちは中央を見ているからと、我々はリストがソートされていることを必要とする あるいは真ん中がどこにあるか我々は知らない、と我々は上を見ている それを見つけるために全体のリストと、その時点で我々は、単に時間を無駄にしています。 weは、ソートされたリストを持っていると我々は真ん中を見つけたらそこで、我々は真ん中を比較するつもりだ 私たちが探している要素へ。 それは高すぎるなら、私たちは右半分を忘れることができます 我々は、もし我々の要素が既に高すぎることを知っているので、 そしてこの要素の右側にすべてが、さらに高くなる それから私達はもうそこに見える必要はありません。 どこでその一方で、我々の要素が低すぎる場合には、 私たちは、その要素の左に、すべてがあまりにも低すぎる知る ので、実際にどちらか、そこを見ても意味がありません。 このように、リストの中間点で一歩一歩、私たちが見るたびに付き、 突然、私たちが知っているので、我々は半分に我々の問題をカットするつもりだ 我々が探しているものにすることはできません数字の全体の束。 擬似コードでは、これは、このような感じでしょう そして我々は半分毎回でリストを切断しているため、 対数に対して直線的からの私達の最悪の場合の実行時にジャンプします。 だから、突然、我々は、リスト内の要素を検索するために、ログの手順を持っています。 ベストケースの実行時間は、しかし、まだ一定である 今ので、ちょうど我々が探している要素があるとしましょう 元のリストは、常に正確なミドル。 そこで、我々は我々が望むほどの大きさ私たちのリストを育てることができますが、我々が探している要素は、中間にある場合 それが唯一の問い合わせ1歩を踏み出すことになるだろう。 weはO(log n)とΩ(1)または定数にいる理由ようだ。 実際にこのリスト上のバイナリ検索を実行してみましょう。 だから我々は要素164を探しているとしましょう​​。 我々がやろうとしている最初のものは、このリストの中間点を見つけることです。 それはちょうどので、中間点は、これら2つの数値の間に入るために起こっていることが起こる ので、中間点が2つの数値の間に入るたびに、ちょうど任意に言ってみましょう ただ切り上げてみましょう。 私達はちょうど私達がこの方法のあらゆるステップを行うことを確認する必要があります。 だから我々は切り上げするつもりだ、と我々は161が私達のリストの途中であることを言おうとしている。 だから、161 <164と161の左側にあるすべての要素 また、<164であるので、我々はそれがすべてで私たちを助けに行くのではないことを知っている 我々が探している要素が存在することはできませんのでこっちを見て開始します。 ですから、私たちにできることは、我々だけで、リストのその全体の左半分を忘れることができますです そして今だけ161以降の右側から検討してください。 そして再び、これは中点です。のがちょうど切り上げましょう。 今すぐ175は大きすぎます。 だから我々は、それは、私たちはここやここを見て支援するつもりはないと知っている ので、我々はちょうどその捨てることができ、最終的には164を打つでしょう。 二分探索で何か質問はありますか? 既にソートされたリストを検索してから移動しましょう 実際に任意の順序で番号のリストを取ることに と昇順に、そのリストを作る。 我々が見た最初のアルゴリズムはバブルソートと呼ばれていました。 そして、これは我々が見たアルゴリズムの単純になるはずだ。 バブルソートは、リスト内の任意の2つの要素が場違いである場合と言う 数値が高いほど、より低い番号の左側にあることを意味し、 その後、我々はそのリストがあることを意味しているので、それらを交換するつもりだ それは以前より "もっとソート"。 そして、私たちはもう一度、もう一度、もう一度、このプロセスを継続する予定としている 最終的にはそれらの要素が正しい場所にバブルのようなものと我々はソートされたリストを持っているまで。 これの実行時間はO(n²)であることを行っている。なぜですか? まあ、最悪の場合には、我々はすべての要素を取るつもりですので、と 我々はリスト内の他のすべての要素と比較する羽目になるだろう。 しかし、最良のケースでは、我々はすでにソートされたリストを持って、バブルソートの 一度だけ通って行く、と言う "いや、私は、どのスワップを行っていないので、私は終わりだ。" だから我々はΩ(n)のベスト·ケースの実行時間を持っています。 リスト上のバブルソートを実行してみましょう。 または第一、本当にすぐにいくつかの擬似コードを見てみましょう。 私たちは、ループの反復ごとに、追跡するためにしたいと言いたい 我々は、任意の要素を変更したかどうかを把握しません。 そこらの理由は、我々はすべての要素を交換していないときに停止するつもりされています。 それで、我々のループの開始時に我々は何を交換していないので、我々は偽だと言うでしょう。 今、我々はリストを通過し、iは要素i + 1に要素を比較するつもりだ それは小さい番号の左側に大きな番号があること事実である場合、 私たちはただそれらを交換するつもりです。 そして、我々は、我々はエレメントを交換していることを覚えておくつもりだ。 それは我々がリストを介して少なくとも1つのより多くの時間を移動する必要があることを意味します 全体のリストが既にソートされているときに我々は停止している状態であるため、 我々は任意のスワップ取引を行っていないという意味。 'いくつかの要素が交換されているが。 "だからここになぜ我々のダウン状態ですつまり だから今はただリストに載っているこのランニングを見てみましょう。 私はリスト5,0,1,6,4を持っています。 バブルソートでは、左側にすべての道を開始しようとしている、それは比較するために起こっている iは要素なので、0〜I + 1、要素1です。 、それは、よく5> 0を言おうとしているが、今の5は左に ので、私は5と0を交換する必要があります。 私はそれらを交換するとき、突然、私は、この別のリストを取得します。 今すぐ5> 1、私たちはそれらを交換するつもりです。 5> 6ではないので、我々はここでは何もする必要はありません。 しかし、6> 4ので、交換する必要があります。 再び、我々は最終的に発見するために全体のリストを介して実行する必要が これらの順序があることを、我々はそれらを交換、 この時点で我々はリスト1を介してより多くの時間を実行する必要が すべてがそのためにだし、この時点バブルソートで終了したことを確認します。 いくつかの要素を考慮し、それらをソートするための異なったアルゴリズムが選択ソートです。 選択ソートの背後にある考え方は、我々はリストのソートされた部分を構築しようとしているということです 一度に1つの要素。 そして、我々はそれをやろうとしている方法は、リストの左側のセグメントを構築することです。 そして、基本的に、すべての - 各ステップで、我々は残されている最小の要素を取るつもりだ それはまだソートされていない、と私たちは、ソートされたセグメントに移動するつもりです。 つまり、我々は継続的にソートされていない最小の要素を見つける必要があります し、その最小の要素を取ると何と交換し ソートされていない最も左の要素。 これの実行時間があるため、最悪の場合にはO(n²)であることを行っている 我々は、他のすべての要素に一つ一つの要素を比較する必要があります。 我々は、リストの左半分で開始した場合、我々が必要と言っているので 最小の要素を見つけるために全体の右のセグメントを通過する可能性があります。 その後、再び、我々は全体の右のセグメント上に行く必要があり、 何度も何度も繰り返していること以上続ける。 つまり、n²となるだろう。我々は、forループの別の内側のforループが必要になるだろう これは、n個の²を示唆している。 最良のケースの思想では、のは、我々はそれをすでにソートされたリストを与えるとしましょう​​; 我々は実際のn²よりも良くはしない。 選択ソートは、ことを知る方法がありませんので 最小要素は、ちょうど私が見てすることが起こるものです。 それはまだ、これが実際に最小であることを確認する必要があります。 そして、このアルゴリズムを使用して、それが最低限だことを確認する唯一の方法は、 再び一つ一つの要素を見ることです。 だから本当に、あなたがそれを与える場合 - あなたが選択ソートをすでにソートされたリストを与えると、 それは、まだソートされていないリストを与えるよりも良い結果を出すことはないだろう。 ところで、それは何かがO(何か)である場合であることを起こる場合 と何かのオメガは、私達はちょうどより簡潔に、それが何かのθだと言うことができます。 あなたがどこでも出てくることがわかりそうだとすれば、それはそれだけで何を意味するかだ。 何かがn²のシータであれば、それはビッグはO(n²)とΩ(nの²)の両方です。 最良のケースと最悪のケースだから、それは、違いを確認していません アルゴリズムは、同じことをするたびに何をしようとしている。 だから、これは選択ソートの擬似コードのように見えることができるものである。 私たちは基本的に私はリストを反復処理することを言おうとしている 右に、ループの各繰り返しで左から、私は移動するつもりだ リストのソートされたこの部分に最小要素。 そして、かつて私はそこに何かを移動し、私は再び、その要素を見てする必要はありません。 できるだけ早く私はリストの左側のセグメントにで要素を入れ替えるように、それはソートだから 我々は最小値を使用して昇順ですべてをやっているので。 だから我々は大丈夫、我々は位置iだ、と我々はすべての要素を見る必要がある、と述べた 最小値を見つけるために私の右側にある。 だから、我々はリストの最後にi + 1から見てみたいということです。 そして今、我々が現在見ているという要素は、今のところ私たちの最小値よりも小さい場合 覚えて、我々はちょうどように最小オフを開始している、 どんな要素が我々に現在している、私は最低だと仮定します。 私はそれよりも小さいの要素を見つけるなら、私は、大丈夫、と言うつもりです まあ、私は、新しい最小値を発見した。 私は、その最小値がどこにあったか覚えているつもりです。 だから今、かつて私は、その権利ソートされていないセグメントを経てきました 私は位置iにある要素で最小の要素を入れ替えるつもりだと言うことができます。 それは私のリストを構築するために起こっているのは、左から右にリストの並べ替え私の部分、 そして我々は今までそれがその部分にだから、もう一度要素を見る必要はありません。 かつて我々はそれを交換してきました。 したがって、このリスト上の選択ソートを実行してみましょう。 ここで青色素子は、iであることを行っている、赤の要素は最小の要素になるだろう。 だから私は5でそう、リストの左側にすべての道を開始します。 今、私たちは最小のソートされていない要素を見つける必要があります。 だから我々は<5ので、0は私の新しい最小値である0を言う。 我々は、0が最小であることを認識することができるにもかかわらずので、しかし、私はそこに停止することはできません 我々は確かにするためのリストの他のすべての要素を介して実行する必要があります。 ので、1の方が大きい、6の方が大きい、4は大きいです。 つまり、これらの要素のすべてを見た後、私は0は最小と判断されたことを意味します。 だから私は5と0を交換するつもりです。 かつて私は、それを交換し、私は新しいリストを取得するつもりだ、と私は再びその0を見てする必要はありませんことを知っている かつて私は、それを交換してきたので、私はそれをソートしてきて終わり。 今度はそれはちょうどので、青の要素が再び5であることを起こる そして我々はその1を決定するために、1を見て6と4が必要 最小の最小要素であるので、我々は1と5を入れ替えます。 再び、我々は見てする必要がある - 、6、4から5を比較する そして我々は、比較、最終的に4と5を交換し、するつもりだ それらの2つの数字と私たちは、ソートされたリストを取得するまで、それらを交換。 選択ソートに何か質問はありますか? オーケー。のがここでの最後のトピックに移動しましょう​​、それが再帰です。 再帰は、覚えて、これは本当にどこ機能メタ事です 繰り返し自体呼び出します。 そこで、いくつかの時点で、我々のfuctionを繰り返し自分自身を呼び出している間に、 我々は自分自身の呼び出しを止めるれるいくつかのポイントがあるのが必要です。 我々はそれをしないならば、我々だけで永遠にこれを行うには続けていくつもりですので、 私たちのプログラムは、ちょうど終了するつもりはない。 我々は、この条件ベースケースと呼ぶ。 とベースケースは、むしろ関数を再度呼び出すよりも、言う 私はいくつかの値を返すつもりです。 我々は値を返さたらそれで、私たちは、自分自身を呼び出しやめた 我々はこれまでに作ったコールの残りも返すことができます。 ベースケースの反対側では、再帰的なケースです。 そして、これは、我々はインチ現在していることを別の関数への呼び出しを行いたい場合です そして、我々はおそらく、常にではありませんが、異なる引数を使用したい。 だから我々は、fという関数を持っている場合、fはちょうど1つの引数を取ると呼ばれる、 私達はちょうどF(1)において、f(1)において、f(1)を呼び出しておくと、それだけでことが起こる 引数1は、再帰的なケースに落ち、我々はまだ停止するつもりはありませんしている。 weはベースケースを持っている場合でも、我々は最終的に我々はベースケースをヒットしようとしていることを確認する必要があります。 私達はちょうどこの再帰的な場合に滞在し保存していません。 一般的に、我々は自分自身を呼び出すときに、我々は、おそらく別の引数を毎回持っているつもりです。 ここは本当に単純な再帰関数である。 だから、これは数値の階乗を計算します。 我々はベースケースを持ってここにトップアップ。 nは≤1、我々は再び乗コールするつもりはない場合。 私達はやめるつもりです、我々はいくつかの値を返すつもりだ。 これが本当でないなら、私たちは私たちの再帰的なケースをヒットするつもりです。 それは非常に有用ではないので、我々はちょうど、階乗(n)を呼び出していないことに注目してください。 私たちは、何か他の階乗を呼ぶつもりです。 そしてあなたは、我々は階乗(5)か何かを渡した場合、最終的には、見ることができます weは、factorial(4)のように呼び出すつもりだし、最終的に我々は、このベースケースをヒットするつもりです。 だから、これはよさそうだ。我々は実際にこれを実行したときに何が起こるか見てみましょう。 これは、スタックだけですが、メインの引数(4)で、この関数を呼び出すために起こっていることを言わせてください。 だから一度見て、階乗= 4の場合、階乗は自分自身を呼び出します。 さて、突然、我々は、(3)階乗を持っています。 そこで、これらの関数は、最終的に我々はベースケースに当たるまで成長を維持しようとしている。 この時点では、このメソッドの戻り値は、return(NXこのメソッドの戻り値)である このメソッドの戻り値は、このNXの戻り値です。 最終的に我々はいくつかの数字をヒットする必要があります。 ここで一番上には、我々は1を返すと言う。 かつて我々は、その数を返すことを意味します、我々は、スタックから、これを開くことができます。 ですから、これは階乗は(1)で行われます。 ときに1が返ると、この階乗(1)を返し、1〜このリターン。 このメソッドの戻り値は、覚えて、このメソッドの戻り値NXだった。 そんなに急に、この男は、私は2を返すようにしたいことを知っています。 だから、これの値はここで戻り値だけNX次第です戻り、覚えておいてください。 だから今我々は3×2と言うことができ、最終的に、ここで我々は言うことができます これはちょうど4×3×2であることを行っている。 そして、この復帰後に、私たちは主の単一の整数の内部に取り掛かる。 再帰に何か質問はありますか? かしこまりました。だから最後に質問のためのより多くの時間があり、 しかし今ヨセフは残りのトピックをカバーしています。 [ジョセフ·オング]すべての権利。だから今我々は再帰について話したことを、 ソートされ、マージかについて少し話してみましょう。 マージソートは、基本的に数字のリストをソートする別の方法です。 そして、それはマージソートであり、どのように動作するか、リストを持っており、私たちがやっていることです 我々は、の2等分これを分割してみましょう、と言う。 私たちは最初に、左半分に再びマージソートを実行することになるでしょう 次に我々は、右半分にマージソートを実行することになるでしょう それが今私たちにソートされている2の半分を与え、そして、今、私たちは一緒にそれらの半分を結合しようとしている。 それは例なしで見るのは少し難しいので、私たちはふりをすると何が起こるかわかります。 ですから、このリストを使用して開始し、我々は2等分に分割します。 我々は最初の左半分にマージソートを実行します。 だから左半分だし、今、私たちは再び、このリストを介してそれらを実行する マージソートに渡され、それから私達は、再び、見される このリストの左側にあると我々はそれにマージソートを実行します。 今、私たちには、2つの数値のリストに降り、 そして今、左半分は1要素の長さであり、我々はできません 半分に1つだけの要素のリストに分割するので、我々は一度だけ私たちは50を持っている、と言う、 ただ1つの要素である、それはすでにソートだ。 weは、その処理が終わったら、私たちができることがわかります このリストの右半分に移動、 と3も、今、このリストの両方の半分がソートされているソートされており、 我々は戻って一緒にこれらの番号を参加させることができます。 だから我々は、50と3を見て、3は50よりも小さいので、それは最初にして50になった出番 さて、それが済んだ、我々はそれが右半分だとリストとソートに戻って上がる。 42はそれ自身の番号ですので、すでにソートだ。 だから今我々は、第一​​に置かれるように、これらの2と3は、42よりも小さい比較 今42に入れ取得し、50インチ入れてさ さて、ソートされている、我々は、トップに戻る、1337年、15〜すべての道を行く。 まあ、我々は今、このリストの左半分を見て、1337年は、それ自体であるので、15でソートと同じだ。 だから今我々は15日、元のリストをソートするために、これら2つの数値を組み合わせる<1337、 ので、それが最初に入り、その後、1337インチ行く そして今、我々はトップアップ元のリストの両方の半分をソート。 そして、我々がしなければならないすべては、これらを組み合わせることである。 我々は、このリストの最初の2つの数字、3 <15を見ているので、最初のソート配列になります。 15 <42ので、それは、今すぐ行くインチ42 <1337年、それはインチ行く 50 <1337年なので、インチになり、私達はちょうどこのリストの2つの数値を脱いだことがわかります。 だから我々は、ちょうど2つのリストの間で交互にしていない。 私達はちょうど初めに探している、と我々は要素を取っている 小さいし、私達の配列にそれを入れているのです。 今、私たちはすべての半分をマージしたと我々は完了です。 マージソートについて何か質問はありますか?はい? [学生]は、それが別のグループに分割するなら、なぜ彼らは一度だけ、それを分割しない そしてあなたは、グループ内の3と2を持っている? [質問の不明朗な休息] 理由は - 私たちはそれらを持って後にそう質問ですが、なぜ私たちはちょうどその最初のステップでそれらをマージすることはできません? 我々がこれを行うことができます理由は、両側の一番左の要素から開始 その後、小さい方を取ると、それを入れる我々はこれらを知っているということです 個々のリストはソート順序になります。 私は両方の半分の左端の要素を見ているのであれば、 私は、彼らがそれらのリストの最小要素であることが分かっている。 だから私はこの大規模なリストの最小の要素のスポットにそれらを置くことができます。 一方、私はあそこに第2レベルにそれらの2つのリストを見れば、 50、3、42、1337、15、それらはソートされません。 私は50と1337を見ればだから、私は最初に私のリストに50を置くつもりです。 しかし、それは本当に3はそれらのすべてのうち、最小の要素であるため、意味をなさない。 だから我々はこの組み合わせステップを行うことができる唯一の​​理由は、私たちのリストがすでにソートされているためです。 我々は底にすべての方法を取得する必要があります理由である 私達はちょうど単一の番号を持っているときは、その単一の番号を知っているので、 それ自体はすでにソートされたリストです。 何か質問?いいえ? 複雑?さて、あなたは、各ステップでの終了番号があることがわかります そして我々は、ハーフログn回でリストを分割することができます 私たちはこのN xのログn複雑さをどこで取得するそれはある。 そして、あなたは、マージソートのための最良の場合はnログnで表示されます、そして、それはちょうどそう起こる 最悪の場合、またはあそこΩは、もnはnをログに記録すること。 心に留めておくべき何か。 上を移動する、のはいくつかの超基本的なファイルI / Oに進みましょう あなたはスクランブルを見た場合は、我々はシステムのいくつかの並べ替えを持っていたことがわかります あなたがコードを通読したとすればどこにログ·ファイルに書き込むことができます。 あなたはそれを行う方法を見てみましょう。 さて、私たちは、あなただけのprintfのように考えることができる、fprintfを持っている しかし、まだ始まったばかりでfゆえではなく、ファイルに印刷します。 あなたはスクランブルで見てきたかもしれないようにそれが何をするか、ここにこのコードのソートは、、、です それは数字が何であるかを、行ごとにプリントアウトあなたの2次元配列を通過します。 このケースでは、printfの端末に出力しますか、我々は、セクションの標準出力と呼んでいるもの。 そして今、このケースでは、我々がしなければならないすべては、fprintf関数でprintfを置き換えるだけです は、印刷したいものをファイルにそれを言うと、この場合には、それだけで、そのファイルに出力します 代わりにあなたの端末にそれをプリントアウト。 我々は、右からのファイルのこの種を入手できますか:じゃあ、質問しておきたいこと? 我々は、この関数fprintfのfuctionにログインを渡さしかし我々はそれがどこから来た全くわからなかった。 さて、初期のコードでは、私たちが持っていたことは、こっちのコードの塊であった 基本的に開いているファイルがlog.txtに呼び出すことを言うている。 つまり後に我々は何をすべきか、我々は、ファイルが実際には正常に開かれていることを確認する必要があります。 だから、複数の理由で失敗することがあります、あなたは、例えば、コンピュータに十分なスペースがありません。 あなたがファイルを使用して、任意の操作を行う前に、それは常に重要だ 私たちは、そのファイルが正常に開かれたかどうかを確認すること。 それでは、それはfopenの引数だと、まあ、我々は多くの方法でファイルを開くことができます。 我々はあるが何ができるか、私たちは、それが終了した場合、既にファイルを上書きすることを意味し、それをワットを渡すことができます 我々は、彼らが代わりにそれを上書きするファイルの末尾に追加され、aを渡すことができます。 または我々が意味rを指定することができます、のは読み取り専用としてファイルを開くことができます。 このプログラムは、ファイルへの変更を行おうとするのであれば それらで叫ぶと彼らはそれを行うことはできません。 最後に、一度我々は、ファイルを使用して行うことで操作を行って完了です 我々はファイルを閉じることを確認する必要があります。 それで、あなたのプログラムの終了時に、それらを再度通過しようとしている あなたが開いて、それを閉じることは、このファイル。 だから、これは、あなたが行うことを確認しなければならないことを何か重要なことです。 ですから、ファイルを開くことができます覚えて、あなたは、ファイルに書き込むことができます ファイル内で操作を行うが、その時には終了時にファイルを閉じる必要があります。 基本的なファイル上の任意の質問のI / O?はい? [学生の質問、不明朗] ここ。質問は、このlog.txtファイルはどこに表示されないのですか? あなたはちょうどそれをlog.txtを与えればよく、それは実行ファイルと同じディレクトリに作成します。 だからyou'reなら - >> [学生の質問、不明朗] はい。同じフォルダ内、または同じディレクトリに、あなたがそれを呼び出すように。 今やメモリ、スタック、およびヒープ。 だからメモリは、コンピュータでどのようにレイアウトされている? さて、あなたはここで、このブロックのようなものとしてメモリを想像することができます。 し、メモリ内では、我々は立ち往生ヒープ、およびそこにダウンだスタックと呼ば​​れるものを持っています。 とヒープが下に向かって伸びていくとスタックが上向きに生えています。 トミーは述べように - ああ、まあ、我々は私が2番目にに着くから、これらの他の4つのセグメントを持っている - トミーは先に述べたように、あなたは彼の関数は、それ自体を呼び出し、互いを呼び出す方法を知っている? 彼らは、スタックフレームのこの種を構築します。 さて、メインのコールfoo、fooがスタックに置かれる場合。 Fooが呼び出しバー、バーのはスタックに置か取得し、後にスタックに置かれることを。 彼らは返すようにと、彼らはそれぞれのスタックからだまされる。 これらの各場所とメモリは何を保持するか。 さて、テキストセグメントでトップは、プログラム自体が含まれています。 そこのマシンコード、SO、一度プログラムをコンパイルします。 次に、任意のグローバル変数を初期化しました。 だから、あなたはあなたのプログラムでグローバル変数を持っていて、= 5のように言う その下に、そのセグメント、右に置かれることを、 あなたは、単にintである初期化されていないグローバルデータを持っている しかし、あなたはそれが何かに等しいだとは言いません。 これらはグローバル変数なので、彼らがメインの外にいる実感。 だから、これは宣言されていますが、初期化されていないすべてのグローバル変数を意味します。 だからヒープに何があるのか​​?メモリは、我々は少しのに着くから、mallocを使用して、割り当てられた。 そして最後に、スタックとは、任意のローカル変数を持っている 任意の関数は、あなたはそれらのいずれかのパラメータで呼び出すことがあります。 最後のものは、あなたが本当に、環境変数が何をすべきかを知っている必要はありません しかし、あなたがプログラムを実行するたびに、同じように、関連するものがある これはプログラムを実行した人のユーザー名です。 そして、それは下部の一種になるだろう。 16進値ですメモリアドレスの面では、 0でトップスタート時の値、およびそれらは底にすべての道を下って行く。 この場合、あなたは、32ビットシステムを使っているのであれば、 下部のアドレスはそれが32ビットだから、AFが続く0xであることを行っている、 これは8バイトであり、この場合には8バイトには8桁の16進数に対応しています。 だからダウンここでは、のように、0xffffffのを持っているつもりですし、そこまでは、0を持っているつもりです。 だからポインタは何ですか?あなたのいくつかは、前のセクションでこれをカバーしていない可能性があります。 しかし、我々は講演でその上に行きましたので、ポインタは単にデータタイプです どの店が、代わりに50のような値のいくつかの並べ替えのために、それは、メモリ内のいくつかの場所のアドレスを格納します。 そのメモリのように[理解不能]。 したがって、このケースでは、我々がしたこと、我々は、整数またはint *へのポインタを持っている そしてそれは0xdeadbeefのこの16進アドレスが含まれています。 だから我々が持っているものを、メモリ内のいくつかの場所でこのポインタは、現在、ある そしてそれはちょうどですが、値50は、このメモリの場所にあります。 いくつかの32ビットシステムでは、すべての32ビットシステムでは、ポインタは32ビットまたは4バイトを占有。 しかし、例えば、64ビットシステム上では、ポインタは64ビットです。 だから、それはあなたが心に留めておくことをお勧めします何かです。 だから最後ビットシステム上では、ポインタは長い端ビットです。 ポインタは、余分なものなしで消化するのは難しいの夫婦です それでは、動的メモリ割り当ての例を挙げて行きましょう。 どのような動的なメモリ割り当てがあなたのために、または私達はmalloc関数と呼んでいるもの、 それはあなたがセット以外のデータのいくつかの並べ替えを割り当てることができます。 したがって、このデータはプログラムの期間のためのより永久的なの一種です。 あなたが知っているようので、あなたが関数の内部でx、およびその関数が復帰を宣言した場合、 あなたはもはやxに格納されたデータへのアクセスを持っていません。 私達は何のポインタをやってみましょう彼らは私たちがメモリまたはストアの値を格納できるようになり つまりメモリの異なるセグメント、ヒープインチ 今一度、私たちは、限り、我々には、ポインタを持っているように、関数の外に戻す メモリ内のその位置に、それから私達は何ができるかは、我々はちょうどそこの値を見ることができますです。 例を見てみましょう:これは再び我々のメモリレイアウトです。 そして、我々は主に、この機能を持っています。 何をするかが - 大丈夫、そう単純で、右 - ?int型のx = 5で、それはただのメインスタック上の変数です。 一方、今、私たちは、関数を呼び出すgiveMeThreeIntsポインタを宣言します。 それで、今、私たちは、この関数に入ると、私たちはそのための新しいスタック·フレームを作成します。 しかし、このスタック·フレームに、我々はint * tempを宣言し、 私たちのためにmallocを3つの整数である。 だからint型の大きさは、このintがどのように多くのバイトを私たちに授けてくれます とmallocはヒープ上のスペースの多くのバイトことを私たちに与えます。 したがって、このケースでは、我々は、3つの整数のための十分なスペースを作成しました ヒープとは、私はそれを描いた理由の上位にあるそこまでの方法です。 我々が終わったら、我々はここに戻ってくるには、わずか3 intが返される必要があり、 そしてそれは、そのメモリがどこにあるの上に、この場合には、そのアドレスを返します。 そして、我々はポインタ=スイッチを設定し、そこまで我々はちょうど別のポインタを持っています。 しかし、どのような関数がリターンはここで積み重ねて消滅していること。 だからtempは消えますが、我々はまだのアドレスを維持 それらの3つの整数は、本管の内側にあります。 だから、このセットでは、ポインタは、積み重ねられたフレームのためにローカルスコープを持ちます しかし、それらが参照するメモリがヒープにある。 それは意味をなさないか? [学生]繰り返して頂けますか? >> [ヨセフ]はい。 私は戻って少しだけ行けばそれで、あなたはtempが割り当てられていることがわかり そこまでヒープ上のいくつかのメモリ。 だからときに、この関数、giveMeThreeIntsが戻るのは、ここでは、このスタックが消えるだろう。 そしてそれはこの場合の変数のいずれか、積み重ねられたフレームに割り当てられたこのポインタを持つ。 消えて行くが、我々は、tempを返したためであることを そして我々は=気温、ポインタが今tempがあったように場所の同じメモリを指すように起こっているのポインタを設定します。 だから今、私たちは一時、その地方のポインタを、失うにもかかわらず、 我々はまだそれがその変数のポインタの内側を指していたもののメモリアドレスを保持します。 質問はありますか?あなたはセクションでその上に行っていないなら、それは混乱トピックのようなものにすることができます。 我々は、あなたのタスクフォースは、間違いなくその上を行くことができますし、もちろん我々は質問に答えることができます。 これについてのレビューセッションの終了時。 しかし、これは複雑なトピックのようなものである、と私は現れるとしているより多くの例を持っている そのポインタが実際に何であるか明確にするのに役立ちます。 この場合、ポインタは、配列に相当します ので、私はint型の配列と同じもののように、このポインタを使用することができます。 だから私は、0にインデックスを付けると、1に最初の整数を変更している 2番目の整数を変更して、3〜第三整数。 ポインタに対するので、より多くの。まあ、BINKY思い出す。 この場合において、我々はポインタを割り当てた、または私達はポインタを宣言 しかし当初は、私はちょうどポインタを宣言したとき、それはメモリのどこを指しているわけではありません。 それはそれの内側にちょうどゴミの値です。 だから私は、このポインタが指して見当がつかない。 それだけで0と1のそれを最初に宣言された場所で満たされているアドレスを持っています。 私はそれに、malloc()を呼び出すまで、私はこれで何もできない そしてそれは私に私が内に値を入れることができ、ヒープ上のわずかなスペースを提供します。 その後、再び、私はこのメモリの中身を知りません。 だから私がしなければならない最初のことは、システムが十分なメモリを持っていたかどうかチェックすることです 私がこのチェックをやっている理由は、最初の場所では、1の整数をお返しします。 ポインタがnullである場合、それは、それは十分なスペースまたは他のエラーが発生しましたを持っていなかったことを意味します ので、私は私のプログラムを終了する必要があります。  それが成功した場合しかし、今私はそのポインタを使用することができます と何*ポインタが行うことは住所がどこにあるか、それが以下の通りである その値があり、それは1に等しく、それを設定している場所へ。 そのメモリが存在していればだからここに、私達はチェックしています。 あなたはそれが存在することを知ったら、あなたはそれに置くことができる この場合1で、あなたはそれに入れたいものの値。 我々はそれに終わったら、そのポインタを解放する必要が 私たちは、あなたが最初の場所で求めていることをシステムメモリに戻って取得する必要があるためです。 コンピュータは我々がそれを行っているときにわからないため。 このケースでは、明示的にそれを言っている、大丈夫、私たちはそのメモリの作業は終了です。 他のプロセスがそれを必要とする場合、いくつかの他のプログラムがそれを必要とする、先に行くとそれを取ること自由に感じなさい。 私たちにも出来ることは我々がちょうどセットでのローカル変数のアドレスを取得できています。 だからint型のxはメインの積層フレームの内側です。 そして、我々はこのアンパサンドを使用する場合、このオペレータは、それが何をするかである それはxを取り、xは、メモリ内のちょうどいくつかのデータですが、それはアドレスを持っています。 それはどこかに位置している。これが何を呼び出し&xは、あるので、それによっては、私たちにxのアドレスを与えます。 これを行うことによって、我々は、xがメモリのどこにあるかへのポインタポイントを作っている。 今、私たちは、* xが、我々は5バックを得ようとしているような何かを行うだけ。 星はそれを間接参照と呼ばれます。 あなたの住所だけに続く、あなたがそこに格納されてそれの値を取得します。 何か質問?はい? あなたは3尖っ事をしない場合は[学生]は、それはまだコンパイルしますか? はい。あなたは3ポイントの事をしない場合、それはまだ、コンパイルするために起こっている しかし、私は、第二で何が起こるかを示して、それを実行せずによ それは我々がメモリリークと呼んでいるものです。は、システムを与えていない そのメモリをバックアップしますので、後にプログラムは蓄積しようとしている間に それは使用しておらず、他に何もないということメモリがそれを使用することができます。 あなたがあなたのコンピュータ上の150万キロバイトでFirefoxを見てきた場合は、 タスクマネージャで、それは何が起こっているのだ。 あなたは彼らが処理していないことをプログラムでメモリリークが発生している。 それでは、どのようにポインタ演算の仕組みを教えてください。 まあ、ポインタ演算は配列に似たインデックスの並べ替えです。 この場合、私はポインタを持っており、私は何を、私は最初の要素へのポインタポイントを作ることです 私が割り当てられてきた3つの整数の配列で。 だから今私は何をすべきか、スターポインタは単にリスト内の最初の要素を変更します。 こっちスターポインタが1点。 そのポインタがここの上にある、ポインタ1はこっちですが、ポインタ2はこっちです。 だから1を追加すると、この配列に沿って移動することと同じです。 我々が行うことであり、我々はポインタ1を行うときには、こっちのアドレスを取得 そしてここでの値を取得するためには、式全体からのスターを置く 間接参照してください。 したがって、この場合、私は、これを1に、配列内の最初の位置を設定してい 2〜第二の位置、および3に、第3の場所。 その後、私はこっちのやっていることを、私は私達のポインターを1、印字していますです それはちょうど私に2を与える。 今、私はポインタをインクリメントしているので、ポインタはポインタ1に等しい その前方に移動します。 それで今私はポインタ1をプリントアウトした場合、ポインタ1は、現在3です このケースではそれは3を出力します。 と順番にフリー何か、私はそれを与えるポインタへ 私はmalloc関数から戻ってきた配列の先頭を指している必要があります。 私はここ3を呼び出すことがあったので、もしこのケースでは、これは、正しいことではないでしょう それは配列の途中のだから。 私は元の場所に到達するために引き算する必要があり 私はそれを解放する前に初期の最初のスポット。 だから、ここにはもっと複雑な例です。 この場合において、我々は文字配列内の7文字を割り当てています。 この場合には我々がやっていることは、我々は彼らの最初の6をループしている そして我々はZにそれらを設定している だから、int型のi = 0、i>の6、i + +は、 だから、ポインタ+ iは、ちょうど私達を与えるだろう、この場合には、 ポインタ、ポインタ1、ポインタ2、ポインタ3などなどループインチ それは何をするつもりなのは、それが値を取得するために、間接参照を、そのアドレスを取得している Zにして変化する値 それから、末尾に右、これは文字列であることを覚えている? すべての文字列はNULL終端文字で終了する必要があります。 だから、私は何をすると、ポインタが6で、私はインチヌル終端文字を入れています そして今、私は基本的にはこっちにやっていることは、文字列をprintfの権利を実施しています? だから、ときにprintfの今では、文字列の末尾に達していない場合? それがnull終端文字を打つとき。 だから、この場合には、この配列の先頭への私の元のポインタを指しています。 私は、最初の文字をプリントアウト。私はいずれかの上に移動します。 私はその文字をプリントアウトする。私はそれを上に移動します。 そして私は私が最後に到達するまでこれを続けさせている。 そして今、終わり*ポインタデリファレンスこの意志とヌル終端文字を取り戻す。 ので、私のwhileループは、その値がNULL終端文字でない場合にのみ実行されます。 だから、今私はこのループの外に出る。 そして私は、このポインタから6を引く場合 私は初めに戻ってすべての道を行く。 私はそれを解放するために先頭に移動する必要があるので覚えておいて、私はこれをやっている。 だから、私はたくさんあったことを知っている。何か質問はありますか? はい、お願いします? [学生の質問不明朗] あなたは大声でそれを言うことができますか?申し訳ありません。 [学生]は、ポインタを解放する直前に最後のスライドでは、 どこにあなたが実際にポインタの値を変えていた? [ヨセフ]だから、まさにここ。 >> [生徒]ああ、大丈夫。 [ジョセフ]だから、私は右、ポインタマイナスマイナスを持って、 これは、私はそれを解放してから再び一つを移動させ、 このポインタは、配列の先頭に指摘されなければならないので。 あなたがその行の後に停止していた[学生]しかし、必要とされないであろうこと。 [ヨセフ]私はこの後に停止していた場合だから、これはメモリリークがあると考えられるでしょう、 私は自由を実行しなかったため。 [学生]は、[理解不能]ポインタ1を持っていた最初の三つの行の後に私は[理解不能]。 [ヨセフ]うーむ。だから、そこの質問は何ですか? 申し訳ありません。ノー、ノー。してください、行く、行く。 [学生]だから、あなたは、ポインタの値を変更していない。 あなたは、ポインタマイナスマイナスをしなければならなかったことはなかっただろう。 [ヨセフ]はい、その通りです。 だから、私はポインタ1とポインタ2を実行した場合、 私はポインタをやっていないよと、ポインタ1に等しい。 だから、ポインタは単に配列の先頭を指したままです。 それは、それがポインタの内側に戻って値を設定することを私はプラスやるときだけだプラス それは実際に沿ってこれを移動すること。 かしこまりました。 多くの質問? これが圧倒的なの一種である場合は、再度、これは、セッションで説明します。 それについてあなたのティーチング·フェローを聞いて、私たちは最後に質問に答えることができます。 そして通常、我々は、このマイナスのことを行うには好きではありません。 これは私が、私は配列内のオフセット自分がどれほどのを追跡する必要があります。 だから、一般的に、これは単なるポインタ演算がどのように機能するかを説明することです。 しかし、私たちが普段やりたいことは、我々はポインタのコピーを作成したいのです 我々は文字列内での移動しているときに、それから私達は、そのコピーを使用します。 したがって、これらの場合には、文字列全体を印刷するためにコピーを使用し、 しかし、我々は、ポインタマイナス6のようにしなければならないか、我々はこれで移動どのくらいを追跡しません ちょうど私達が私達の原点がまだリストの最初に指摘されていることを知っているので、 そして私たちは変更したすべては、このコピーであった。 だから、一般的には、元のポインタのコピーを変更します。 等でソートしようとしないでください - 無関心は、元のコピーを変更します。 あなたのオリジナルのコピーのみを変更しようとしています。 我々は、printfに文字列を渡すときだから、あなたは気付く あなたは、私たちは他のすべての間接参照でやったようにそれの前に星を置く権利を持っていないのですか? あなたは全体の文字列%sが期待するプリントアウトでないと、アドレスです 文字の配列のように、この場合のポインタ、またはこの場合インチ 文字は、char * s、および配列は同じものです。 ポインタが文字になり、文字配列は同じものです。 それで、我々がしなければならないすべては、ポインタを渡している。 私たちは、*ポインタ、またはそのような何かのように通過する必要はありません。 だから、配列とポインタは同じものです。 あなたはこっち配列のx [y]のような何かをやっているときに、 何それはフードの下でやっているのは大丈夫、それは、文字配列だが、それを言ってるのさ ので、それはポインタだ。 それでxは、同じものです ので、それが何をするかは、それがxにyを加算している そんなにメモリに前進と同じものはどれですか。 そして今、x + yは、私達に住所のいくつかの並べ替えを与える そして我々はアドレスを間接参照するか、または矢印をたどる どこにメモリ内のその場所であり、我々は、メモリ内のその場所から値を取得します。 だからので、これらの2つはまったく同じものです。 それはただのシンタックスシュガーです。 彼らは同じことを行う。彼らはお互いのためにちょうど別の統語論だ。 だから、ポインタで何が間違って行くことができますか?ロット、のような。オーケー。だから、悪い事。 あなたのmallocコールが右、nullが返された場合、あなたが行うことができますいくつかの悪いことが確認されていません? このケースでは、私は私を与えるために、システムを求めている - その数は何ですか? 整数のサイズが4バイトであるため、2億回4拍手。 私は8億バイトと同じようにそれを求めています。 もちろん、私のコンピュータは私に多くのメモリバックを与えることになるではありません。 これがnullの場合、我々は我々があそこに逆参照しようとするので、チェックしませんでした - それがために起こっている場所にある矢印をたどる - 私たちはそのメモリを持っていない。 これは、我々はnullポインタを間接参照と呼んでいます。 そして、これは本質的にはセグメンテーションフォルトします。 これは、セグメンテーションフォルトができる方法の一つです。 あなたが行うことができ、他の悪い事 - まあいい。 それはnullポインタを間接参照しました。オーケー。 他の悪いことは - まあ、あなたはただそこにチェックを入れてこれを修正するには そのポインタがnullであるかどうかをチェック それはmallocはNULLポインタを返すことが起こるなら、プログラムを終了する。 それはXKCD漫画だ。人々は今それを理解する。のようなもの。 だから、メモリ。そして、私はこの上に行きました。 我々は、ループ内でmallocを呼び出すが、私たちは、malloc()を呼び出すたびにしている 我々は、このポインタが指している場所を追跡を失っている 我々はそれを追い払っているので。 だから、malloc関数の最初の呼び出しは、私にこっちにメモリを提供します。 これに対する私のポインタのポインタ。 今、私はそれを解放しないので、今、私は再び、malloc()を呼び出します。 今度はこっちに指摘している。今、私の記憶がこっちに向いている。 ここに上でポインティング。ここに上でポインティング。 しかし、私が割り当てられたことをこっちにすべてのメモリのアドレスのトラックを失ってしまった。 そして今私はもはやそれへの参照を持っていない。 だから、私はこのループの外にそれらを解放することはできません。 ので、このような何かを修正するために、 あなたは、メモリを解放することを忘れており、このメモリリークを得れば、 あなたは、あなたがそれで終わったら、このループの内側にメモリを解放する必要があります。 まあ、これは何が起こるかです。私はあなたの多くはこれを嫌い知っている。 しかし、今 - イェーイ!あなたは44000キロバイトのように得る。 だから、あなたは、ループの最後でそれを解放 それは単にメモリを毎回解放するだろう。 本質的に、あなたのプログラムは、もはやメモリリークを持っていません。 そして今、あなたがすることができる何か他のものを使用すると、二回求めてきたいくつかのメモリを解放しています。 このケースでは、mallocの何かするときには、その値を変更します。 あなたはあなたがそれを用いて行われたと言ったので、あなたが一度それを解放します。 しかし、その後、我々は再びそれを解放した。 これは非常に残念だ何かである。 それは、最初にセグメンテーション違反にはならないだろう しかし後にこれが何をするかしばらく二重、これが壊れるあなたのヒープ構造を解放している あなたはCS61のようなクラスを取ることを選択した場合、あなたはこのことについてもう少し学びます。 しかし、本質的に後にコンピュータが混乱しようとしている間に どことどこでそれが格納されていることについて、メモリの場所は - どこにデータがメモ​​リに保存されます。 それでポインタの解放は、二回あなたがやりたくないことを悪いことだ。 間違って行くことができます他のものは、sizeofを使用していません。 したがって、このケースでは、8バイトのmalloc それは2つの整数、右側と同じものですか? だから、それは完全に安全だが、それですか? まあ、ルーカスが異なったアーキテクチャでの話として、 整数は長さが異なる。 だから、あなたが使用しているアプライアンスでは、整数は4バイト程度である、 しかし、いくつかの他のシステムでは、それらは8バイトになるか、またはそれらは16バイトであるかもしれません。 だから、私はちょうどここの上にこの番号を使用する場合 このプログラムは、アプライアンス上で動作するかもしれない それはいくつかの他のシステムに十分なメモリを割り当てることはないだろう。 このケースでは、これはsizeof演算子が何に使用されるかである。 私たちは、これがされて何をするかはsizeof(int)を呼び出すと、  それは私たちにプログラムが実行されているシステム上の整数のサイズを示します。 したがって、この場合は、sizeof(int)は、アプライアンスのような何かに4を返します 8で、今、この意志4 * 2、 これは、ちょうど2つの整数のために必要なスペースの量です。 異なるシステム上で、intは16バイトまたは8バイトのようであれば、 それだけでその量を格納するのに十分なバイト数を返すことになるだろう。 そして最後に、構造体。 だから、あなたは、メモリに数独ボードを保持したい場合、どのように我々はこれを行うのでしょうか? あなたは、最初のもののための変数と同じように考えるかもしれない 第二のもののための変数、第三のもののための変数、 第四事のための変数 - 悪い、右か? だから、あなたがこの上に作ることができる1改善は9×9の配列を作ることです。 それはいいですが、あなたは数独ボードと他の事を関連付けるために望んでいる場合 は、ボードの難しさとは何か好き または、例えば、あなたのスコアは何であるか、どのくらいの時間、それはあなたがこのボードを解決するために取ってきて? さて、何を行うことができます使用すると、構造体を作成できることです。 私は基本的に言っていることは、私はここの上でこの構造を定義していますです と私は、9×9であるオンボードで構成されています数独ボードを定義しています。 そして、何それはレベルの名前へのポインタを持っています。 また、私は今どこにいるの座標xとyを持っています。 また、時間が[理解不能]を費やしてきた、そしてそれは私がこれまでに入力した移動操作の総数を持っています。 ので、この場合には、私はちょうど1つの構造体にデータの全体の束をまとめることができます 代わりに別の変数のように飛んでのようにそれを持っていることの 私は本当に幅を把握することはできません。 そして、これは私たちは、この構造体の内部に別のものを参照するのソートのためだけの素敵な構文を持つことができます。 私はちょうどboard.boardを行うことができます、そして、私は数独ボードを取り戻す。 Board.level、私はそれがどのように厳しい態度を取る。 Board.xとboard.yは私がボー​​ドにあるかもしれない場所の座標を与える。 そして、私は我々が構造体のフィールドと呼んでいるものにアクセスしています。 これは私が持っているタイプですsudokuBoardを定義します。 そして今、我々はここにいる。私はタイプsudokuBoardの "ボード"と呼ばれる変数を持っています。 それで今、私はこっち、この構造体を構成するすべてのフィールドにアクセスすることができます。 構造体について何か質問はありますか?はい? int型のx、yについては、[学生]は、1行に両方の宣言? >> [ヨセフ]うーむ。 [学生]だから、あなたは、単にそれらのすべてでそれを行うことができる? x、yのコンマ倍合計で好きですか? [ヨセフ]はい、あなたは間違いなくそれを行うが、私は同じ行にxとyを置くことができる理由 - 我々だけで、同じ行にこれを行うことができますなぜ、質問はありますか? なぜ我々はちょうどある同じ行に、これらのすべてを入れてはいけません xとyは互いに関連している、 これは、ある意味では、単に文体より正しいです それは、同じ回線上の2つの事柄をグループ化だので、 のようなソートは同じ事に関連しています。 そして私はちょうど離れてこれらを分割します。それはスタイルだけのことだ。 それは、機能的には全く違いはありません。 構造体で他に質問は? あなたは、structと図鑑を定義することができます。 ポケモンの数を持っており、それが手紙、所有者、型を持っています。 あなたはポケモンの配列を持っている場合、その後、あなたは正しい、図鑑を作ることができますか? さて、涼しい。だから、構造体についての質問。それらは、構造体に関連しています。 最後に、GDB。 GDBは、あなたが何をできるのですか?それはあなたのプログラムをデバッグすることができます。 GDBを使用していないならば、私はショートを見てお勧めしたい そしてただ、あなたがそれをどのように動作するか、どのようにそれを使用するかもしれないされているもの、GDB上に行く、 とプログラムにそれをテストします。 それで、GDBはあなたが行うことができますどのように処理し、休止[理解不能]アッププログラムで次のことができますです そして実用的なライン。 たとえば、私は、私のプログラムの3行目のように実行を一時停止したい 私は3行目にいる間、私はそこに存在するすべての値をプリントアウトすることができます。 そして私たちはラインで一時停止のように呼んでいるもの 我々は、これはその行にブレークポイントを入れて呼んでいる それから私達はその時のプログラムの状態の変数をプリントアウトすることができます。 我々は、そこからプログラム行ずつステップ実行することができます。 そして、我々は一度にスタックの状態を調べることができます。 そして、我々は何をすべきかGDBを、使用するために、我々はCファイルに打ち鳴らすの呼び出しです しかし、我々はそれを-GGDBフラグを渡す必要があります。 そして、かつて我々は我々だけで結果の出力ファイル上でGDBを実行することで行われている。 そしてあなたは、このようなテキストの一部のような塊を得る しかし、あなたがしなければならない本当にすべては初めにコマンドを入力されています。 ブレイクメインは、メインにブレークポイントを置きます。 リスト400は、ライン400の周りにコードの行を示しています。 ので、この場合にはあなただけの、ああ、見て回ると言うことができます 私はこのラインであるライン397、、目にブレークポイントを設定したい その後、プログラムは、そのステップに実行され、それは破るために起こっている。 それはそこに一時停止するように起こっている、あなたは、例えば、低または高の値をプリントアウトすることができます。 それで、あなたが知る必要があるコマンドの束があります そして、このスライドショーは、ウェブサイト上で上がる あなただけのこれらを参照するか、チートシートの上に置きたいので、もし、お気軽に。 クール。それはクイズレビュー0であり、ご質問があれば私たちの周り我慢しましょう​​。 かしこまりました。  [拍手] [CS50.TV]