[Powered by Google Translate] [SECTION 5:あまり快適] [ネイトHardison、ハーバード大学] [これはCS50です。] [CS50.TV] だから、戻ってみんなを歓迎します。 第5節へようこそ。 この時点で、クイズに0を完了したとあなたがやった方法を見てきた 私は非常にこのセクションのスコアに感銘を受けましたので、うまくいけば、あなたは本当に良い感じ。 弊社のオンライン視聴者のために、私たちは質問のカップルを見てきた 問題セットの最後の2つの問題について - やクイズで、むしろ。 だから我々は、誰もが何が起こったかを見ているように、本当にすぐにそれらの上で行くつもり というだけで解決策そのものを見るよりも実際のソリューションを通過する方法。 我々は、本当に迅速に問題の最後のカップル上に行くために32と33を行っている。 ただ、再びので、オンライン視聴者がこれを見ることができる。 あなたは、13ページにありますあなたの問題32に回すと、 16のうち13は、問題32は、すべてのスワップについてです。 それは、2つの整数をスワッピングについてのすべてだった。 それは我々が講義中に数回にわたって行っただろうとの問題です。 そして、ここで、我々はあなたが何を求めていたと、クイックメモリートレースです。 彼らがスタック上にあるので、変数の値を入力するには コー​​ドは、このスワップ機能を通過するとき。 特に、我々が探しているもの - このiPadを鎮圧しようとして - 私 -​​ 特に、私たちが見ていると、この行は右ここでは6の番号が付けられています。 そして、それは前の問題とだけ隣接の6の番号が付けられている。 私たちがやりたいことは、メモリの状態を表示したり、ラベルである それは我々がこの行番号6を実行したときの時間である、として これは、効果的に右ここに私たちのswap関数からの戻りです。 我々がここで下にスクロールした場合、我々は、メモリ内のすべてのアドレスが私たちのために提供されていたことを見た。 これは非常に重要であり、我々はちょうどその瞬間にそれに戻ってくるでしょう。 そして、ダウンここ下部に、我々はを参照しようとしている小さなメモリ図を持っていた。 私は実際に私の計算された上でこれを行っている。 だから、僕は参考のためにiPadと、このコードの間を行ったり来たり交互にするつもりです。 始めましょう。最初は、ここでの主な権利の最初の数行に注目しましょう​​。 開始するために、我々は2から1とyにxを初期化しようとしている。 だから我々は2つ​​の整数変数は、彼らは両方のスタック上に配置することになるだろうしている。 我々は彼らに1と2を入れてするつもりです。 私はiPadに裏返しので、もしうまくいけば、見てみましょう - Apple TVのミラーリング、およびそこに私達は行く。オーケー。 私はiPadに裏返しそうだとすれば、 私は2から1とyにxを初期化したい。 我々はXと書かれたボックスに1を書き込むことによって、非常に単純にそれを行う とyと書かれたボックスに2。かなりシンプル。 だから今度はラップトップに戻りましょう、次に何が起こるかを参照してください。 物事はトリッキー取得する場所だからこの次の行があります。 我々は、パラメータとしてxのアドレスとyのアドレスを渡すスワップ機能にaとb。 xとyのアドレスのアドレスは、我々は計算することができないものです ここに至るまでこれらの箇条書きを参照することなく。 幸いなことに、最初の2つの箇条書きは、答えが正確に何を教えて下さい。 メモリ内のxのアドレスは10で、メモリ内のyのアドレスは14です。 だから、それらは私たちのswap関数で、aとbがトップとして渡される値です。 だからもう一度、私たちのダイアグラムに切り替え、私は10を書き込むことができます aとbの14。 我々はスワップを進める今どこに、この点である。 だから、もう一度ラップトップに戻ってひっくり返す 我々は、スワップが動作する方法は、私まずデリファレンスであることを見て、tmpに結果を格納します。 だから、間接参照演算子がねえ "と言う。アドレスとして、変数の内容を扱います。 そのアドレスに格納されているものは何でもに移動し、それをロードします。 " あなたは何を変数のうちロードは、弊社のTMP変数に格納しようとしている。 iPadにバックフリップ。 我々は10に対処するために行けば、我々はアドレス10がvarible xであることを知っている 我々は、メモリ内のxのアドレスが10であるという我々の箇条書きと言われたので。 だから我々は、我々はiPad上で見るように、そこに行く1であることの価値を得ることができます そのtmpにロード。 繰り返しますが、これは最終的な内容ではありません。 我々は、ウォークスルーするつもりだと我々は最後に示すプログラムの我々の最終的な状態に到達するでしょう。 しかし、今、私たちは、tmpに格納された値1を持つ。 とこっちに簡単な質問があります。 [アレキサンダー]間接参照演算子です - ちょうど変数の前に星の右ですか? >>はい。 、我々は再び私たちのラップトップに戻ってめくるように、間接参照演算子は、そう この星は右の前にあります。 その意味で、です - あなたは、乗算演算子とそれを対比 これは、二つのことが必要です。間接参照演算子は、単項演算子です。 二項演算子とは対照的に、ただ、一つの値に適用される どこに2つの異なる値に適用されます。 だからそれは、この行で何が起こるかです。 我々は1の値をロードし、私たちの一時的な整数変数にそれを格納します。 次の行は、我々にbの内容を保存する - または、むしろ、我々は、bが指している場所にを指している内容を保存します。 我々は、右から左に、これを分析する場合、我々は、間接参照Bにしようとしている 我々は14に対処しようとしている、我々はそこにある整数をつかもうとしており、 それから私達は、アドレス10に行くつもりです そして我々はその空間にbの私達の参照解除の結果をスローしようとしている。 我々は、これはもう少し具体的にすることができます私たちの計算に戻り、反転、 私はここにいるすべてのアドレスの数字を書けばそれが役立つかもしれない。 だから我々はyで、我々はアドレス14であることを知って、xはアドレス10にある。 我々はbで起動したときに、私たちは間接参照bは、我々は値2をつかむつもりだ。 我々は、それがアドレス14に住んでいる値ですので、この値を取得しようとしている。 そして、我々はアドレス10に住んで変数に入れていくつもりですが、 これは、すぐそこに私たちの変数xに対応している。 だから我々はここで上書きするの少しを行うことができます 我々は1を取り除くと、その代わりに我々は2を書き込む場所。 だから、すべては私たちが現在上書きxをしたにも関わらず、よく、世界で良いことだ。 私たちは、TMP変数のxの古い値を格納していた。 だから我々は次の行を使用してスワップを完了することができます。 私たちのラップトップに戻ってめくる。 これで、すべてそのままでは私たちの一時的な整数変数の内容を取り出すことである aとbが保持しているアドレスに住んで変数に格納します。 だから我々は変数へのアクセスを得るために効果的に間接参照Bに行くんだ つまり、Bはそれに保持しているアドレスである、 そして我々はtmpがそれに保持している値を詰め込むつもりだ。 もう一度iPadにバックフリップ。 私は、ここに2をこの値を消去することができます その代わりに、我々はそれに1右をコピーします。 もちろん実行し、次の行、 - 我々はノートパソコンにバックフリップ - もし、この時点で6です それは私達が私達の図が完全に記入したかった点である。 だから、完成した図を見ることができるだけので、もう一度iPadに戻って反転、 あなたは私たちがxの中では10、b 14、tmpに1、2、およびyの1となっていることがわかります。 このことについて何か質問はありますか? これはそれを通って歩いた、より理にかなっていますか? あまり意味を作る?うまくいけません。オーケー。 ポインタは非常にトリッキーなことがあります。 我々は仕事の一人は非常に一般的なことわざがあります: "ポインタを理解するには、まずポインタを理解する必要があります。" これは私は非常に本当だと思います。それは、それに慣れるのにしばらく時間がかかりますか。 たくさんの写真を描いて、このようなメモリ·ダイアグラムの抽選は、非常に有用である 、あなたは例の後、例の後で例を歩く後、 それはもう少しセンスともう少しセンスともう少し意味があるように始めましょう。 最後に、ある日、あなたはそれがすべて完全にマスターしているでしょう。 我々は次の問題に移る前に何か質問はありますか?かしこまりました。 だからノートパソコンにバックフリップ。 我々が持っている次の問題は、ファイルI / Oで、問題番号33です この少しにズームイン。 問題33 - はい? [ダニエル]私はちょうど簡単な質問がありました。この星、またはアスタリスク、 それはあなたが前にアスタリスクを使用するときにデリファレンスと呼ばれています。 あなたが前にアンパサンドを使用する場合、それは何と呼ばれるのですか? >>アンパサンド前にアドレス演算子です。 それでは、戻って上にスクロールすることができます。 おっと。私は実際にスクロールすることはできませんので、私はズームモードにいるよ。 私たちは右ここでは本当にすぐにこのコードを見れば、 もう一度、同じことが起こって。 我々は、この行に、右ここにこのコードを見れば、我々は、呼び出しがスワップを行う場合には、 アンパサンドは、単に "変数xに住んでアドレスを取得します"と言っている あなたのコンパイラは、コードをコンパイルするとき、 それは実際に物理的に生きるためにあなたのすべての変数のためのメモリ内の場所をマークする必要があります。 そしてそれはすべてのものをコンパイルしてたら、コンパイラは次に何ができるか、 それは "ああ、私はアドレス10にxを入れた。私はアドレス14でyを入れます。"、知っている そして、それはあなたのために、これらの値を入力できます。 だから、その後することができます - それは、次に同様で、パス&yにこれを渡すことができます。 これらの人は、あなたがスワップ機能にそれらを渡すときも、アドレスを取得しますが、それら 右ここでは、このタイプの情報、このint *、コンパイラに指示し、 "さて、私たちは、整数型の変数のアドレスとしてこのアドレスを解釈することになるだろう。" 文字変数のアドレスと異なっているint型のアドレスとして intは32ビットマシン上で、占有するため、スペースの4バイトを占有します 文字がスペースだけの1バイトを占め、一方。 だからそれは何であるかも知ることが重要だ - 住んでいるのか、値のタイプを 渡されてしまったアドレスに住んでいる あなたが扱っていること、またはアドレス。 そのように、あなたが実際にあなたのRAMからロードする方法を多くの情報のバイトを知っています。 そして、はい、あなたのようなこの間接参照演算子は、求めていた なり、特定のアドレスに情報にアクセスします。 だから、ここでは、この変数を使用して、言う、アドレスとしての内容を扱う、 そのアドレスに移動し、引き出し、プロセッサにロード、レジスタへのロード 実際の値またはそのアドレスで暮らす内容。 これ以上の質問は?これらは良い質問です。 それはあまりにも新しい用語がたくさんあり​​ます。 それは別の場所で見て&と*もファンキーのようなものだ。 かしこまりました。 だから戻って問題を33にするには、ファイルI / O これは、私は物事のカップルが起こったと思うそれらの問題のうちの1つだった。 一つは、それはかなり新しいトピックです。 これは、クイズの前に、もうすぐ発表されました そして私はそれが数学でそれらの単語のいずれかの問題のような種類のだったと思う どこに、彼らはあなたに多くの情報を与えるが、実際にそれのトンを使用しなければならなくなることはありません。 この問題の最初の部分では、CSVファイルが何であるかを記述しています。 さて、CSVファイルには、説明によると、カンマ区切り値ファイルです。 これらはすべて面白いが、あなたは今までにそれらを使用する理由である理由、 、なぜなら、どのようにあなたがたの多くは、これまでExcelのようなものを使用しているのですか? 、おそらく、またはあなたの人生の中でいくつかの点で使用されているあなたのほとんどを示しています。 あなたは、Excelのようなものを使用します。 Excelスプレッドシートからデータを取得したり、それを処理の任意の並べ替えを行うために、 あなたは、CプログラムやPythonプログラム、Javaプログラムを書きたい場合 あなたがそこに格納されたデータに対処するため、 それを取得するための最も一般的な方法の一つは、CSVファイルに含まれています。 あなたは、対話 '名前を付けて保存 "に行くときや、Excelを開くことができ あなたは、実際のCSVファイルを得ることができます。 これらの事に対処する方法を知って便利。 それが動作する方法はそれに似ているということです - 私が意味する、それは本質的に、スプレッドシートを模倣している ここで、我々は非常に、一番左の部分で、ここに見られるように、 我々はすべての最後の名前を持っています。 だから我々はその後、マラン、Hardison、その後ボーデン、MacWilliam、その後チャンを持っています。 すべての姓。そして、コンマは最初の名前から姓を分離します。 デビッド、ネイト、ロブ、トミー、そしてZamyla。 私はいつも、ロビーとトムを混ぜる。 そして、最後に、3番目の列は、電子メールアドレスです。 あなたがそれを理解したら、プログラムの残りの部分を実装するのはかなり簡単です。 私達は私達のCプログラムで、これと同じ構造を模倣するために何をやったか 我々は、構造体を使用してきましたされています。 我々は、同様にこれらのもう少し一緒に遊んでから始めましょう。 私たちは辞書を扱った問題セット3の最初の少しのためにそれらを見た。 しかし、このスタッフのstructは、姓、名、電子メールを保存します。 弊社のCSVファイルなどが格納していました。 だから、これはちょうど、ある形式から別の形式に変換しています。 我々は、ラインに、この場合には、スタッフの構造体を変換する必要が ちょうどそのようにカンマで区切られた行、。 お分かりでしょうか?あなたたちはすべてのクイズを取った、 ので、私はあなたが、少なくともこのことについて考える時間を持っていた想像してみてください。 レンタル機能では、問題は、私たちがでとるように求めます - この少し上でwe'llズーム - 、名前sで、職員体制、スタッフのstructに取る と私たちのstaff.csvファイルにその内容を追記します。 これが使用する非常に簡単であることが判明。 今日はもう少し、これらの関数をいじっの一種よ。 しかし、この場合には、fprintf関数は、実際にキーです。 だからfprintfので、我々はあなたたちはprintfのこの全体の用語を使用してきたのと同様に、印刷することができます。 あなたは、ファイルへの行のprintfができます。 だけではなく、通常のprintfの呼び出しを行うので、あなたはそれをフォーマット文字列を与える場所 そして、あなたは、次の引数を使用してすべての変数を置き換える fprintf関数で、あなたの非常に最初の引数は、代わりにあなたが書き込みたいファイルです。 私たちは、男fprintfを、たとえば、アプライアンスでこれを見た場合 我々は、printfとfprintfの違いを見ることができます。 私はここで少し拡大します。 printf関数とそう、我々はそれをフォーマット文字列を与えると、その後の引数 私達の書式文字列に置換または置換のためのすべての変数です。 fprintfを持つのに対し、最初の引数には、確かに、ストリームと呼ばれるこのファイルは*です。 、私たちの雇用にこっち戻って移動する 我々はすでに私たちのためにオープンしたファイル*ストリームを持っている。 それはのこの最初の行が何をするか、それはstaff.csvファイルを開き、 それを追記モードでそれを開き、私たちが行うためには残っているすべてです ファイルへのスタッフの構造を記述します。 そして、私はiPadを使用しますか、見てみましょう? 私はiPadを使用します。私たちはvoidを持っている - 私は少し良く書き込めるようにテーブルの上にこれを入れてみましょう - レンタルを無効にし、それは1つの引数、sと呼ばれるスタッフの構造にかかる。 私たちのカッコを持って、我々は、ファイルと呼ばれる我々のファイル*を持っている 我々は我々のfopenライン私たちに与えられた、 そして私はちょうどそれがpediaで既になのでドットなど書こうと思います。 そして、私たちの次の行に、我々は、fprintfのに電話をするつもりだ そして我々は我々が印刷したいファイルを渡すつもりだ、 その後私達の書式文字列、どの - 私はあなたたちは、それがどのように見えるかを教えてもらおう。 あなたはどう、ステラ?書式文字列の最初の部分がどのようなものか知っていますか? [ステラ]私はよく分からない。 >>はジミーをお気軽に。 あなたは、ジミーを知っていますか? [ジミー]は、それだけで最後でしょうか?知りません。私は全くわからない。 オーケー。>>方法について、誰もがこの試験で正しいを取得するのですか? すべての権利号。 それは、ここで我々が​​しなければならないすべては私達が私達スタッフの構造の各部分を望んであることが判明 我々のファイルに文字列としてプリントアウトすることができます。 我々は姓を持っているので、我々は、ちょうど3つの異なる時点で文字列置換文字使用 続いてコンマ、その後、最初の名前は、続いてコンマ 続いて、そして最後にメールアドレス - ではない 私の画面にフィット - しかし、それは、改行文字が続いている。 だから、僕はダウンしてそこにそれを書くつもりだ。 そして、我々の形式の文字列を次の 私達はちょうど私達がドット表記法を使用してアクセスする置換を、持っている 我々は問題セット3で確認した。 我々はs.last、s.first、とs.emailを使用することができます 私達の書式指定文字列にこれらの3つの値に置換する。 だからそれはどうだった?理にかなって? はい?いいえ?多分?オーケー。 我々が印刷したと我々はファイルをオープンしたら後に我々が行うことを最終的なもの: 我々は、ファイルを開いたときはいつでも、私たちは常にそれを閉じるために覚えておく必要があります。 さもなければので、我々は、メモリリークが発生してしまいます ファイル記述子を使用した。 だから我々は、どの関数を使うのですか、それを閉じますか?ダニエル? [ダニエル] fcloseは?まさに>> fcloseは、。 だから、この問題の最後の部分は、fclose関数を使用して、ファイルを正しく閉じるようだった これは、ちょうどそのように見えます。 あまりにもクレイジーではない。 クール。 だからクイズでの問題33です。 我々は間違いなく、より多くのファイルがあるでしょうI / Oが出てくる。 今日は今日の講演で、またはセクションでもう少しやる、 それはこの次期psetのバルクを形成するために何が起こっているのだから。 この時点でクイズから移動してみましょう。はい? [シャルロット]]なぜ代わりにfcloseのfcloseを(ファイル)(staff.csv)? ああ。>>それがあることが判明したので - ので、素晴らしいものです質問、 なぜ、我々は、fcloseを書いた時、fcloseを(ファイル)スター変数を記述しているされている のようにファイル名、staff.csvに反対?それは正しいですか?うん。 それでは見てみましょう。私は私のラップトップに切り替えた場合、 とfclose関数を見てみましょう。 だから、fclose関数は、ストリームをクローズし、それは我々がクローズするストリームへのポインタを取り として我々はクローズする実際のファイル名に反対した。 あなたはfopenの呼び出しを行ったとき、これは、背後からである あなたがファイルを開くときには、実際にファイルの情報を格納するためのメモリを割り当てています。 だからあなたは、ファイルに関する情報が含まれるファイルのポインタを持っている それは開いているように、ファイルに現在あるその大きさ、 ので、ファイル内の特定の場所への呼び出しを読み書きすることができますことを。 あなたは、ファイル名をクローズするのではなくポインタを閉じてしまう。 はい? [ダニエル]だからレンタルを使用するために、あなたは言うだろう - それはどのようにユーザーの入力を取得するのですか? fprintfはそれだけでユーザーの入力を待つつもりだという意味で、GetStringメソッドのように動作しません これを入力するように求める - または、これらの3つのものを入力するように待つ? それとも、レンタルを実装するために何かを使用する必要がありますか? >>うん。だから我々はわからない - 質問があったが、どのように我々は、ユーザの入力を取得するのですか 雇用を実現するためには?そして、どのような我々がここにあることは、雇うの発信者である 既に構造体に格納されたデータのすべてとこのスタッフの構造体で渡された。 だから、fprintfはちょうどファイルに直接そのデータを書き込むことができる。 ユーザーの入力を待っているはありません。 ユーザがすでに正しくこのスタッフstructにそれを置くことによって入力を与えてくれた。 これらのポインタのいずれかがnullだった場合、物事は、もちろん、壊してしまう ので、我々はここに戻って上にスクロールして、我々は我々の構造を見てみましょう。 我々は、最後の文字列、文字列には、まず文字列のメールを持っています。 我々は今、それらの本当にすべてが、ボンネットの下に、char *変数であることを知っている。 つまり、またはNULLを指しているかもしれません。 彼らは、ヒープ上のメモリを指している可能性があり スタック上の多分メモリ。 私たちは本当に知っているが、これらのポインタのいずれかがnullの場合、または無効である場合、しないでください 間違いなく私たちのレンタル機能をクラッシュさせるだろうということ。 それは試験の範囲を超えてのようなものだったものだった。 我々はそれについて心配していない。 グレート。オーケー。だからクイズから移動。 のはこの男を閉じてみましょう、と我々は、pset 4見ていくつもりです。 だから君たちはPSETスペックを見れば、一度それにアクセスすることができ、cs50.net/quizzes、 今日はセクションの問題のいくつかを通過しようとしている。 私は、下にスクロールしている - 質問のセクションは、pset仕様の3ページ目から始まります。 と最初の部分は、リダイレクトやパイプに行くとショートを視聴することが求​​められます。 クールショートのようなものだった、どっちがあなたが使用できるいくつかの新しい、クールなコマンドライントリックを示しています。 そして、我々は、同様にあなたのためのいくつかの質問を持っている。 printfは、デフォルトで書き込むストリーム、約この最初の質問 我々の種類のはちょっと前に少しだけに触れました。 我々だけで議論していたことをこのfprintf関数は、引数としてファイル*ストリームを取り込む。 fcloseは、同様にファイル*ストリームを取り込んで やfopenの戻り値は、同様にあなたのファイル*ストリームを提供します。 我々はprintfの扱ってきたときに前のものを見たことがない理由 printfのデフ​​ォルトのストリームを持っているためです。 そして、それが書き込む既定のストリーム あなたは、簡単に言えば知ります。 だから、間違いなく、それを見てみましょう。 今日のセクションでは、私たちは、GDBについて少し話をするつもりだ 、より身近なあなたがそれをしているので、あなたがそれを得るより多くの練習 より良いことができるあなたが実際にあなた自身のコード内のバグを追い詰めるだろう。 これは途方もなくアップデバッグのプロセスをスピードアップします。 だからprintfを使用することにより、毎回あなたは、あなたのコードを再コンパイルしなければならないことをやる あなたが再びそれを実行する必要があり、時にはあなたは、周りのprintfの呼び出しを移動する必要があります コー​​ドをコメントアウトして、それだけでしばらく時間がかかります。 私たちの目標は、GDBと、あなたは本質的にできることをしようと説得することである printfのコード内の任意の時点で何でも、あなたはそれを再コンパイルする必要はありません。 起動および場所printfの隣に推測し続けなければならないことはありません。 最初に行うべきことは、この行をコピーして、ウェブのセクションコードを下車します。 私は、 "wget​​をhttp://cdn.cs50.net言う、"このコード行をコピーしています。 私はそれをコピーするつもりです。 私はあなたが私がやっているかが分かるようにズームアウト、私のアプライアンスの所へ行くつもりだ、 そこにそれを貼り付ける、と私はEnterキーを打ったとき、このwgetコマンドは、文字通りWebはgetです。 それはインターネットのこのファイルをオフ​​プルダウンになるだろう、 そしてそれは、現在のディレクトリに保存するつもりです。 私は、現在のディレクトリの一覧を表示した場合今、あなたは私はすぐそこにこのsection5.zipファイルを持っていることがわかります。 その男に対処する方法は、それを解凍することです そのあなたがちょうどこのように、コマンドラインで行うことができます。 Section5.zip。 それはそれを解凍してくださいよ、私のためにフォルダを作成し、 すべての内容を膨らませて、そこに入れます。 だから今は、cdコマンドを使用して、私のセクション5のディレクトリに入ることができます。 クリアを使用して画面をクリアします。だから、画面をクリアします。 今、私はに対処するための良いクリーンな端末を持っている。 今私は、私は、このディレクトリに表示されるすべてのファイルを一覧表示する場合、 buggy1、buggy2、buggy3、とbuggy4:あなたは、私が4ファイルを持っていることがわかります。 私もそれに対応する。cファイルを持っている。 私たちは、今のところは。cファイルを見に行くわけではありません。 その代わりに、我々は、GDBを開くときにそれらを使用するつもりです。 私たちは、GDBを使っているときに我々は実際のソースコードへのアクセス権を持っているように、それらの周りを守ってきた GDBで周りが、セクションのこの部分の目的は、手を加えている 我々は、これらの4つのバギーの各プログラムで間違って何が起こっているのかを把握するためにそれを使用する方法を参照してください。 だから我々は単に、本当に迅速に部屋の周りに行くんだ と私は、バギーのいずれかのプログラムを実行するために誰かに依頼するつもりです その後、我々は、GDBを介​​してグループとして行くだろう、と我々は、これらのプログラムを修正するために何ができるのかがわかります あるいは少なくともそれらの各々に間違った何が起こっているかを識別することができます。 ダニエルと一緒にここからやり直してみましょう。あなたはbuggy1を実行するのだろうか?何が起こるか見てみましょう。 [ダニエル]それは、アプリケーションの障害があると言う。 >>うん。その通りです。 私はbuggy1を実行した場合だから、私はワンセグ障害を取得します。 この時点で、私は、行くとbuggy1.cを開く可能性 試してみて、間違って何が起こっているのかを把握 しかし、このセグメントフォルトエラーについての最も嫌なものの一つ それは実際に間違っていたと壊したどのようなプログラムの物事の行にあなたを教えていないということです。 あなたのコードを見ているの種類 との推測を使用して把握し、チェックやprintf間違った何が起こっているのを参照してください。 GDBは約クールなものの一つは、それが本当に、本当に簡単だということです プログラムがクラッシュした時のラインを把握する。 それは完全にそれだけで、そのためにも、それを使用する価値がある。 だから、GDBを起動するために、私はGDBを入力し、[私が実行したい実行可能ファイルへのパスを与える。 ここで私は、gdb ./buggy1を入力している。 ENTERキーを押してください。 、私にすべてのこの著作権情報を提供します 上下ここでは、/ home /からシンボルを読み込む "と言う、この行が表示されます jharvard/section5/buggy1。 " すべてがうまくいけば、あなたはそれがこのようなメッセージを出力し表示されます。 それはシンボルを読んでみよう、それは "私は、あなたの実行可能ファイルからシンボルを読んでいる"と言うでしょう そして、次に、それはこっちにこの "done"メッセージを持つことになります。 この他のいくつかのバリエーションを参照するか、またはあなたはそれがシンボルを見つけられませんでした表示された場合 またはそのような何かは、何を意味するとちょうど正しく実行ファイルをコンパイルしていないということです。 我々は、GDBで使用するためのプログラムをコンパイルするとき、私たちは、その特別な-gフラグを使用する必要が あなたのプログラムをコンパイルした場合、そのことは単に入力して、デフォルトでは終わった またはそれらのいずれか、バギーを作るか、または回復させる。 しかし、あなたはClangのを使って手動でコンパイルしているなら、あなたはに行くと、その-gフラグを入れておかなければなりません。 この時点で、今我々は、GDBのプロンプトを使用していること、 それは、プログラムを実行するのは非常に簡単です。 我々は、いずれかの実行を入力するか、または私達はちょうどrを入力することができます。 最も多くのGDBコマンドは省略できます。 通常かなりいいですちょうど1またはカップルの手紙、へ。 あなたはタイプRと入力し、Enterを押せばそれで、サアド、何が起こりますか? [Saadは]私は、SIGSEGV、セグメンテーションフォールトを持って、そして、すべてのこの無意味な言葉。 >>うん。 申し訳画面上で見ているような、とSaadさんが言ったように、 我々は、実行またはrを入力して、Enterを押したとき、我々はまだ同じセグメントフォルトを取得します。 だからGDBを使用して私たちの問題を解決していません。 しかし、それは私たちにいくつかの無意味な言葉を与え、それはこの無意味な言葉が判明 それが起こっている場所を実際に教えてくれる。 この少しを解析するには、この最初のビットはすべてが間違って起こっている機能です。 そこにこの_ strcmp_sse4_2だし、それはそれは、このファイルで何が起こっていることを教えてくれる sysdeps/i386と呼ばれる、このすべて、再び、混乱の種 - しかし、ライン254。 ことは、解析するのは難しいのようなものだ。通常はこのようなものを見たとき、 それはそれはシステムライブラリのいずれかに断層ワンセグていることを意味します。 strcmp関数とは何かはそう。君たちは前にstrcmpを見てきました。 ではない、あまりにも狂ったが、これはstrcmp関数が壊れているか、strcmp関数に問題があることを意味するのでしょうか? あなたはアレキサンダー、どう思いますか? [アレキサンダー]ということです - 254ラインですか?と - しないバイナリが、それは彼らの天井ではないが、 その後、各関数の別の言語があります。その関数内でその254がある、または - ? >>これは、ライン254です。それはおそらく、この。sファイルでどのように見えるので、それはアセンブリコード。 しかし、私は、我々はワンセグ障害を得ているので、より差し迫ったものは、であることを推測する それはstrcmp関数から来ているように見え、 これはstrcmpが壊れている、その後、意味するものではありません? それがうまくいけば、するべきではありません。だから、あなたがセグメンテーションフォールトを持っているので、 システム機能の一つで、一般的にあなたがちょうどそれを正しく呼び出していないことを意味すること。 実際に何が起こっているのかを把握するために行うには最速のもの あなたはワンセグ障害を見るたびに、このような狂気何かを見たとき、 あなただけのメイン以上を使っているプログラムを持っている場合は特に、 バックトレースを使用することです。 私は完全なバックトレース言葉とは対照的に、BTを書き込むことによって、バックトレースを省略できます。 しかしシャーロットは、BTを入力し、エンターを押したときに何が起こるか? [シャルロット]それは私に2つの行、行0と1行目を示しています。 >>うん。だからライン0と1行目。 これらは、あなたのプログラムがクラッシュしたときインプレーに現在あった実際のスタックフレームです。 最上位のフレーム、フレーム0から開始されて、フレーム1である、一番下に行く。 私たちの一番上のフレームには、strcmpのフレームです。 あなたは、これで我々だけでポインタを使ってクイズにやっていたことが問題に似たものと考えることができます 我々はメインスタックフレームの上にスタックフレームを交換していたところ、 そして我々はスワップがメインで使用されていた変数の上に使用していた変数を持っていた。 私たちのメインの関数から呼び出された私たちのstrcmp関数で起こったここに私たちのクラッシュ、 バックトレースは、私たちに物事は失敗している機能だけでなく、与えている すべてのものが呼び出された場所が、それはまた、私たちに言っている。 だから私は、右にもう少し上をスクロールした場合、 我々は、ええ、我々はこの関数strcmp-sse4.sファイルの行254にあったことがわかります。 しかし、コールはbuggy1.c、6行目で行われた。 私達はちょうどチェックアウトして、何が起こっていたか見に行くことができている - 私たちにできることを意味するので、 buggy1.c、6行目で。 繰り返しになりますが、これを行うためのいくつかの方法があります。一つは、GDBを終了することである またはあなたのコードが他のウィンドウとのクロスリファレンスで開く必要があります。 今、あなたはオフィスの営業時間にならないため、それは、それ自体が、かなり便利です そして、あなたはワンセグ障害を持っていると、すべてが破壊された場所をTFのは不思議 あなただけの "ああ、6行目、と言うことができます。私は、何が起こっているのか分からない しかし、6行についての何かが私のプログラムが破損する原因となっている。 " それを行うための他の方法は、GDBのリストと呼ばれる、このコマンドを使用することができます。 またリットルとそれを短縮することができます。 我々はリットルを押せばそれで、私たちはここで何を得るのですか? 我々は奇妙なものの全体の束を取得します。 これは、実際のアセンブリコードです それはstrcmp_sse4_2になっています。 これは、ファンキーのようなものを探します そして我々はこれを取得している理由は、今からです GDBがフレーム0で私たちを持っています。 だから、いつでも我々は見ての変数で、我々はソースコードを見て、いつでも、 我々はインチ現在の通貨スタックフレームに関連するソースコードを見ている だから、意味のある何かを得るために、我々はする必要はあり より理にかなっているスタック·フレームに移動します。 この場合、メインスタックフレームは、もう少し意味があるだろう それは実際に我々が書いたコードだったので。 strcmpのコードではない。 我々は2つ​​を持っているので、あなたは、この場合には、フレーム間を移動することができる方法、 我々は、0と1を持っている あなたは、上下コマンドを使用して行うこと。 私は1つ上のフレームに移動する場合は、 今私はメインスタックフレームにいるよ。 私は、私がいた場所に戻って上下に移動することができます 再び下り、再び上がると、再び上がる。 あなたがこれまでにGDBでプログラムを行う場合には、クラッシュすることでしょう、あなたは、バックトレースを取得 そして、あなたはそれはあなたが何が起こっているか知っていないいくつかのファイルでのことがわかります。 あなたがリストを試して、コードは、あなたに見覚えはありません あなたのフレームを見て、あなたがどこにいるか把握する。 あなたは間違っているスタック·フレームにはおそらくだ。 あるいは、少なくとも、あなたが本当にデバッグできるものではないスタックフレームにしている。 今、我々は適切なスタック·フレームにしていることを、我々は、メインにしている 今、私たちはラインが何であったかを把握するには、listコマンドを使用することができます。 そして、あなたはそれを見ることができ、それは右ここに私たちのためにそれを印刷した。 しかし、我々はすべて同じで、リストは私たちに、この素​​敵なプリントアウトを与えるリストを打つことができる ここで起こっている実際のソースコード。 特に、我々は、6行目で見ることができます。 我々はここで何が起こっているかを見ることができます。 そして、我々は文字列の比較を作っているように見える 文字列 "CS50岩"とargv [1]の間。 このことについて何かがクラッシュしていました。 ミッシーだから、あなたはここで何が起こっている可能性があります上の任意の考えを持っていますか? [ミッシー]私はそれがクラッシュしている理由がわからない。 >>あなたは、それがクラッシュしている理由がわからない? ジミー、任意の考え? [ジミー]私は全くわからないんだけど、我々は文字列を使用した最後の時間を比較し、 またはstrcmpの、我々はそれの下の3つの異なる例のようでした。 我々は、==を持っていなかったが、私は右、その最初の行で、とは思わない。 代わりに、それは、3つに分離し、1 == 0だった 1 <0、私が思うに、一つは> 0であった。 そのようなので、多分何か? >>うん。だから、この問題があります の我々は、正しく比較をやっている? ステラ?任意の考え? [ステラ]私はよく分からない。 >>わからない。ダニエル?考えですか?オーケー。 それは、まさにここで起こっていることが判明し、我々はプログラムを実行したときです 初めて、ダニエルのためのプログラムを実行したとき、我々は、ワンセグ障害を持って あなたはそれを任意のコマンドライン引数を与えたのでしょうか? [ダニエル]ナンバー>>第その場合は、argv [1]の値は何ですか? >>値はありません。 >>は右。 まあ、適当な文字列値はありません。 しかし、いくつかの値があります。そこに格納されている値とは何ですか? >>ガベージ値はありますか? >>それは、この場合には、どちらかゴミ値だか argv配列の終わりは常にnullで終端されています。 それでは、実際に格納されてしまったと、nullがあります。 他のこういった問題を解決することではなく、を介してそれを考えて、 それをプリントアウトしてみることです。 私は、GDBを使用して偉大であることを言っていたところです あなたは、すべての変数は、必要なすべての値をプリントアウトすることができますので、 この便利で素晴らしいpコマンドを使用します。 私はpを入力し、もしそうなら、私は、変数または変数の名前の値を入力します 、argcを言う、私はargcが1であることがわかります。 私は、argvをプリントアウトしたい場合は[0]が、私はちょうどそのように行うことができます。 そして、我々が見たように、argv [0]は常にあなたのプログラムの名前で、 常に実行可能ファイルの名前。 ここでは、それが完全なパス名を持っている参照してください。 私も、何が起こるか見ARGV [1]プリントアウトすることができます。 ここでは、神秘的な価​​値のこの種を得た。 我々は、この0x0を得た。 我々は、16進数の数字の話期首に覚えていますか? またはhexで50を表現する方法についてPSET 0の終了時に、その少し疑問? 私達はちょうど私達自身を混同しないように、CSで16進数を書く方法 十進数で、我々は常に0xでそれらを接頭辞です。 だから、この0xプレフィックスは常にちょうど、16進数で、次の数字を解釈することを意味 文字列ではなくではなく、10進数ではなく、二進数として。 番号5-0進の有効な数値であるので。 そしてそれは、10進数、50の番号です。 だから、これは私たちがどのように曖昧さをなくすだけです。 だから0x0はまた、10進数の0、2進数の0は16進数の0を意味します。 それだけで値0です。 これは、メモリ内に、実際に、これはnullがあるものであることが判明した。 nullがちょうど0になります。 ここでは、argvに格納されている要素[1]はnullです。 だから我々は、NULL文字列に私たちの "C​​S50岩"という文字列を比較しようとしている。 だから間接参照NULL、NULLで物事をアクセスしようとし、 それらは、一般的に発生するセグメンテーションエラーまたは他の悪い事のいくつかの並べ替えを引き起こすかもしれません。 そして、それはstrcmpを確認してくださいしないことが判明 あなたは、nullの値に渡されたかどうか。 むしろ、それは単に先に行くと、そのことを実行しようとすると、 それは障害をワンセグならば、それは障害をワンセグ、そしてそれはあなたの問題です。あなたはそれを修正するに行かなければならない。 本当にすぐに、我々はこの問題をどのように解決するのでしょうか?シャーロット? [シャルロット]は次のような場合は、使用して確認できます。 もしそうであればargv [1]がnullの場合、== 0の場合、1を返し、とか[理解不能]。 >>うん。だから、我々は確認することができますように、それを行うための一つの大きな方法だ 我々はstrcmp関数は、argvに合格しようとしている値は、[1]、それはnullになります? それがnullの場合は、次に我々は、abortを大丈夫と言うことができます。 これを行うには、より一般的な方法はargcの値を使用することです。 あなたは、主の初めに右ここに見ることができます 我々は、我々は、コマンドライン引数を使用するときに我々が一般的に行うことをその最初のテストを省略 これは、私たちのargcは値は、我々が期待するものであるかどうかをテストすることです。 この場合において、我々は、少なくとも2つの引数を期待している プログラムの名前に加え、他の1。 我々はここに第二引数を使用しようとしているから。 だから私たちのstrcmpの呼び出しの前に、あらかじめテストのいくつかの並べ替えを持っ argvが少なくとも2であるかどうかをテストするには、また同じようなことをするだろう。 そのプログラムを再度実行して動作している場合我々は見ることができます。 あなたはいつも本当にいいですGDBは、内でプログラムを再起動することができます。 、実行することができますし、あなたのプログラムに引数を渡すとき あなたは、GDBを起動するときは、runをコールするときにそれらを渡しません。 そうすればあなたは、異なる引数を指定して、それぞれの時間をあなたのプログラムを呼び出しておくことができます。 だから、もう一度実行するか、または、私は、rを入力して、我々が "こんにちは"と入力すると何が起こるか見てみましょうことができます。 再度最初からそれを起動したい場合、それは常にあなたを尋ねてきます。 通常は、もう一度最初からそれを起動したいです。 再び、この時点で、それはそれを再起動し、それがプリントアウト 私たちが実行していることをプログラム、buggy1、こんにちは引数を指定して、 そしてそれは、この標準出力を出力し、それは悲しい顔をして "あなたは、Dを得る"と言う。 しかし、我々はseg faultをしませんでした。それは、そのプロセスが正常に終了しましたと述べた。 だからそれはかなりよさそうだ。 これ以上のセグメントフォールト、我々は、それが過去行われません それは確かに我々が得ていたワンセグ障害のバグだったようなので、それが見えます。 残念なことに、それは我々がDを取得していることを教えてくれる 我々は戻ってコードを見て、そこに何が起こっていたかがわかります 何であったかを把握する - それは我々がDを得たことを告げた理由 ここで、これはprintfのあなたがDを得たことを言っていた、見てみましょう 我々はリストを入力した場合、入力中リストを保持するように、それは、あなたのプログラムを介してダウン繰り返し処理を続け そうそれはあなたのプログラムの最初の数行をお見せしましょう​​。 それはあなたに次の数行を表示し、次のチャンク、次のチャンクう。 それがダウンして行くことにしようとしておこう。 そして今、我々が買ってあげる "行番号16が範囲外です。" それだけで15行を持っているので。 この時点までに取得し、あなたの疑問に思った場合は、 "私は何をしますか?"あなたは、helpコマンドを使用することができます。 助けて、その後それをコマンドの名前を与える使用。 そして、あなたは、GDBが私たちのもののすべて、この種を提供してください。 これは、以前上場後または約10以上の行を一覧表示し、引数を指定しないと "と言う。 リスト - 前に10行をリスト - " だからリストマイナスを使ってみましょう。 そして、それは10行が前の一覧表示、あなたはリストで少し周りを再生することができます。 このリストは、リストを行うことができます - 、あなたもリスト8のように、番号を一覧与えることができる、 そしてそれは、8行目の周りの10行をリストアップします。 あなたがもし、他の単純なを持っているそして、あなたはここで何が起こっているのか見ることができます。 あなたはCS50岩を入力すると、それは "あなたはAをもらう"プリントアウト それ以外の場合は、 "あなたはDを得る"プリントアウト がっかりの町。かしこまりました。はい? だから私は、引用符なしCS50岩をやってみました[ダニエル] それは "あなたはDを得る"と言う 私はそれを動作させるために引用符を必要とし、その理由は何ですか? >>うん。これは別の楽しい小さなちらほらです - それは、時が判明 - 我々はそれを実行し、我々はCS50岩石に入力する場合は、プログラムを実行すると、 同じように、ダニエルは、彼がやったと言っていました、そしてあなたは、Enterキーを押す それはまだ我々はDを得ると言う との質問ですが、これはなぜですか? そしてそれは私たちのターミナルとGDBの両方がこれらの2つの別個の引数として解析することが判明した。 スペースがあるときに、それは次のように暗黙のだから 最初の引数は終了し、次の引数が始まろうとしている。 2にそれらを結合する方法、または申し訳ありませんが、一つの引数に、 引用符を使用することです。 だから今、私たちは、引用符でそれを入れて、再びそれを実行する場合、我々はAを取得 だから要約すると、引用符なし、CS50と岩が2つの別個の引数として解析されていません。 重引用符で、それは完全に一つの引数として解析だ。 私たちは、ブレークポイントでこれを見ることができます。 これまでのところ、我々のプログラムを実行してきた、それが実行されている どちらかが故障ま​​たはヒット、エラーはsegまで まで、またはそれが終了している、すべてが完全に罰金となっています。 時にはので、これは必然的に最も有用なものではありません あなたのプログラムでエラーが発生しているが、それはセグメンテーションフォルトを起こすわけではありません。 それはあなたを停止するためのプログラムまたはそのような何かを起こしていない。 あなたのプログラムが特定のポイントで一時停止するには、GDBを取得する方法 ブレークポイントを設定することです。 あなたは関数名でブレークポイントを設定することによってこれを行うことができます または、コードの特定の行にブレークポイントを設定することができます。 覚えやすい、 - ので、私は、関数名でブレークポイントを設定したい そしてあなたが実際に行くと、少しの上のあなたのソースコードを変更した場合、 その後、ブレークポイントは、実際にあなたのコード内の同じ場所にとどまります。 一方、あなたは、行番号を使用していて、行番号が変更した場合 あなたには、いくつかのコードを追加したり削除したりするので、次にあなたのブレークポイントはすべて完全に台無しにされています。 私が行う最も一般的なものの一つは、main関数にブレークポイントを設定しています。 多くの場合、私は、GDBを起動します、私は、Bメインを入力しますEnterキーを押すと、そのブレークポイントを設定します ただ "あなたが実行を開始するとすぐに、プログラムを一時停止"と言うメイン関数上 私はと言うと、2つの引数としてCS50岩を私のプログラムを実行し、そのように、 そして、Enterキーを押すと、main関数に到達すると、それは右の非常に最初の行で停止します それはstrcmp関数を評価する直前。 私が一時停止しているので、今私の周りいじくると何が起こっているのを見て起動することができます 私のプログラムに渡され、異なる変数のすべてを持つ。 ここで私はargcをプリントアウトして何が起こっているのか見ることができます。 それはそれで3つの異なる値を持っているので、argcが3であることがわかります。 それはプログラムの名前を持っている、それは第一引数と第二引数を持っている。 我々は、argv [0]、argv [1]に、とargv [2]を見て、それらのうちを印刷することができます。 このstrcmp関数呼び出しが失敗しようとしている理由はだから今も見ることができ、 あなたはそれが2つの別々の引数にCS50や岩を分割しなかったことを見ているから。 ブレークポイントにヒットしたらこの時点で、あなたはあなたのプログラムをステップ実行し続けることができます 行ずつ、などもう一度プログラムを開始することに反対した。 再度、ちょうどあなたのプログラムを起動したくない場合は、だから、ここから続けて 最後に、プログラムを実行するには、continueコマンドを使用して、処理を継続できます。 ちょうどそれは、ここで行ったような。 私はプログラム、CS50岩を再起動した場合しかし、それは、再び私のブレークポイントをヒット 私はプログラムの残りの部分を介してすべての道を行くしたくない場合は、今回は、 私はまた、nと省略する次のコマンドを使用することができます。 そして、これはプログラムを1行ずつステップ実行します。 物事を実行するようにあなたは物事が更新されはじめると、、のような変数の変化を監視することができます。 これはかなりいいです。 他のクールなことは、何度も何度も何度も同じコマンドを繰り返すのではなく、ある あなたは、単にEnterを押せば - そうここにあなたが私が何かに入力していないを参照してください - 私は、単にEnterを押した場合、それは、前のコマンドを繰り返すことになります または私はちょうどインチ置くことを以前のGDBコマンド 私は、Enterを押すと保つことができますし、それはラインで私のコード行をステップ実行しておこう。 私は君たちがなく、他のバギープログラムをチェックアウトしに行くことを勧めます。 我々は今日のセクションでそれらのすべてを介して取得する時間がありません。 ソースコードがあるので、あなたは何が起こっているかの種類を見ることができます あなたが本当に困ったとき舞台裏で、 しかしせめて、ちょうど、GDBを起動中の練習 それがあなたがたの上に中断するまで、プログラムを実行している 、クラッシュはしていたどのような機能を考え出す、バックトレースを取得 何行には、いくつかの変数の値をプリントアウトしていた それは本当にあなたが今後に役立つのでちょうどので、それの感触を得る。 この時点で、我々はあなたが終了するか、ただQを使用してください、GDB、外に終了するつもりです。 あなたのプログラムがまだ実行中であり、そしてそれは、終了していない場合 それはいつもあなたを聞いてきます、 "あなたは本当に終了してもよろしいですか?" あなただけはい打つことができます。 今、私たちは猫のプログラムである我々が持っている次の問題は、見ていくつもりです。 あなたがリダイレクトやパイプの短いのを見れば、あなたは、トミーがこのプログラムを使用することがわかります それは基本的に画面にファイルのすべての情報を出力します。 私は猫を実行するのであれば、これは、アプライアンスに実際には組み込みのプログラムであり、 あなたがMacを持っている場合は、端​​末を開いた場合、あなたは、あまりにもあなたのMac上でこれを行うことができます。 そして、我々 - 猫、のは、cp.cを言わせて、Enterを押してください。 これが何をしたか、我々は少し上にスクロールし、我々はラインを実行した場所が表示される場合 または我々は、catコマンドを実行したところ、それは文字通り、弊社の画面にcp.cの内容をプリントアウト。 我々は再びそれを実行することができますし、一緒に複数のファイルに置くことができます。 それで、あなたは猫のcp.cを行うことができます、そして、我々はまた、cat.cファイルを連結することができます それは我々が書き込みしようとしているプログラムであり、 そしてそれは私たちの画面に背中合わせに両方のファイルを印刷します。 私たちは少し上にスクロールした場合そこで、我々は見ている我々は、この猫cp.c、cat.cを実行したとき 最初にそれはcpファイルをプリントアウトしてから、その下に、それは右のダウンここcat.cファイルをプリントアウト。 私達はちょうど私達の足が濡れるためにこれを使用するつもりです。 端末への簡単な印刷で遊んで、その様子を見てください。 君たちが、gedit cat.cで開く場合は、Enterキーを打つ あなたは私たちが書き込みしようとしていることをプログラムを見ることができます。 我々は、この素敵なボイラープレートを用意しましたので、我々はすべて、アウトを入力する時間を費やす必要はありません。 また、渡された引数の数をチェック 私たちは素敵な使用方法のメッセージを出力します。 これは、私たちが話してきたように、再び、ものの一種です それはほとんど筋肉の記憶のようなものだ。 だけのものと同じ種類のものをやり続けることを忘れないでください と常に有用なメッセージのいくつかの並べ替えをプリントアウト ので、人々はあなたのプログラムを実行する方法を知っている。 猫と一緒に、それは非常に簡単です、我々はちょうど別の引数のすべてを通過しようとしている それが我々のプログラムに渡された、と我々は印刷するつもりだ 一度に1画面にその内容を外に。 画面にファイルをプリントアウトするために、我々は非常によく似た何かをやろうとしている 我々はクイズの最後に行ったのと。 プログラムを雇うクイズの終わりに、我々は、ファイルを開く必要がありました その後、我々はそれに印刷しなければならなかった。 この場合において、我々はファイルを開くしようとしている、と我々は代わりにそれから読むつもりだ。 その後、我々は、ファイルに出力するのではなく、しようとしている、我々は画面に出力しようとしている。 ですから、すべてのprintfと前やった画面への印刷。 だからそれはあまりにもクレイジーではありません。 しかし、ファイルを読んでいると変なの一種です。 我々は一度その少し通過するでしょう。 あなた達は自分のクイズ、問題33でその最後の問題に戻ると 我々がここでやろうとしていることを最初の行には、ファイルを開いて、私たちはそこに何をしたかと非常に似ています。 ステラだから、我々はファイルを開いたときに、そのようなラインを見ていますか? [ステラ]キャピタル·FILE *と、ファイル - >>さて。 >> - fopenのと同じです。 >>うん。 このケースではどれですか?それはコメントであります。 >>それはコメントでですか? ARGV [i]とR? まさに>>。右に。だからステラは全く正しいです。 これは線のように見えるものです。 我々は、このFILE *に保管しますので、すべてのキャップをファイルストリーム変数を取得するつもりだ、 ファイル、*、この変数の名前がファイルになります。 我々は好きなようにそれを呼び出すことができます。我々は我々が望むものは何でも、それはfirst_file、またはfile_i呼び出すことができます。 し、ファイルの名前は、このプログラムへのコマンドラインに渡された。 だからそれは、argvに格納されているの[i、]、それから私達は、読み取りモードでこのファイルを開くしようとしている。 今我々は、我々は常に行うには覚えなければならないことことだ何、ファイルを開いてしまったことを 我々は、ファイルを開いてしまったときに?それを閉じます。 ミッシーので、どのように我々は、ファイルをクローズするには? [ミッシー] fcloseを(ファイル)>> fcloseを(ファイル)。その通りです。 グレート。オーケー。私たちは右ここにコメントを行うには、この見れば、 それが "オープンのargv [i]は、標準出力にその内容を印刷します"と言う。 標準出力には、奇妙な名前です。 stdoutは言うちょうど私たちの方法です 我々は、端末にそれを印刷したい、我々は、標準出力ストリームにそれを印刷したい。 我々は、実際に右ここにこのコメントを取り除くことができます。 私はそれをコピーして、それは我々がやったことだから、それを貼り付けるつもりです。 この時点で、今、私たちは少しして、ファイルのビットを読まなければならない。 我々は、ファイルを読み込むのはいくつかの方法について説明してきました。 どれが今のところお気に入りですか? どの方法があなたが見ているか、ファイルを読むために、覚えていますか? [ダニエル] freadは? >> freadは?だから、freadは一つです。ジミーは、任意の他の人を知っていますか? [ジミー]いいえ>>オーケー。いや。シャーロット?アレクサンダー?すべて他人?オーケー。 だから、他のものは、我々は多くを使用しますので、1 fgetcはされています。 また、fscanfはあります;君たちはここにパターンを参照してください? 彼らはすべてのfで始まります。ファイルとすることを何でも。 freadは、fgetcは、fscanfはあります。これらは、読み取り機能のすべてです。 我々はfwriteを持って書くために、私たちの代わりにfgetcのは、fputcを持っています。 我々はまた、我々はfprintfのクイズで見たように持っている。 これは、ファイルからの読み込み伴う問題ですので、 我々は、これら3つの関数のいずれかを使用するつもりです。 ここでは、これらの機能をダウンを使用するつもりはない。 これらの関数は、すべての標準I / Oライブラリで発見されています。 ですから、このプログラムの先頭を見れば、 あなたは我々がすでに標準I / Oライブラリのヘッダファイルが含まれていたことがわかります。 、我々は我々が使用する1把握したい場合 我々は常に、manページを開くことができます。 だから我々は男がstdio入力することができます AとCのstdio入出力関数についてのすべてを読み そして、我々はすでに、ああ、見て確認することができます。それはfgetc関数に言及いる、それは、fputcに言及だ。 だから、fgetcは、少しドリルダウンして、見て、言うことができます とそのmanページを見てみましょう。 あなたはそれが他の機能の全体の束と一緒に行くことがわかります: fgetcは、fgetsの場合、getc、getchar関数は、ungetcを取得し、文字や文字列のその入力。 だから、これは、我々は標準入力からファイルから文字や文字列で読む方法です。 これは、ユーザーから本質的になる。 そして、これは我々が実際のC言語でそれを行う方法です。 だから、これはGetStringメソッドとgetchar関数を使用していない 我々は、CS50ライブラリから使用されることを確認します。 我々はいくつかの方法でこの問題をやろうとしている そのようにあなたはそれを行うための2つの異なる方法を見ることができます。 ダニエルが述べたとfgetcは、両方のfread関数は、それを行うには良い方法です。 ご覧のように私は、それが唯一持っているので、fgetc関数は、少し簡単だと思う、 我々はから文字を読み取るしようとしている一つの引数は、FILE * その戻り値はintです。 そして、これは右、少し混乱しています? 我々が文字を取得しているので、なぜこれはcharを戻しません? 君たちは、これはchar型を返さない可能性がありますなぜ上の任意のアイデアがありますか? [ミッシーに答え、理解不能] >>うん。だから、ミッシーは全く正しいです。 それがASCIIの場合、この整数は実際のcharにマップすることができる。 ASCII文字でなければ、それは右である可能性があります。 それは正確に何が起こっているかだ。 我々は、単にそれがより多くのビットを持っているので、int型を使用しています。 私たちのchar型は8ビットのみを有しており、当社の32ビットマシン上で1バイトという、それはchar型よりも大きいです。 とintは宇宙のすべての4バイト分を持っています。 そして、それは方法はfgetc関数が機能していることが判明し、 我々は、このマニュアルページで当社の概要で少し下にスクロールした場合、 すべての方法を下にスクロールします。それは、彼らがEOFと呼ばれるこの特殊な値を使用していることが判明した。 それはfgetc関数の戻り値として特殊な定数です たびにファイルの終わりをぶつけたり、エラーが発生した場合。 そして、それは、適切にEOFで、これらの比較を行うことが判明 あなたはint型で持っている情報は、余分な量を持つようにしたい としてchar型の変数を使用するのではなく。 fgetcは、効果的にファイルから文字を取得しているにもかかわらず、 あなたはそれがあなたにint型の何かを返していることを覚えておきたい。 それはそれはかなり使いやすいですが、言った。 それは私達に文字を与えるために起こっている、ので、我々がしなければならないすべては、ファイルを求めておくです "、私に次の文字を与える、私に次の文字を与える、私に次の文字を与える" 我々は、ファイルの終わりに到達するまで。 そしてそれは、我々のファイルから1文字ずつ引っ張ってくることになり それから私達は私達がそれと同じようなことを行うことができます。 我々はそれを保存することができます、我々はそれをプリントアウトすることができ、それを文字列に追加することができます。 それのいずれかを実行します。 バックアウトズームと私たちのcat.cプログラムに戻って、 我々はfgetc使うつもりなら、 どのように我々はこのコードの次の行に近づくのでしょうか? 我々は、使用しようとしている - freadはわずかに異なる何かを行います。 そして今回は、我々だけで、一度に1つの文字を取得するにはfgetc関数を使用するつもりです。 ファイル全体を処理するには、何を我々はしなければならないのでしょうか? そこにファイル内の何文字ですか? がたくさんあり​​ます。だから、あなたはおそらく1を取得したい し、別のを取得し、別のを取得し、別のものを得る。 あなたは私たちがここで使用しなければならないことがあり、アルゴリズムのどのようなお考えですか? どのようなタイプの - ? forループ[アレキサンダー] A?まさに>>。 ループのいくつかのタイプ。 forループはこのケースでは、実際に素晴らしいです。 あなたは、ファイル全体をループしたいようにし、あなたが言ったように、それは、音 一度に1文字を取得する。 どのようになるか上の任意の提案ですか? [アレキサンダー、不明朗] >>さて、ちょうどあなたがやろうとしていることを英語で教えてください? [アレキサンダー、不明朗] 我々だけで、ファイル全体をループしようとしているようですので、この場合には、それが聞こえる。 [アレキサンダー]それで、i >大きさ - ? 私は右、ファイルのサイズを推測する?サイズ - we'llはちょうどそれをこのように書きます。 当分の間、ファイルのサイズは、i + +は。 だから、それは方法は、あなたがこのfgetc関数を使用しないことが判明し、これは新しいです 単にファイルのサイズを取得する簡単な方法はありませんということです あなたが前に見てきた構築物のこの "sizeof"演算タイプを持つ。 我々はfgetc関数を使用する場合、我々はいくつかの種類を紹介しています だけではなく、基本的なカウンタを使用してこのforループに新しい、ファンキーな構文、 文字単位で行くために、私たちは一度に1つの文字を引っ張っていくつもりですが、 1文字ずつ、そして我々は終わりにしている知っている方法 我々は特定の文字数をカウントしたときに、ではない しかし、我々は引き抜くときに文字は、ファイルの文字の特殊なエンドです。 だから我々は、これを行うことができます - 私はこのCHを呼び出して、我々はそれを初期化するつもりだ ファイルのうち最初の文字を取得するための我々の最初の呼び出しで。 右ここにこの部分ので、これには、ファイルの文字を取得する予定です と変数chに格納します。 我々は、ファイルの終わりに到達するまで、我々はこれをやり続けるつもりだ、 我々は特別なEOF文字に等しくない文字のためにテストすることによって行うことができる。 代わりにCHをやって、次に+ +どちらただ、値をインクリメントしたい 我々は、ファイルのうち、資本金、言う、読むそうだとすれば CH + +私たちにbを与えるだろうし、我々は、cとdを得ると思います。 それは我々が望むものをはっきりとではありません。我々はここで何をしたい この最後のビットを私たちはファイルから次の文字を取得したいです。 では、どのようにファイルから次の文字を得るかもしれない? どのように我々はファイルの最初の文字を取得するのですか? [学生] fgetfile? >> fgetcは、または、申し訳ありませんが、あなたは完全に正しかった。 私は右のそれをそこにスペルミス。うんそう。 ここでは代わりにchを行う+ + 私達はちょうど再びfgetc関数(ファイル)を呼び出すつもりだ と私たちの同じchの結果を変数に格納します。 [学生の質問、不明朗] これらのFILE *の連中が特殊である場合>>です。 彼らは仕事のやり方は、彼らです - あなたが最初に開いたとき - あなたが最初にfopenの呼び出しを行ったときに、 FILE *とは、効果的に、ファイルの先頭へのポインタとして機能します。 そして、あなたはfgetc関数を呼び出すたびに、そのファイルを介して1つの文字を移動します。 だから、あなたがこれをコールするたびに、あなたは1つの文字でファイルポインタをインクリメントしている。 そして、あなたは再びFGETCたとき、あなたはそれを別の文字を移動している と別の文字と他の文字と別の文字。 [学生の質問、理解不能] >>そしてthat's - ええ。 それは、ボンネットの下にこの魔法のようなものだ。 あなただけを介してインクリメント保つ。 この時点では、実際に文字を対象に処理を行うことが可能になりました。 それでは、どのように我々は今、スクリーンにこれをプリントアウトするのでしょうか? 我々は、我々が前に使用したのと同じprintfのものを使用することができます。 我々はすべての学期を使用してきたこと。 我々は、printfを呼び出すことができます。 そして我々はちょうどそのように文字を渡すことができます。 それを行うための別の方法は、むしろprintfを使用していて、この形式の文字列を実行することよりも、ある 我々はまた、他の関数のいずれかを使用することができます。 我々は、画面に文字を出力fputcとを、使用することができます 我々はfputcと見ている場合を除き、 - 私は少しズームアウトしてみましょう。 それは我々はfgetc関数を使用して読み出すことが文字を取り込んでいる私たちは、素敵なものを見る しかし、我々はそれに印刷するためのストリームを与える必要があります。 我々はまた、標準出力に直接配置しますputchar関数を使用することができます。 だから我々は、印刷のために使用できるさまざまなオプションの全体の束があります。 彼らは、標準I / Oライブラリ内のすべてだ。 印刷したいときはいつでも - だからprintf関数は、デフォルトで、出力ストリームに専用の標準出力されます そのstdoutはどちらです。 だから我々はちょうどここでstdout、この魔法の値のようなものとしてそれを参照することができます。 おっと。外にセミコロンを置きます。 これは、ここで新たな、ファンキーな情報がたくさんある。 これの多くは、これがコードであるという意味で、非常に慣用句です それは、読みやすいように読んできれいだという理由だけでこのように書かれている。 それを行うには多くの異なる方法では、使用できるさまざまな機能がありますが、 しかし、我々は単に何度も何度も、これらと同じパターンに従う傾向がある。 あなたが何度も何度も出てくるこのようなコードが表示される場合はそう驚くことはありません。 かしこまりました。この時点で、我々はその日のために分割する必要があります。 来てくれてありがとう。あなたがオンラインなら見てくれてありがとう。そして、我々は来週お会いしましょう​​。 [CS50.TV]