1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [セクション5 - より快適] 2 00:00:02,500 --> 00:00:04,690 [ロブボーデン - ハーバード大学] 3 00:00:04,690 --> 00:00:07,250 [これはCS50です。 - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> 私は私の電子メールで述べているように、あなたが使用できるものがたくさんあり​​ます 5 00:00:14,250 --> 00:00:17,060 実際問題セットを実行するアプライアンス以外。 6 00:00:17,060 --> 00:00:19,910 我々は、我々はより簡単にあなたを助けることができるという理由だけでは、アプライアンスでそれを行うことをお勧めします 7 00:00:19,910 --> 00:00:22,070 そして我々は、すべてが動作するように起こっているか知っています。 8 00:00:22,070 --> 00:00:26,950 しかし、言う場合は、物事を行うことができます場所の一例としては、アクセス権を持っていない 9 00:00:26,950 --> 00:00:31,570 アプライアンスへのか、科学センターの地下で仕事をしたい - 10 00:00:31,570 --> 00:00:33,090 その実際に彼らはあまりにもアプライアンスを使用している - 11 00:00:33,090 --> 00:00:35,150 あなたがどこでも仕事をしたい場合。 12 00:00:35,150 --> 00:00:42,370 一例は、SSHの見て/聞いたことがあるのですか? 13 00:00:44,380 --> 00:00:47,780 SSHは、ちょうど何かに接続するように基本的にです。 14 00:00:47,780 --> 00:00:51,340 実際に、今私は、アプライアンスにSSHedよ。 15 00:00:51,340 --> 00:00:54,290 私は、アプライアンスで直接作業することはありません。 16 00:00:55,930 --> 00:01:01,060 ここアプライアンスがあり、ここでダウンして見てみると、このIPアドレスを参照してください。 17 00:01:01,060 --> 00:01:03,650 私は、アプライアンス自体では動作しません; 18 00:01:03,650 --> 00:01:08,840 私はいつもiTerm2ウィンドウ/ターミナルウィンドウにやって来る。 19 00:01:08,840 --> 00:01:15,910 あなたは、そのIPアドレス、SSH jharvard@192.168.129.128へのSSHができます。 20 00:01:15,910 --> 00:01:20,390 それはこのような素敵なパターンなので、私は非常に簡単にその番号を覚えています。 21 00:01:20,390 --> 00:01:24,920 しかし、それは私のパスワードを私に尋ねるでしょう、そして今私は、アプライアンスにいるよ。 22 00:01:24,920 --> 00:01:33,060 基本的に、この時点では、場合は、アプライアンス自体の内部端子を開放 23 00:01:33,060 --> 00:01:36,350 このインタフェースは、しかし、あなたがそれを使用するでしょう、まったく同じです 24 00:01:36,350 --> 00:01:40,010 インターフェイスとして、私はこっちに使っていますが、今はSSHedいる。 25 00:01:42,240 --> 00:01:44,920 アプライアンスへのSSHをする必要はありません。 26 00:01:44,920 --> 00:01:52,360 そこにSSH可能性がある別の場所の一例は、私はあなたがデフォルトで持っているかなり確信している - 27 00:01:52,360 --> 00:01:55,020 ああ。ビガー。 28 00:01:55,020 --> 00:02:01,130 あなたのすべては、FASのサーバーでデフォルトのFASのアカウントである必要があります。 29 00:02:01,130 --> 00:02:06,840 私にとって、私はrbowden@nice.fas.harvard.eduへのSSHだろう。 30 00:02:06,840 --> 00:02:11,610 それはあなたが初めて聞いて起こっている、とあなたは "はい"と言う。 31 00:02:11,610 --> 00:02:15,840 私のパスワードは私のFASのパスワードであることを行っている。 32 00:02:15,840 --> 00:02:22,650 それで今、私は素敵なサーバーにSSHedている、と私は私はここにしたい何かを行うことができます。 33 00:02:22,650 --> 00:02:28,560 あなたが取るかもしれない多くのクラスは、124のように、あなたがここにコンテンツをアップロードする必要があるとしている 34 00:02:28,560 --> 00:02:30,950 実際にあなたの問題セットを提出する。 35 00:02:30,950 --> 00:02:34,100 しかし、あなたがお使いのアプライアンスへのアクセスを持っていないと言う。 36 00:02:34,100 --> 00:02:37,910 それは言うだろう、ここでのように、あなたは、物事を行うことができます - 37 00:02:37,910 --> 00:02:42,160 これはただの質問の私達のセクションです。 38 00:02:42,160 --> 00:02:45,070 これは、アプライアンスでこれを行うよう求めてきます。 39 00:02:45,070 --> 00:02:47,790 代わりに私は、サーバー上でそれを行うだけでしょう。 40 00:02:47,790 --> 00:02:50,560 私はそれを解凍するつもりです。 41 00:02:50,560 --> 00:02:55,670 問題は、あなたが、geditのようなものを使用するために使用していることになるだろう 42 00:02:55,670 --> 00:02:58,160 アプライアンスのまたは任意の内部。 43 00:02:58,160 --> 00:03:01,830 あなたは、FASのサーバー上のそのを持っているつもりはない。 44 00:03:01,830 --> 00:03:04,110 これは、すべてのちょうどこのテキストインターフェースになるだろう。 45 00:03:04,110 --> 00:03:09,180 だから、どちらか1、彼らが持ってないことをテキストエディタを習得しようとするかもしれません。 46 00:03:09,180 --> 00:03:12,130 彼らは、ナノを持っています。 47 00:03:12,130 --> 00:03:14,990 ナノは、通常、かなり使いやすいです。 48 00:03:14,990 --> 00:03:19,470 あなたの矢印を使用して、正常に入力することができます。 49 00:03:19,470 --> 00:03:21,250 だからそれは難しいことではありません。 50 00:03:21,250 --> 00:03:24,720 あなたが本当に空想取得したい場合は、Emacsを使うことができ、 51 00:03:24,720 --> 00:03:29,850 私もEmacsを終了する方法がわからないので、これは私はおそらく開かれているべきではありません。 52 00:03:29,850 --> 00:03:32,760 コントロールのX、コントロールC?うん。 53 00:03:32,760 --> 00:03:35,310 またはあなたは、私が使用しているものですVimを使用することができます。 54 00:03:35,310 --> 00:03:37,800 そしてそうそれらはあなたのオプションは次のとおりです。 55 00:03:37,800 --> 00:03:43,830 あなたが見れば、することができ、また、そうしたくない場合はmanual.cs50.net- - 56 00:03:43,830 --> 00:03:45,410 ああ。 57 00:03:45,410 --> 00:03:49,920 PCでは、SSHは、PuTTYを使用することができます 58 00:03:49,920 --> 00:03:51,940 そのシステムとは別にダウンロードする必要があるとしている。 59 00:03:51,940 --> 00:03:55,460 Mac上で、あなただけのデフォルトでターミナルを使用するか、または、iTerm2をダウンロードすることができます 60 00:03:55,460 --> 00:03:58,490 これは良い、空想ターミナルのようなものです。 61 00:03:58,490 --> 00:04:03,780 あなたはmanual.cs50.netに行く場合は、メモ帳+ +へのリンクが表示されます 62 00:04:03,780 --> 00:04:07,120 これは、あなたがPC上で使用できるものです。 63 00:04:07,120 --> 00:04:13,340 それはあなたのメモ帳+ +は、基本的にSSHのであるから、SFTPをすることができます。 64 00:04:13,340 --> 00:04:17,750 これは何をあなたが行うようになると、ローカルにあるファイルを編集 65 00:04:17,750 --> 00:04:20,670 その後、あなたがそれらを保存したい時はいつでも、それは、nice.fasに保存されます 66 00:04:20,670 --> 00:04:23,670 どこでそれらを実行することができます。 67 00:04:23,670 --> 00:04:26,880 およびMac上で同等のTextWranglerになるだろう。 68 00:04:26,880 --> 00:04:28,760 だから、あなたが同じことを行うことができます。 69 00:04:28,760 --> 00:04:32,800 それは、あなたがローカルにファイルを編集し、nice.fasにそれらを保存することができます 70 00:04:32,800 --> 00:04:35,730 どこでそれらを実行することができます。 71 00:04:35,730 --> 00:04:40,400 あなたがこれまでアプライアンスずに立ち往生している場合は、それで、あなたは、これらのオプションを持っている 72 00:04:40,400 --> 00:04:44,230 それでも問題セットを行う。 73 00:04:44,230 --> 00:04:48,250 1問題は、CS50ライブラリを持っているつもりはないことになるだろう 74 00:04:48,250 --> 00:04:51,580 nice.fasはデフォルトであることを持っていないため。 75 00:04:51,580 --> 00:04:55,970 あなたはどちらCS50ライブラリをダウンロードすることができます - 76 00:04:55,970 --> 00:04:58,470 私はこの時点ではその必要はないと思う。 77 00:04:58,470 --> 00:05:03,270 あなたはどちらか、CS50ライブラリをダウンロードしてnice.fasにそれをコピーすることができます 78 00:05:03,270 --> 00:05:07,450 または私はこの時点で我々はとにかくそれをもう使用しないと思います。 79 00:05:07,450 --> 00:05:12,720 我々が行う場合、または、あなたは時間に置き換えていることができます 80 00:05:12,720 --> 00:05:18,480 とにかくCS50ライブラリ内の関数の実装。 81 00:05:18,480 --> 00:05:21,370 だから制限の多くはないはずです。 82 00:05:21,370 --> 00:05:23,710 そして、それはそれだ。 83 00:05:26,460 --> 00:05:29,820 >> 私は今、アプライアンスに戻って行くよ、我々は、アプライアンスに全力を尽くします。 84 00:05:29,820 --> 00:05:37,510 私は私の電子メールの中で述べたように、初めに、質問の私達のセクションを見てみると、 85 00:05:37,510 --> 00:05:43,620 我々はあなたが見ることになっていた短い1の話をしなければなりません。 86 00:05:43,620 --> 00:05:51,980 我々は、リダイレクトとパイプと、これらの3つの質問があります。 87 00:05:51,980 --> 00:05:56,070 >> するストリームのような関数は、printfデフォルトで書くのですか? 88 00:05:56,070 --> 00:05:59,130 だからストリーム。ストリームとは何ですか? 89 00:06:06,520 --> 00:06:15,100 それは単にいくつかのような流れは、基本的には - 90 00:06:15,100 --> 00:06:21,450 それも、1と0のソースではありません。 91 00:06:21,450 --> 00:06:24,920 それがここに求めているストリームは標準外です。 92 00:06:24,920 --> 00:06:27,250 それで、標準出力は、あなたがそれに書き込むことストリームです 93 00:06:27,250 --> 00:06:30,940 それが画面に表示されます。 94 00:06:30,940 --> 00:06:36,860 標準出力は、ストリームによって、それはあなただけで、それには、1と0書き込みを意味 95 00:06:36,860 --> 00:06:40,220 と標準出力のもう一方の端は、まさにそれをストリームから読み込みます。 96 00:06:40,220 --> 00:06:43,540 それはちょうど1と0の文字列です。 97 00:06:43,540 --> 00:06:45,570 あなたは、ストリームに書き込むこともできますし、ストリームから読み込むことができます 98 00:06:45,570 --> 00:06:47,950 ストリームが実際に何であるかによって異なります。 99 00:06:47,950 --> 00:06:52,800 他の二つのデフォルト·ストリームは、標準的なエラーに標準装備されています。 100 00:06:52,800 --> 00:06:57,540 あなたがgetStringんいつで標準的であり、それはあなたのための入力のものを待っています。 101 00:06:57,540 --> 00:07:01,570 だから、それはあなたを待って、それは実際には規格に待っている、 102 00:07:01,570 --> 00:07:04,880 これは、あなたがキーボードでタイプしたときに取得されるものは本当にです。 103 00:07:04,880 --> 00:07:07,530 あなたはインチ規格に入力している 104 00:07:07,530 --> 00:07:10,050 標準エラー出力は、標準出力と基本的に同等である 105 00:07:10,050 --> 00:07:13,280 あなたが標準エラー出力に印刷するとき、それは、それを専門の 106 00:07:13,280 --> 00:07:16,770 あなたはそれだけにエラーメッセージを出力することになっている 107 00:07:16,770 --> 00:07:20,200 ので、画面に出力通常のメッセージを区別することができます 108 00:07:20,200 --> 00:07:24,560 彼らは標準出力または標準エラー出力に行ったかどうかに応じてエラーメッセージ対。 109 00:07:24,560 --> 00:07:28,660 あまりにファイル。 110 00:07:28,660 --> 00:07:32,440 標準標準入力、出力、標準エラー出力は、単に特別なストリームです 111 00:07:32,440 --> 00:07:36,810 しかし実際には、任意のファイルは、ファイルを開いたときに、バイトのストリームになる 112 00:07:36,810 --> 00:07:40,740 どこにあなたはちょうどそのストリームから読み込むことができます。 113 00:07:40,740 --> 00:07:47,770 あなたは、ほとんどの部分は、単にバイトストリームとしてファイルを考えることができます。 114 00:07:47,770 --> 00:07:51,190 だから彼らは、デフォルトではストリームに何を書くのですか?標準出力。 115 00:07:51,190 --> 00:07:56,980 >> >と>>の違いは何ですか? 116 00:07:58,140 --> 00:08:03,710 誰もが事前にビデオを見ましたか。オーケー。 117 00:08:03,710 --> 00:08:10,960 >は、あなたがファイルにリダイレクトする方法であることを行っている 118 00:08:10,960 --> 00:08:15,240 と>>また、ファイルに出力をリダイレクトしようとしている 119 00:08:15,240 --> 00:08:17,820 それは代わりに、ファイルに付加するだろう。 120 00:08:17,820 --> 00:08:23,430 たとえば、みましょう私は、右ここに辞書を持って起こると言う 121 00:08:23,430 --> 00:08:27,020 とdictの内側だけのものは、猫、犬、魚、犬です。 122 00:08:27,020 --> 00:08:31,530 あなたがコマンドラインで持っていることを1つのコマンドで、猫です 123 00:08:31,530 --> 00:08:34,539 これは、単にファイルに何があるか印刷しようとしている。 124 00:08:34,539 --> 00:08:40,679 だから私は、猫のdictを言うとき、それは猫、猫、犬、魚、犬を印字することになっている。つまり、すべての猫が何だ。 125 00:08:40,679 --> 00:08:46,280 それは猫、猫、犬、魚、犬標準出力に出力することを意味します。 126 00:08:46,280 --> 00:08:53,240 私が代わりにファイルにあることをリダイレクトしたい場合は、私は>を使用して、ファイルが何であれ、それをリダイレクトすることができます。 127 00:08:53,240 --> 00:08:56,460 私は、ファイルのファイルを呼ぶことにします。 128 00:08:56,460 --> 00:09:00,320 私は、ls場合だから今、私はファイルと呼ばれる新しいファイルを持って表示されます。 129 00:09:00,320 --> 00:09:05,700 私はそれを開く場合、それは猫には、コマンドラインで入れて正確に何を持っているために起こっている。 130 00:09:05,700 --> 00:09:11,040 私は再びそれを行う場合、だから今、それは、出力をファイルにリダイレクトするために起こっている 131 00:09:11,040 --> 00:09:13,930 と私は、まったく同じものを持っているつもりです。 132 00:09:13,930 --> 00:09:17,910 だから、技術的に、それは完全に我々が持っていたものを覆した。 133 00:09:17,910 --> 00:09:22,970 そして、私は辞書を変更した場合は私たちが表示されます、私は犬を取り出した。 134 00:09:22,970 --> 00:09:29,980 ここでもう一度ファイルに我々は猫のdictならば、我々は犬が除去された新しいバージョンを持っているつもりです。 135 00:09:29,980 --> 00:09:32,400 だから、それを完全に上書きされます。 136 00:09:32,400 --> 00:09:36,640 我々は>>を使用する場合は、代わりに、ファイルを追加するようになるだろう。 137 00:09:36,640 --> 00:09:40,860 さて、ファイルを開いて、我々は、我々は2回印刷だけ同じものを持って参照してください。 138 00:09:40,860 --> 00:09:44,920 それはかつてあったので、我々は元に追加されます。 139 00:09:44,920 --> 00:09:48,130 だからそれは何>と>>行う。 140 00:09:48,130 --> 00:09:50,580 次回は頼むん - それはそれについて尋ねることはありません。 141 00:09:50,580 --> 00:09:59,050 >> 我々が持っているもう一つは、標準出力をリダイレクトIF <、>、である 142 00:09:59,050 --> 00:10:01,970 <は標準をインチリダイレクトされようとしている 143 00:10:01,970 --> 00:10:12,050 我々は例があれば見てみましょう。 144 00:10:14,750 --> 00:10:16,930 私は、簡単な本当の自分を書くことができます。 145 00:10:17,870 --> 00:10:25,700 の任意のファイル、hello.cを見てみましょう。 146 00:10:56,060 --> 00:10:59,070 比較的簡単なファイル。 147 00:10:59,070 --> 00:11:03,570 私はちょうど私が先ほど入力した文字列が何であったかにかかわらず "こんにちは"を印刷し、文字列を取得しています。 148 00:11:03,570 --> 00:11:07,990 だからハローハロー、次に作る。/。 149 00:11:07,990 --> 00:11:10,720 今では、何かを入力するように私を求めている 150 00:11:10,720 --> 00:11:15,070 それはそれはインチ標準に入力する事で待っていることを意味 151 00:11:15,070 --> 00:11:20,450 だからロブ、私達はちょうどこんにちは言おうとしているインチ私は標準的にほしいと思うものは何でも入る! 152 00:11:20,450 --> 00:11:23,310 それは、ハローに標準出力にロブを印刷しています! 153 00:11:23,310 --> 00:11:28,860 私は、。/ helloとその後リダイレクトをするのであれば、 154 00:11:30,740 --> 00:11:34,310 今のあなただけのファイルからリダイレクトすることができます。 155 00:11:34,310 --> 00:11:41,720 私はいくつかのファイル、txtファイルに入れて、私は、ロブを置くのであれば 156 00:11:41,720 --> 00:11:52,300 私はハロー実行し、その後にファイルtxtをリダイレクトした場合、。/こんにちは、それはロブ、こんにちはと言うつもりだ!直ちに。 157 00:11:52,300 --> 00:11:57,160 それは最初のGetStringメソッドを取得し、それは、内標準を待っているとき 158 00:11:57,160 --> 00:12:01,730 における標準は、もはや入力を、取得するデータは手動でキーボードの上で待機されていません。 159 00:12:01,730 --> 00:12:05,980 その代わりに、我々はファイルtxtファイルからの読み込みに標準でリダイレクトしている。 160 00:12:05,980 --> 00:12:10,290 そしてそれは、単にラインロブあるファイルtxtファイルから読み取るために起こっている 161 00:12:10,290 --> 00:12:13,380 そして、次に、それはこんにちは、ロブを印字することになっている! 162 00:12:13,380 --> 00:12:18,180 そして、私が望んでいたならば、私も行うことができます。/こんにちは 00:12:21,500 その後こんにちはです、それの印刷、ロブ、その標準出力!、 164 00:12:21,500 --> 00:12:24,700 私は、独自のファイルにそれをリダイレクトすることができます。 165 00:12:24,700 --> 00:12:29,790 私はまさしくこんにちはファイルを呼ぶことにします - いや、私はしません、それは実行可能だから - txt2。 166 00:12:29,790 --> 00:12:40,150 さて、txt2はHelloになるだろう。/こんにちは 00:12:43,520 >> 質問はありますか? 168 00:12:45,900 --> 00:12:49,090 >> オーケー。それでは、ここではパイプラインを持っています。 169 00:12:49,090 --> 00:12:53,510 パイプは、リダイレクションの最後の単位です。 170 00:12:53,510 --> 00:12:58,750 >> ああ。私は、リダイレクションの1以上のユニットがあれば代わりにだと思います>あなたは2点を行う> 171 00:12:58,750 --> 00:13:01,070 それは標準エラーをリダイレクトだ。 172 00:13:01,070 --> 00:13:06,280 何かが標準エラーに行きそうだとすれば、それはtxt2に入れ得られないだろう。 173 00:13:06,280 --> 00:13:12,480 しかし、私は2をすれば気付く>、それはまだこんにちは、ロブを印刷しています!コマンドラインに 174 00:13:12,480 --> 00:13:18,600 私は唯一の標準エラー出力をリダイレクトしているので、私は標準をリダイレクトしていないよ。 175 00:13:18,600 --> 00:13:22,210 標準エラーおよび標準出力が異なっている。 176 00:13:24,210 --> 00:13:27,080 あなたは、実際には標準エラー出力に書きたい場合は、 177 00:13:27,080 --> 00:13:35,080 それから私はstderrにfprintfのようにこれを変更することができます。 178 00:13:35,080 --> 00:13:37,850 だからprintfは、デフォルトでは、標準出力に出力します。 179 00:13:37,850 --> 00:13:41,720 私は手動で標準エラー出力に出力したい場合は、私はfprintfを使用する必要があります 180 00:13:41,720 --> 00:13:45,010 と私が印刷したいものを指定します。 181 00:13:45,010 --> 00:13:49,720 代わりに私はfprintfを標準出力(stdout)を行った場合は、そのは、printfと基本的に同等です。 182 00:13:49,720 --> 00:13:55,530 しかし、標準エラー出力にfprintfを。 183 00:13:57,790 --> 00:14:03,650 だから今、私はtxt2にこれをリダイレクトする場合は、こんにちは、ロブ!まだコマンドラインで印刷されたばかり 184 00:14:03,650 --> 00:14:08,270 は標準エラー出力に出力さなってきたと私は唯一の標準をリダイレクトしているから。 185 00:14:08,270 --> 00:14:16,420 私は今、標準エラー出力をリダイレクトする場合は、ここでは印刷されませんでした、とtxt2こんにちは、ロブになるだろう! 186 00:14:16,420 --> 00:14:21,910 だから今、あなたは、標準エラー出力に、実際のエラーを印字することができます 187 00:14:21,910 --> 00:14:24,720 および標準への定期的なメッセージをプリントアウトする。 188 00:14:24,720 --> 00:14:31,420 それで、あなたがプログラムを実行すると、次のようにそれを実行することができます/こんにちはこのタイプを2で> 189 00:14:31,420 --> 00:14:33,800 ので、あなたのプログラムが正常に実行しようとしていること、 190 00:14:33,800 --> 00:14:38,400 しかし、あなたはあなたを取得したすべてのエラーメッセージは、エラー·ログで後で確認することができます 191 00:14:38,400 --> 00:14:44,500 エラーのように、後に見て、あなたのエラーファイルは、発生したエラーを持つことになります。 192 00:14:45,200 --> 00:14:47,540 >> 質問はありますか? 193 00:14:47,540 --> 00:14:58,070 >> 最後のものは一つのコマンドから標準を取るように考えることができますパイプ、ある 194 00:14:58,070 --> 00:15:01,210 それ次のコマンドの中で標準となっています。 195 00:15:01,210 --> 00:15:05,570 ここでの例では、echoは、コマンドラインの事です 196 00:15:05,570 --> 00:15:11,840 それはちょうど私がその引数として置くものは何でもエコーしようとしている。私は引用符を置くことはありません。 197 00:15:11,840 --> 00:15:16,150 エコー何とか、何とか、何とかはただ何とか、何とか、何とかを印刷しようとしている。 198 00:15:16,150 --> 00:15:20,600 前に、私が言ったとき、私はtxtファイルにロブを入れていた 199 00:15:20,600 --> 00:15:28,830 私はロブをエコーし​​ている場合私は/、代わりに、txtファイルをリダイレクトすることができますので、 200 00:15:28,830 --> 00:15:35,520 その後パイプそれ。/こんにちは、また同じタイプのものを行いますに。 201 00:15:35,520 --> 00:15:39,160 これは、このコマンドの出力は、エコーロブを取っている 202 00:15:39,160 --> 00:15:43,610 とするための入力としてそれを使用して、。/ helloです。 203 00:15:44,790 --> 00:15:49,560 あなたは、最初のファイルにエコーロブをリダイレクトと考えることができます 204 00:15:49,560 --> 00:15:54,160 し、ただ出力されました。/こんにちは、そのファイルに入力。 205 00:15:54,160 --> 00:15:57,850 しかし、それは、画像の一時ファイルを取り出す。 206 00:16:01,890 --> 00:16:04,460 >> その上で質問がありますか? 207 00:16:04,460 --> 00:16:07,150 >> 次の質問は、これを含むとしている。 208 00:16:07,150 --> 00:16:15,310 あなたはnames.txtと呼ばれるファイルに一意の名前の番号を見つけるためにどのようなパイプラインを使用することができます? 209 00:16:15,310 --> 00:16:24,160 次に我々はここで使用したいとしているコマンドは一意であるため、uniqの、トイレ。 210 00:16:24,160 --> 00:16:28,840 あなたは、実際にそれが何をするかを見たい場合は、man uniqを行うことができます 211 00:16:28,840 --> 00:16:34,840 とそれだけで入力から隣接一致する行をフィルタリングするために起こっている。 212 00:16:34,840 --> 00:16:40,690 そして男wcは改行、単語、および各ファイルのバイト数を出力しようとしている。 213 00:16:40,690 --> 00:16:43,760 そして、我々が使用したいとしている最後の1つは、ソートされ 214 00:16:43,760 --> 00:16:47,410 それはちょうどtxtファイルの行をソートしようとしている。 215 00:16:47,410 --> 00:16:58,080 私はいくつかのtxtファイル、names.txtを作り、それはロブ、トミー、ヨセフ、トミー、ヨセフ、RJ、ロブ、なら 216 00:16:58,080 --> 00:17:03,910 私はここでやりたいことは、このファイル内でユニークな名前の数を見つけることです。 217 00:17:03,910 --> 00:17:08,750 だから答えは何をすべきですか? >> [生徒] 4。 >>うん。 218 00:17:08,750 --> 00:17:13,780 ロブ、トミー、ヨセフ、RJは、このファイル内で一意の名前だけなのでそれは4でなければなりません。 219 00:17:13,780 --> 00:17:20,180 最初のステップは、私はちょうどnames.txt上のワードカウントを行う場合、 220 00:17:20,180 --> 00:17:24,290 これは実際に私にすべてを語っている。 221 00:17:24,290 --> 00:17:32,560 これは、実際に印刷である - 改行、単語、そしてバイト·カウント - 男性トイレ、見てみましょう。 222 00:17:32,560 --> 00:17:38,270 私が行だけを気にしている場合、私はちょうどトイレ - lのnames.txtを行うことができます。 223 00:17:41,730 --> 00:17:44,300 だからステップ1です。 224 00:17:44,300 --> 00:17:50,510 names.txtはちょうどすべての名前が含まれているため、しかし、私は、トイレ - lのnames.txtにしたくない 225 00:17:50,510 --> 00:17:54,170 と私は、すべての非一意のものを除外する。 226 00:17:54,170 --> 00:18:01,200 私はuniqはnames.txtをすればそう、それは非常に私は欲しいものを与えるものではありません 227 00:18:01,200 --> 00:18:03,760 重複する名前がまだ残っているからです。 228 00:18:03,760 --> 00:18:07,690 これはなぜですか? uniqは私が欲しいものをなぜしてるんじゃない? 229 00:18:07,690 --> 00:18:10,500 [学生]重複ではない[聞こえない] >>うん。 230 00:18:10,500 --> 00:18:16,370 uniqのためのmanページはフィルタ隣接マッチングラインを言うことを覚えています。 231 00:18:16,370 --> 00:18:19,680 彼らは隣接じゃないので、それらをフィルタリングしません。 232 00:18:19,680 --> 00:18:31,100 私が最初にそれらを並べ替える場合、並べ替えnames.txtは一緒にすべての重複行を入れることになるだろう。 233 00:18:31,100 --> 00:18:34,450 だから今ソートnames.txtはということです。 234 00:18:34,450 --> 00:18:40,550 uniqは|私はあるuniqは、への入力としてそれを使用するつもりです。 235 00:18:40,550 --> 00:18:43,390 それは私のヨセフは、RJ、ロブ、トミーを与える 236 00:18:43,390 --> 00:18:49,260 と私は、トイレ - lへの入力としてそれを使用したい 237 00:18:49,260 --> 00:18:52,740 それは私に4を与えるために起こっている。 238 00:18:52,740 --> 00:18:56,930 それがここで言うように、あなたはどのようなパイプラインを使用することができます? 239 00:18:56,930 --> 00:19:01,390 あなたは、一連のコマンドを使用して同じようにたくさんのことを行うことができます 240 00:19:01,390 --> 00:19:05,130 どこであなたは次のコマンドの入力としてコマンドからの出力を使用しています。 241 00:19:05,130 --> 00:19:08,780 あなたは物事の多くは、巧妙なたくさんのことを行うことができます。 242 00:19:08,780 --> 00:19:11,440 >> 質問はありますか? 243 00:19:12,910 --> 00:19:14,600 オーケー。 244 00:19:14,600 --> 00:19:17,880 パイプとリダイレクト用のそれはそのです。 245 00:19:18,370 --> 00:19:24,090 >> 今、私たちは、実際のものは、コーディングのものに進みます。 246 00:19:24,090 --> 00:19:29,100 このPDFの内部では、このコマンドが表示されます 247 00:19:29,100 --> 00:19:32,950 そして、あなたのアプライアンスでこのコマンドを実行するとよいでしょう。 248 00:19:36,240 --> 00:19:42,250 wgetのは、基本的には、ちょうどインターネットから何かを得るためのコマンドである 249 00:19:42,250 --> 00:19:45,180 そうwgetとこのURL。 250 00:19:45,180 --> 00:19:49,110 お使いのブラウザでこのURLに行ってきました場合は、そのファイルをダウンロードします。 251 00:19:49,110 --> 00:19:52,510 私はちょうどそれをクリックしたので、それは私のためにファイルをダウンロードしました。 252 00:19:52,510 --> 00:19:55,650 しかし、端末の内部にその事のwgetの書き込み 253 00:19:55,650 --> 00:19:58,620 ちょうどあなたの端末にそれをダウンロードしようとしている。 254 00:19:58,620 --> 00:20:02,750 、私はsection5.zip持っていて、section5.zipを解凍したいと思う 255 00:20:02,750 --> 00:20:06,520 あなたにセクション5と呼ばれるフォルダを与えるために起こっている、 256 00:20:06,520 --> 00:20:11,550 これは、我々はその中に今日使用されようとしているすべてのファイルを持っているとしている。 257 00:20:33,380 --> 00:20:37,710 これらのプログラムのファイル名が示唆するように、彼らは少しバギーだ、 258 00:20:37,710 --> 00:20:40,990 ので、あなたの使命は、gdbを使って理由を解明することである。 259 00:20:40,990 --> 00:20:44,560 それらは皆をダウンロードし/それらがダウンロード取得する方法を知っていますか 260 00:20:44,560 --> 00:20:47,480 それらのアプライアンスに?オーケー。 261 00:20:47,480 --> 00:20:56,400 >> ./buggy1実行し、それは、セグメンテーションフォールト(コアダンプ)を言うだろう 262 00:20:56,400 --> 00:21:00,500 そのあなたがセグメンテーションフォルトを取得し、いつでも、それは悪いことだ。 263 00:21:00,500 --> 00:21:03,810 どのような状況であなたはsegfaultを得るのですか? 264 00:21:03,810 --> 00:21:08,210 [学生]はNULLポインタを間接参照。 >>うん。だから、その一例である。 265 00:21:08,210 --> 00:21:11,580 あなたがセグメンテーションフォルトを取得するつもりだNULLポインタを間接参照。 266 00:21:11,580 --> 00:21:16,720 何segfaultを意味することは、あなたが触れるべきではないメモリを触れているである。 267 00:21:16,720 --> 00:21:21,350 だからヌルポインタを間接参照することにより、アドレス0に触れている 268 00:21:21,350 --> 00:21:28,060 そして基本的に、すべてのコンピュータは最近アドレス0は触れるべきではないメモリであると言う。 269 00:21:28,060 --> 00:21:31,920 セグメンテーションフォルトでNULLポインタを逆参照の結果、なぜようだ。 270 00:21:31,920 --> 00:21:37,210 あなたはポインタを初期化しないために起こるとき、それは、ゴミの値を持つ 271 00:21:37,210 --> 00:21:41,520 ので、あなたがそれをデリファレンスしようとすると、十中八九、メモリを触れている 272 00:21:41,520 --> 00:21:43,540 それは、辺ぴな所にあります。 273 00:21:43,540 --> 00:21:45,650 あなたは幸運とゴミ値を取得してしまった場合 274 00:21:45,650 --> 00:21:48,440 スタックまたは何かのどこかをポイントするように起こった、 275 00:21:48,440 --> 00:21:50,820 その後、ときにポインタを初期化していないことを間接参照するとき、 276 00:21:50,820 --> 00:21:52,730 何も間違って行くことはありません。 277 00:21:52,730 --> 00:21:55,480 しかし、それはどこかでスタックとヒープの間、と言う、を指している場合、 278 00:21:55,480 --> 00:21:59,850 またはそれだけでどこかに、まだあなたのプログラムで使用されていないために、その指している 279 00:21:59,850 --> 00:22:02,240 次にあなたが触れるべきではないメモリに触れていてはsegfault。 280 00:22:02,240 --> 00:22:06,370 再帰的な関数を書いて、それが何回も再帰した場合 281 00:22:06,370 --> 00:22:08,720 そしてあなたのスタックが大きくなりすぎたとの事にスタックが衝突 282 00:22:08,720 --> 00:22:12,270 それはと衝突してはならないこと、あなたが触れるべきではありませんメモリを触れている、 283 00:22:12,270 --> 00:22:14,810 ので、あなたはsegfault。 284 00:22:14,810 --> 00:22:17,010 つまりsegfaultをするものです。 285 00:22:17,010 --> 00:22:21,810 >> それはまた、あなたのような文字列を持っている場合と同じ理由だ - 286 00:22:21,810 --> 00:22:23,930 のは、前のプログラムに戻りましょう。 287 00:22:23,930 --> 00:22:28,530 hello.cの - は - 私にちょうど何か他のものを作るつもり。 288 00:22:28,530 --> 00:22:33,770 char *型S = "こんにちは、世界!"; 289 00:22:33,770 --> 00:22:42,310 私が使用している場合* S =何か、s [0] = 'X';を 290 00:22:42,310 --> 00:22:47,290 そうこんにちは作る、。/こんにちは、なぜそれはsegfaultしましたか? 291 00:22:48,410 --> 00:22:51,250 なぜこのようなことがsegfaultをしましたか? 292 00:22:55,660 --> 00:22:57,890 何が起こると思いますか? 293 00:22:57,890 --> 00:23:06,640 私が行った場合のprintf( "%s \ n"が、秒)、あなたは何を印刷したいと思いますか? 294 00:23:06,640 --> 00:23:09,930 [学生]×ハロー。 >>うん。 295 00:23:09,930 --> 00:23:15,140 問題は、あなたがこのような文字列を宣言するときにということである 296 00:23:15,140 --> 00:23:18,190 sは、スタック上に行くために起こっているポインタです 297 00:23:18,190 --> 00:23:25,880 とどのようなsが指しているのは、読取り専用メモリに格納されているこの文字列です。 298 00:23:25,880 --> 00:23:30,560 名前だけで、読み取り専用メモリによりだから、あなたのアイデアを取得する必要があります 299 00:23:30,560 --> 00:23:33,010 それは、読み取り専用メモリ内容変更しようとすると、 300 00:23:33,010 --> 00:23:36,670 あなたはメモリでやってされるべきではない何かをやっているとあなたはsegfault。 301 00:23:36,670 --> 00:23:45,360 これは実際にはchar * sとcharの[]の間には大きな違いです。 302 00:23:45,360 --> 00:23:48,790 だからcharの[]は、今、この文字列はスタックに置かれようとしている、 303 00:23:48,790 --> 00:23:53,960 およびスタックは、これは完全に正常に動作する必要がありますことを意味し、読み取り専用ではありません。 304 00:23:55,500 --> 00:23:57,370 そしてそれはありません。 305 00:23:57,370 --> 00:24:06,250 私は何のchar * S = "こんにちは世界!"、S自体がスタック上にあることを覚えておいてください 306 00:24:06,250 --> 00:24:10,390 が、sどこかを指し、それはどこかに読み取り専用であることを起こる。 307 00:24:10,390 --> 00:24:15,640 しかし、charの[]はスタック上の何かである。 308 00:24:17,560 --> 00:24:21,760 だからそれは起こってセグメンテーション違反の別の例です。 309 00:24:21,760 --> 00:24:27,820 >> 我々は./buggy1がセグメンテーション違反になったことを見た。 310 00:24:27,820 --> 00:24:31,810 理論的には、直ちにbuggy1.cで見てはいけない。 311 00:24:31,810 --> 00:24:35,170 代わりに、私たちは、gdbを介してそれを見てみましょう。 312 00:24:35,170 --> 00:24:37,750 あなたがセグメンテーションフォールトを(コアダンプ)を取得したときにすることに注意して、 313 00:24:37,750 --> 00:24:40,850 あなたはここに呼ばれるコアの上でこのファイルを取得します。 314 00:24:40,850 --> 00:24:45,200 我々は、ls-l場合には、当社はそのコアは通常かなり大きなファイルで表示されます。 315 00:24:45,200 --> 00:24:51,580 これは、ファイルのバイト数ですので、250代のキロバイトのように見えます。 316 00:24:51,580 --> 00:24:56,120 この理由は、コア·ダンプが実際に何であるということです 317 00:24:56,120 --> 00:25:01,410 あるとき、プログラムがクラッシュすると、あなたのプログラムのメモリの状態 318 00:25:01,410 --> 00:25:05,230 ただ、このファイルにコピー&ペーストされます。 319 00:25:05,230 --> 00:25:07,270 なお、ファイルにダンプされます。 320 00:25:07,270 --> 00:25:13,060 このプログラムは、それが実行されている状態で、約250キロバイトのメモリ使用量がたまたま 321 00:25:13,060 --> 00:25:17,040 となるように、このファイルにダンプされてしまったものだ。 322 00:25:17,040 --> 00:25:23,630 我々はgdb buggy1コアをすれば今度はそのファイルを見ることができます。 323 00:25:23,630 --> 00:25:30,130 私達はちょうどGDB buggy1を行うことができます、そしてそれはちょうど、定期的にgdbを起動します 324 00:25:30,130 --> 00:25:33,800 その入力ファイルとしてbuggy1を使用しています。 325 00:25:33,800 --> 00:25:38,260 gdbの使い方buggy1コアにした場合には、それが具体的にgdbを起動するために起こっている 326 00:25:38,260 --> 00:25:40,330 そのコアファイルを見ることによって。 327 00:25:40,330 --> 00:25:45,560 そして、あなたはbuggy1手段gdbを言ってと、そのコアファイルがbuggy1プログラムから来ていることを知っている。 328 00:25:45,560 --> 00:25:49,580 だからGDB buggy1コアがすぐに私たちをもたらすために起こっている 329 00:25:49,580 --> 00:25:52,060 プログラムが終了することを起こった場所へ。 330 00:25:57,720 --> 00:26:02,340 我々はここで、信号11、セグメンテーションフォルトで終了したプログラムを参照してください。 331 00:26:02,340 --> 00:26:10,110 我々は、おそらく非常に参考にされていないアセンブリの行を参照してくださいに起こる。 332 00:26:10,110 --> 00:26:15,360 あなたはBTまたはバックトレースを入力した場合でも、それは関数になるだろう 333 00:26:15,360 --> 00:26:19,430 それが私たちの現在のスタックフレームのリストを与える。 334 00:26:19,430 --> 00:26:23,150 だからバックトレース。我々は2つ​​だけのスタックフレームを持っているように見えます。 335 00:26:23,150 --> 00:26:26,310 第一は、私たちのメインスタックのフレームです 336 00:26:26,310 --> 00:26:29,810 2つ目は、我々はにたまたまいるこの関数のスタックフレームです 337 00:26:29,810 --> 00:26:34,440 我々は唯一のアセンブリコードを持っているように見えている。 338 00:26:34,440 --> 00:26:38,050 それでは、私たちのメイン関数に戻りましょう 339 00:26:38,050 --> 00:26:42,300 そして、我々はフレーム1を行うことができない、と私は、我々はまた、ダウンできると思うために 340 00:26:42,300 --> 00:26:45,160 アップまたは - しかし、私はほとんどダウンして行うことはありません。うん。 341 00:26:45,160 --> 00:26:50,710 上下。アップダウンスタックフレームをあなたをダウンさせ、1つのスタックフレームをあなたが表示されます。 342 00:26:50,710 --> 00:26:53,240 私はそれを使用しない傾向にあります。 343 00:26:53,240 --> 00:26:59,120 私は具体的には1のラベルが付いたフレームに移動されているフレーム1を、言う。 344 00:26:59,120 --> 00:27:01,750 フレーム1は、メインスタックフレームに私たちをもたらすために起こっている 345 00:27:01,750 --> 00:27:05,570 そしてそれは我々がであることが起こるのコード行を右ここに述べています。 346 00:27:05,570 --> 00:27:07,950 私たちはコードのカップル以上の行を検索したい場合、我々はリストを言うことができる、 347 00:27:07,950 --> 00:27:11,280 そしてそれは私達にそれを回避してコードのすべての行を与えるために起こっている。 348 00:27:11,280 --> 00:27:13,360 我々はsegfaultedラインは6であった: 349 00:27:13,360 --> 00:27:17,360 するif(strcmp関数( "CS50岩"は、argv [1])== 0)。 350 00:27:17,360 --> 00:27:24,130 それがまだ明確でない場合、あなたはそれがsegfaultedなぜ考えることによって、ここからまっすぐにそれを得ることができます。 351 00:27:24,130 --> 00:27:28,800 しかし、我々はさらに一歩それを取ると、 "なぜ、argvは[1] segfaultを起こすだろうか"、と言うことができます 352 00:27:28,800 --> 00:27:38,830 プリントargv [1]にしてみましょう、それがnullポインタであるそれの0x0の、のように見えます。 353 00:27:38,830 --> 00:27:44,750 我々は、CS50岩やnullをstrcmpingしていて、そのためにsegfaultを起こすために起こっている。 354 00:27:44,750 --> 00:27:48,280 そして、なぜですargv [1]をヌル? 355 00:27:48,640 --> 00:27:51,280 [学生]我々はそれをすべてのコマンドライン引数を与えていないので。 356 00:27:51,280 --> 00:27:53,390 うん。我々はそれをすべてのコマンドライン引数を与えなかった。 357 00:27:53,390 --> 00:27:58,460 だから./buggy1はargv [0]のこと./buggy1を持っているとしている。 358 00:27:58,460 --> 00:28:02,100 それは、argv [1]が、その結果は、セグメンテーション違反になるだろう持っていることはないだろう。 359 00:28:02,100 --> 00:28:07,450 しかし、代わりに、私はちょうどCS50行う場合、それはあなたがDを得ると言うために起こっている 360 00:28:07,450 --> 00:28:09,950 それはそれが行うことになっているものだからです。 361 00:28:09,950 --> 00:28:15,240 buggy1.cを見て、それを印刷することになっている "あなたは、Dを得る" - 362 00:28:15,240 --> 00:28:20,820 argvは[1] "CS50岩"は、他に、 "あなたは、Dを取得"されていない場合は "あなたが得る!" 363 00:28:20,820 --> 00:28:25,660 私たちが望むのであれば、我々は、真と比較するためにこれが必要 364 00:28:25,660 --> 00:28:28,710 これは、それが0に比較することを意味します。 365 00:28:28,710 --> 00:28:31,100 だから、argvは[1] "CS50岩"である必要があります。 366 00:28:31,100 --> 00:28:35,660 あなたは、コマンドラインでその処理を行いたい場合、スペースをエスケープするには\を使用する必要があります。 367 00:28:35,660 --> 00:28:41,690 だからCS50 \岩やあなたが取得! 368 00:28:41,690 --> 00:28:44,060 バックスラッシュを行わない場合は、なぜこれが動作しませんか? 369 00:28:44,060 --> 00:28:47,190 [学生]それは、2つの異なる引数です。 >>うん。 370 00:28:47,190 --> 00:28:52,540 argv [1]にはCS50になるだろう、とargv [2]は、岩になるだろう。オーケー。 371 00:28:52,540 --> 00:28:56,470 >> 今すぐ./buggy2は再びsegfaultをしようとしている。 372 00:28:56,470 --> 00:29:01,880 代わりに、そのコアファイルとそれを開くのでは、我々だけで、直接buggy2を開くよ 373 00:29:01,880 --> 00:29:05,000 gdbのbuggy2そう。 374 00:29:05,000 --> 00:29:09,590 私達はちょうど私達のプログラムを実行する場合、今、それはシグナルSIGSEGVを受信したプログラムを言おうとしている、 375 00:29:09,590 --> 00:29:15,530 それはセグメンテーションフォルト信号であり、それが起こることを起こった場所です。 376 00:29:15,530 --> 00:29:21,250 私たちのバックトレースを見ると、我々は、我々は関数oh_noにあったことがわかり 377 00:29:21,250 --> 00:29:23,900 関数BINKYによって呼び出された関数のちっぽけな、、によって呼び出された 378 00:29:23,900 --> 00:29:26,460 どちらがメインで呼ばれていた。 379 00:29:26,460 --> 00:29:31,680 我々はまた、これらの関数に引数を見ることができます。 380 00:29:31,680 --> 00:29:34,680 ちっぽけとBINKYへの引数は1であった。 381 00:29:34,680 --> 00:29:44,390 我々は関数oh_noをリストする場合は、我々はoh_noはただのchar ** S = NULLをやっていることがわかります。 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 なぜそれが失敗していました? 384 00:29:54,330 --> 00:29:58,380 [学生]あなたはNULLポインタを逆参照することはできません? >>うん。 385 00:29:58,380 --> 00:30:06,090 これは単に、それはchar **であることを起こるかどうかに関係なく、sがNULLであると言っている 386 00:30:06,090 --> 00:30:12,070 あなたがそれをどう解釈するかに応じて、それは文字列へのポインタへのポインタの場合もある、 387 00:30:12,070 --> 00:30:15,550 または文字列の配列。 388 00:30:15,550 --> 00:30:21,430 それはsがNULLですので、* sは、NULLポインタを間接参照している 389 00:30:21,430 --> 00:30:24,800 ので、これがクラッシュしようとしている。 390 00:30:24,800 --> 00:30:27,540 これはあなたがおそらくセグメンテーションフォルトができる最も簡単な方法の一つです。 391 00:30:27,540 --> 00:30:31,300 それはちょうどヌルポインタを宣言してすぐにセグメンテーションフォルトだ。 392 00:30:31,300 --> 00:30:34,570 それはoh_noがやっていることだ。 393 00:30:34,570 --> 00:30:43,400 我々は1つ上のフレームに行くなら、私たちはoh_no呼び出された関数に取得するつもりだ。 394 00:30:43,400 --> 00:30:44,830 私がダウンしていることを実行する必要があります。 395 00:30:44,830 --> 00:30:48,610 次のコマンドを入力しないと、あなただけ再度Enterを押すと、 396 00:30:48,610 --> 00:30:52,350 それはちょうどあなたが実行したことを前回のコマンドを繰り返すことになります。 397 00:30:52,350 --> 00:30:56,610 我々は、フレーム1にあります。 398 00:30:56,610 --> 00:31:04,650 このフレームの一覧表示、我々の関数であるここを参照してください。 399 00:31:04,650 --> 00:31:08,520 あなたは再びリストをヒットしたり、リスト20を行うことができますし、それはより多くのリストが表示されます。 400 00:31:08,520 --> 00:31:13,640 関数ちっぽけなiが1である場合、その後、oh_noの機能に行くと言う 401 00:31:13,640 --> 00:31:15,960 他こそこそ機能にアクセスしてください。 402 00:31:15,960 --> 00:31:18,700 そして、我々は我々がここまで見ることが起こるので、私は1知っている 403 00:31:18,700 --> 00:31:22,560 そのちっぽけな、引数1で呼び出されました。 404 00:31:22,560 --> 00:31:27,560 それとも、ただ私をプリント行うことができますし、それは私が1であると言うだろう。 405 00:31:27,560 --> 00:31:33,770 私たちはちっぽけで現在、我々は別のフレームを上がると、我々はBINKYで終わるでしょうね。 406 00:31:33,770 --> 00:31:36,600 アップ。今、私たちはBINKYにしている。 407 00:31:36,600 --> 00:31:41,340 この関数をリストする - 半分は私を断つ前からリスト - 408 00:31:41,340 --> 00:31:52,670 iが0であるかのようにそれは始まったし、我々は、それoh_no呼び出していくつもりですが、他のちっぽけな呼び出し。 409 00:31:52,670 --> 00:31:57,000 我々は、私が1であったことがわかっているので、ちっぽけと呼ばれる。 410 00:31:57,000 --> 00:32:05,030 そして今、我々は、メイン、メインに戻ってきただけます。int i = RAND()%3であることを行っている。 411 00:32:05,030 --> 00:32:08,790 それはちょうどあなたに0,1、または2のいずれかの乱数を与えるために起こっている。 412 00:32:08,790 --> 00:32:12,780 それは数字でBINKYを呼び出すために起こっている、それは0を返します。 413 00:32:12,780 --> 00:32:16,700 これを見ると、 414 00:32:16,700 --> 00:32:19,880 ただ、すぐにそれを実行せずに手動でプログラムを歩く 415 00:32:19,880 --> 00:32:25,400 あなたは私たちがプログラムを実行するときにすることを意味メイン、目にブレークポイントを設定します 416 00:32:25,400 --> 00:32:31,020 それがブレークポイントに達するまで、プログラムが起動実行されます。 417 00:32:31,020 --> 00:32:35,450 プログラムを実行しているので、それが実行され、それが主な機能にヒットし、実行を停止します。 418 00:32:35,450 --> 00:32:44,700 今、私たちは主の中にいると、stepやnextのコードの次の行に私たちを持って来るために起こっている。 419 00:32:44,700 --> 00:32:47,050 あなたは、stepやnextを行うことができます。 420 00:32:47,050 --> 00:32:51,800 次回打つ、今私は、RAND()%3、私たちは、iの値を印刷することができます、に設定されている 421 00:32:51,800 --> 00:32:55,280 そしてそれは私が1であると言うだろう。 422 00:32:55,280 --> 00:32:58,110 今では、私たちが次のまたはステップを使用するかどうかに関係ありません。 423 00:32:58,110 --> 00:33:01,000 私はそれ以前のもので大事だっと思いますが、我々は次の使用するとよいでしょう。 424 00:33:01,000 --> 00:33:06,000 我々はステップを使用する場合、我々は現物を見てみつまり、関数にステップインする 425 00:33:06,000 --> 00:33:07,940 それはBINKYの内側に起こっている。 426 00:33:07,940 --> 00:33:10,510 我々は次を使用している場合、それは関数を通すことを意味 427 00:33:10,510 --> 00:33:14,070 そして、弊社のメイン関数のコードの次の行に進みます。 428 00:33:14,070 --> 00:33:17,900 右ここでは、この行には、私はそれは、rand()%3言ったところであった; 429 00:33:17,900 --> 00:33:21,320 私は一歩をした場合、それは、randの実装に行くだろう 430 00:33:21,320 --> 00:33:25,110 そしてそこに何が起こっているかを見て、私は、rand関数をステップ実行することができます。 431 00:33:25,110 --> 00:33:26,920 しかし、私は、rand関数を気にしないでください。 432 00:33:26,920 --> 00:33:30,190 私はメインのコードの次の行に移動したいので、私は次の使用します。 433 00:33:30,190 --> 00:33:35,800 しかし、今私はBINKY機能について気にしないので、私はそれに足を踏み入れたいと思います。 434 00:33:35,800 --> 00:33:37,730 今私はBINKYにいるよ。 435 00:33:37,730 --> 00:33:42,040 コー​​ドの最初の行は、(i == 0)場合に言おうとしている、私は、一歩を踏み出す 436 00:33:42,040 --> 00:33:44,930 私たちはちっぽけで終わるを参照してください。 437 00:33:44,930 --> 00:33:51,620 我々はリストの事をした場合、我々はそれがi = 0であることを確認してください。 438 00:33:51,620 --> 00:33:55,470 、iは0に等しいではないので、それは他の条件に行ってきました 439 00:33:55,470 --> 00:33:59,540 そのちっぽけな(i)を呼び出すために起こっている。 440 00:33:59,540 --> 00:34:04,030 あなたは混乱してしまうでしょう。 441 00:34:04,030 --> 00:34:07,380 あなただけの直接これらの行を見れば、あなたは、(i == 0)場合と思うかもしれない 442 00:34:07,380 --> 00:34:10,800 大丈夫、私は一歩を踏み出した、今私はちっぽけな(i)によ 443 00:34:10,800 --> 00:34:14,120 あなたはそれがi = 0のか何かを意味しな​​ければならないと思われるかもしれません。 444 00:34:14,120 --> 00:34:18,980 いいえ、それはちょうどそれがラインちっぽけな(i)に直接貼ることができます知っていることを意味します。 445 00:34:18,980 --> 00:34:23,300 iが0ではないので、次のステップでは、他で終了するつもりはない。 446 00:34:23,300 --> 00:34:26,239 そうでなければで停止するように起こっているラインがありません。 447 00:34:26,239 --> 00:34:31,570 それだけでは、(i)貧弱である、それが実際に実行することができます次の行に移動するだろう。 448 00:34:31,570 --> 00:34:36,090 ちっぽけな(i)にステッピング、我々は、(i == 1)かどうかを確認します。 449 00:34:36,090 --> 00:34:42,670 我々は、i = 1のため、我々はステップするとき、我々はoh_noで終わるつもりだ知っている知っていますか 450 00:34:42,670 --> 00:34:46,489 i = 1であるあなたが足を踏み入れることができます関数oh_noを呼び出すため、 451 00:34:46,489 --> 00:34:52,969 はchar ** sは= NULLとすぐに "ブーム"に設定しようとしている。 452 00:34:54,270 --> 00:34:59,690 そして、実際にbuggy2の実装を見て、 453 00:34:59,690 --> 00:35:04,590 0,1、または2 - - 通話BINKY、これは、私だけで乱数を取得している 454 00:35:04,590 --> 00:35:10,610 iが0である場合、それは他のoh_no、それがここに来るちっぽけを呼び出し、呼び出されます。 455 00:35:10,610 --> 00:35:18,100 私は、コールoh_no 1であれば、そうでなければ、ここまで来れた、しなやかで優雅を呼び出す 456 00:35:18,100 --> 00:35:20,460 iが2である場合、oh_noを呼び出します。 457 00:35:20,460 --> 00:35:24,720 私も方法があるとは思わない - 458 00:35:24,720 --> 00:35:30,030 誰もがこのsegfaultをされないプログラムの作り方を見ていますか? 459 00:35:30,030 --> 00:35:37,530 私は何かが欠けている限り、私が0であれば、あなたはすぐにセグメンテーション違反になるため、 460 00:35:37,530 --> 00:35:41,250 他には、私はあなたがsegfaultを1であれば機能に行く 461 00:35:41,250 --> 00:35:44,540 他にはiが2である場合は、セグメンテーションフォルト機能に行く。 462 00:35:44,540 --> 00:35:46,810 だから、あなたが何をするかに関係なく、あなたはsegfaultしていません。 463 00:35:46,810 --> 00:35:52,380 >> 私は、それが代わりにchar ** S = NULLを行うのであろう固定させる方法の一例を推測 464 00:35:52,380 --> 00:35:55,610 あなたは、その文字列のためのスペースをmalloc関数可能性があります。 465 00:35:55,610 --> 00:36:04,230 sizeofのか - 我々は、malloc(sizeof演算)を行うことができます? 466 00:36:09,910 --> 00:36:15,190 [学生](char型)* 5? >>これは右の見えるのですか? 467 00:36:15,190 --> 00:36:21,060 私は実際にそれを実行した場合これがうまくいくと仮定しているが、それは私が探しているものではありません。 468 00:36:24,400 --> 00:36:32,940 sの型を見てみましょう。 int *を追加してみましょうので、int型* xになります。 469 00:36:32,940 --> 00:36:35,600 私はmalloc(sizeof(int))を行うだろう。 470 00:36:35,600 --> 00:36:40,490 または私は5の配列を検索したい場合、私は(sizeof(int)を* 5)するだろう。 471 00:36:40,490 --> 00:36:44,210 私は、int **を持っている場合はどうなりますか? 472 00:36:46,260 --> 00:36:49,140 私は、mallocう? 473 00:36:49,140 --> 00:36:53,510 [学生]ポインタのサイズ。 >>うん。 (はsizeof(int *)を); 474 00:36:53,510 --> 00:36:56,960 ここで同じことをダウン。 475 00:36:56,960 --> 00:37:01,280 私は(sizeof(char *)は)したい; 476 00:37:06,170 --> 00:37:12,840 これは "ブーム"を指すポインタに領域を割り当てるために起こっている。 477 00:37:12,840 --> 00:37:15,330 私は "ブーム"自体に領域を割り当てる必要はありません。 478 00:37:15,330 --> 00:37:17,210 これは私が前に言ったことと基本的に同じであるため、 479 00:37:17,210 --> 00:37:20,870 char型の* X = "ブーム"。 480 00:37:20,870 --> 00:37:27,950 "BOOM"はすでに存在しています。これは、メモリの読み出し専用領域に存在すると発生します。 481 00:37:27,950 --> 00:37:35,200 sはchar **型であれば、それはすでに、次のコード行を意味し、存在 482 00:37:35,200 --> 00:37:43,900 次に* sはchar *型であり、あなたが "ブーム"を指すように、このchar *を設定しています。 483 00:37:43,900 --> 00:37:50,040 私はsに "BOOM"をコピーしたい場合は、私は、sのためのスペースを割り当てる必要があります。 484 00:37:55,170 --> 00:38:03,900 私がやります* S =のmalloc(sizeofの型(char)* 5); 485 00:38:03,900 --> 00:38:06,210 なぜ5? 486 00:38:06,210 --> 00:38:10,860 なぜいけないの4? "BOOM"は4文字であるように見えます。 >> [学生]がnull文字。 487 00:38:10,860 --> 00:38:14,580 うん。あなたのすべての文字列は、ヌル文字を必要としています。 488 00:38:14,580 --> 00:38:23,590 今私は、strcatのような何かを行うことができます - 文字列をコピーするための機能とは何ですか? 489 00:38:23,590 --> 00:38:28,520 [学生] CPY? >> strcpyの。 490 00:38:28,520 --> 00:38:32,700 男strcpyの。 491 00:38:36,120 --> 00:38:39,590 だから、strcpyをstrncpyをや。 492 00:38:39,590 --> 00:38:43,410 あなたが正確にどのように多くの文字を指定できますので、strncpyは、少し安全です 493 00:38:43,410 --> 00:38:46,190 私たちが知っているので、しかし、ここでは重要ではありません。 494 00:38:46,190 --> 00:38:50,340 だからstrcpyおよび引数に見える。 495 00:38:50,340 --> 00:38:53,100 最初の引数は、私たちの目的地です。 496 00:38:53,100 --> 00:38:56,770 二番目の引数は、私たちの情報源です。 497 00:38:56,770 --> 00:39:10,310 我々は先の* sのポインタ "ブーム"にコピーしようとしている。 498 00:39:10,310 --> 00:39:19,820 なぜあなたは私たちが前に持っていただけで何の代わりにstrcpyのでこれをしたいと思うかもしれません 499 00:39:19,820 --> 00:39:22,800 * S = "ブーム"の? 500 00:39:22,800 --> 00:39:28,630 そこにあなたがこれをしたいと思うかもしれません理由があるが、その理由は何ですか? 501 00:39:28,630 --> 00:39:31,940 [学生]は "ブーム"の中で何かを変更したい場合。 >>うん。 502 00:39:31,940 --> 00:39:37,950 今私はSのような何かを行うことができます[0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 のポイントは、ヒープ上のヒープとその空間にsは、を指しているので、 504 00:39:48,190 --> 00:39:52,320 "BOOM"が格納されているヒープ上に多くのスペースへのポインタです。 505 00:39:52,320 --> 00:39:55,150 だから "ブーム"のこのコピーは、ヒープに格納されています。 506 00:39:55,150 --> 00:39:58,780 我々のプログラムで "ブーム"の2つのコピーが技術的にあります。 507 00:39:58,780 --> 00:40:03,500 ちょうどこの "ブーム"文字列定数で与えられている最初のものは、あります 508 00:40:03,500 --> 00:40:09,250 と "ブーム"の2番目のコピーは、strcpyのは "ブーム"のコピーが作成されます。 509 00:40:09,250 --> 00:40:13,100 しかし、 "ブーム"のコピーは、ヒープ上に格納され、ヒープあなたは自由に変更しているされています。 510 00:40:13,100 --> 00:40:17,250 ヒープが読み取り専用ではないので、ことはつまり、S [0] 511 00:40:17,250 --> 00:40:20,500 あなたは "ブーム"の値を変更できるようにする予定です。 512 00:40:20,500 --> 00:40:23,130 それはあなたがそれらの文字を変更できるようになるだろう。 513 00:40:23,130 --> 00:40:26,640 >> 質問はありますか? 514 00:40:27,740 --> 00:40:29,290 オーケー。 515 00:40:29,290 --> 00:40:35,500 >> レッツGDB buggy3、buggy3に移る。 516 00:40:35,500 --> 00:40:39,840 私達はちょうどそれを実行し、我々は我々がsegfaultを取得してください。 517 00:40:39,840 --> 00:40:46,550 我々はバックトレースする場合は、唯一の2つの機能があります。 518 00:40:46,550 --> 00:40:52,970 私達が私達の主な機能にまで行けば、私たちはこのラインでsegfaultedていることがわかります。 519 00:40:52,970 --> 00:41:00,180 だから、(ためには、この行を見てint型の行= 0; fgetsはこのようなものと等しくない場合はNULLをします; 520 00:41:00,180 --> 00:41:03,770 行+ +)。 521 00:41:03,770 --> 00:41:08,010 私たちの前のフレームが_IO_fgetsと呼ばれていました。 522 00:41:08,010 --> 00:41:10,720 組み込みのC関数とそのロットがわかります、 523 00:41:10,720 --> 00:41:15,350 あなたがセグメンテーションフォルトを取得するときに、本当に不可解な関数名が存在すること 524 00:41:15,350 --> 00:41:18,090 このような_IO_fgets。 525 00:41:18,090 --> 00:41:21,770 しかし、それはこのfgetsのコールに関連するだろう。 526 00:41:21,770 --> 00:41:25,850 どこか内部ここで、我々はセグメンテーションフォルトしています。 527 00:41:25,850 --> 00:41:30,340 我々はfgetsに引数を見れば、我々はバッファを印刷することができます。 528 00:41:30,340 --> 00:41:41,180 として印刷してみましょう - いや、ああ。 529 00:41:48,980 --> 00:41:51,900 プリントはまさに私はそれがしたいように仕事に行くのではない。 530 00:41:55,460 --> 00:41:58,000 実際のプログラムを見てみましょう。 531 00:42:02,200 --> 00:42:09,640 バッファは文字配列です。それは、128文字の文字配列です。 532 00:42:09,640 --> 00:42:14,980 だから私は、プリントバッファと言うとき、それは、それらの128文字を印字することになっている 533 00:42:14,980 --> 00:42:18,300 これは私が推測するには、期待されているものです。 534 00:42:18,300 --> 00:42:21,390 私は何を探していたとすると、バッファのアドレスを出力している 535 00:42:21,390 --> 00:42:23,680 それは本当に私に多くを教えてくれない。 536 00:42:23,680 --> 00:42:30,770 だから私はここでxのバッファを開くと言うことが起こるとき、それは、私に0xbffff090を示しています 537 00:42:30,770 --> 00:42:38,690 以前のまたはいくつかのポイントを覚えていれば、これ、Oxbffffはスタックっぽい地域になる傾向がある。 538 00:42:38,690 --> 00:42:46,020 スタックはちょうど0xC000から下のどこかを開始する傾向がある。 539 00:42:46,020 --> 00:42:51,890 ただ、このアドレスを見て、私は、バッファはスタック上に起こっていることを知っています。 540 00:42:51,890 --> 00:43:04,500 アップ、実行、私のプログラムを再起動し、我々が見たバッファは、この文字シーケンスであった 541 00:43:04,500 --> 00:43:06,530 それはかなり無意味です。 542 00:43:06,530 --> 00:43:12,270 次に、ファイルを印刷する場合、ファイルをどのように見えるか? 543 00:43:15,120 --> 00:43:17,310 [学生]はNull。 >>うん。 544 00:43:17,310 --> 00:43:22,610 、ファイルはFILE *型のなので、ポインタである 545 00:43:22,610 --> 00:43:26,610 そのポインタの値はnullになります。 546 00:43:26,610 --> 00:43:33,240 だからfgetsが、間接的な方法でそのポインタから読み取ろうとしている 547 00:43:33,240 --> 00:43:37,320 しかし、そのポインタにアクセスするためには、逆参照する必要があります。 548 00:43:37,320 --> 00:43:40,550 または、それが指すべきかをアクセスするためには、それを間接参照。 549 00:43:40,550 --> 00:43:43,810 だからそれはヌルポインタとセグメンテーションフォルトを間接参照だ。 550 00:43:46,600 --> 00:43:48,730 私はそこに再起動した可能性があります。 551 00:43:48,730 --> 00:43:52,170 私達は私達の主なポイントと実行時に中断した場合、 552 00:43:52,170 --> 00:43:57,320 コー​​ドの最初の行は、char *ファイル名= "nonexistent.txt"です。 553 00:43:57,320 --> 00:44:00,870 これは、このプログラムが失敗した理由として、かなり大きなヒントを与える必要があります。 554 00:44:00,870 --> 00:44:06,080 私はこのファイルを開く場所を次のように入力すると、次の行にいってみましょう 555 00:44:06,080 --> 00:44:11,140 その後、私はすぐに、かつて私は、次のヒット我々の行、入る、それはsegfaultになるだろう。 556 00:44:11,140 --> 00:44:16,880 誰も我々はセグメンテーションフォルトかもしれない理由をスローするようにしたいのですか? 557 00:44:16,880 --> 00:44:19,130 [学生]ファイルが存在しません。 >>うん。 558 00:44:19,130 --> 00:44:22,250 これがヒントであることになっている 559 00:44:22,250 --> 00:44:29,570 あなたがファイルをオープンするたびに、ファイルが実際に存在していることを確認する必要がある。 560 00:44:29,570 --> 00:44:31,510 そこでここでは、 "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 我々読書はfopenのファイル名は、我々はそれから言う必要があるとき 562 00:44:34,700 --> 00:44:45,870 場合(ファイル== NULL)やprintf( "ファイルが存在しません!"と言う 563 00:44:45,870 --> 00:44:56,340 または - まだ良い - ファイル名);戻り値1; 564 00:44:56,340 --> 00:45:00,300 だから今我々はそれがNULLであるかどうかを確認してください 565 00:45:00,300 --> 00:45:03,930 実際に継続して、そのファイルから読み取ろうとする前に。 566 00:45:03,930 --> 00:45:08,800 我々は、ちょうどそれがはたらくことを確認するためにそれをリメイクすることができます。 567 00:45:11,020 --> 00:45:14,970 私は、新しい行を含むことを意図する。 568 00:45:21,090 --> 00:45:25,290 だから今nonexistent.txtは存在しません。 569 00:45:26,890 --> 00:45:30,040 あなたは、常にこの種のことをチェックする必要があります。 570 00:45:30,040 --> 00:45:33,870 あなたは、常にfopenがNULLを返しているかどうかを確認する必要があります。 571 00:45:33,870 --> 00:45:38,170 あなたはいつも、mallocがNULLを返していないことを確認すべきです 572 00:45:38,170 --> 00:45:41,410 さもないとあなたはsegfault。 573 00:45:42,200 --> 00:45:45,930 >> 今すぐbuggy4.c。 574 00:45:49,190 --> 00:45:58,440 ランニング。私はこれが入力またはおそらく無限ループを待っていると推測している。 575 00:45:58,440 --> 00:46:01,870 はい、それは無限ループです。 576 00:46:01,870 --> 00:46:05,560 buggy4そう。我々が無限ループしているように見えます。 577 00:46:05,560 --> 00:46:12,590 我々は、主に破ることができる、私たちのプログラムを実行します。 578 00:46:12,590 --> 00:46:20,180 gdbで、限り、あなたは使う略語があいまいであるとして 579 00:46:20,180 --> 00:46:23,420 彼らはあなたのために提供したり、特殊な略語、 580 00:46:23,420 --> 00:46:29,020 その後はずっと次のOUT入力するのではなく、次のを使用する場合は、nを使用することができます。 581 00:46:29,020 --> 00:46:33,730 そして今、私は一度ヒットNできたので、私はちょうど隣続けるためにEnterキーを打つことができる 582 00:46:33,730 --> 00:46:36,640 代わりに、Enterキーは、nを入力し、nはnを入力しヒットする必要がなくなります。 583 00:46:36,640 --> 00:46:44,630 私は0に[i]の配列を設定してforループのいくつかの種類の中にいるように見えます。 584 00:46:44,630 --> 00:46:50,510 それは私がこのforループを抜け出したことがないように見えています。 585 00:46:50,510 --> 00:46:54,780 私は私の印刷なので、iが2であれば、私は次行くよ。 586 00:46:54,780 --> 00:46:59,250 私は、i、iが3である場合、私は次行くよ刷る。 587 00:46:59,250 --> 00:47:05,360 私は、私が印刷だろうと私は3です。次に、iを印刷し、私は4です。 588 00:47:05,360 --> 00:47:14,520 実際に、印刷はsizeof(配列)であるため、配列のサイズは20です。 589 00:47:16,310 --> 00:47:32,870 いくつかの特別なGDBコマンドは何かが起こるまで行くためにそこのようですが、それが見えます。 590 00:47:32,870 --> 00:47:37,620 これは、変数の値に条件を設定するようなものだ。しかし、私はそれが何であるか覚えていません。 591 00:47:37,620 --> 00:47:44,100 - 私たちは前進し続けるのであれば 592 00:47:44,100 --> 00:47:47,120 何を言ったのか?あなたは何を持ってきたの? 593 00:47:47,120 --> 00:47:50,500 [学生]が表示されていますか私が追加 - >>うん。だから私は助けることができるが表示されます。 594 00:47:50,500 --> 00:47:54,530 私達はちょうど私が表示された場合は、iの値が何であるかをここでお付けいたします 595 00:47:54,530 --> 00:47:56,470 ので、私は毎回それをプリントアウトする必要はありません。 596 00:47:56,470 --> 00:48:02,930 私たちはすぐ隣続けるなら、私たちは0、1、2、3、4、5、0、1、2、3、4、5、0、1、2、3、4、5を参照してください。 597 00:48:02,930 --> 00:48:08,530 何かがひどく間違っている、と私は0にリセットされています。 598 00:48:13,330 --> 00:48:22,220 buggy4.cを見てみると、起こることすべてがintの配列[5]を参照してください。 599 00:48:22,220 --> 00:48:26,200 (のは、i <=はsizeof(配列); i + +はi = 0のとき)のために 600 00:48:26,200 --> 00:48:28,550 配列[I] = 0; 601 00:48:28,550 --> 00:48:31,390 我々はそれがここで間違って何が見えますか? 602 00:48:31,390 --> 00:48:39,480 ヒントとして、私は、gdb buggy4をしていたとき - メインは、実行を中断してみましょう - 603 00:48:39,480 --> 00:48:45,980 私はちょうど条件が私はようやく抜け出すべき場所であるかを確認するには、printはsizeof(array)をしました。 604 00:48:47,690 --> 00:48:51,100 どこまで話しましたか?私が実行したのですか? 605 00:48:51,100 --> 00:48:54,280 私はまだ宣言していませんでした。 606 00:48:54,280 --> 00:48:58,680 だからプリントはsizeof(配列)と20代、 607 00:48:58,680 --> 00:49:06,690 、私の配列のサイズが5であり、それは5つの整数のだから期待されている 608 00:49:06,690 --> 00:49:12,410 ので、全体のことは、sizeof(int)は4になりがち5 * sizeof(int)をバイトでなければなりません。 609 00:49:12,410 --> 00:49:14,780 だから、はsizeof(配列)は20です。 610 00:49:14,780 --> 00:49:17,420 これは何をすべきか? 611 00:49:17,420 --> 00:49:21,720 [学生]はsizeof(int)を割ったものである。 >>うん、/ sizeof(int)を。 612 00:49:21,720 --> 00:49:30,630 ここでの問題は依然として存在しているように見えます。私はこれがちょうどされるべきだと思う< 613 00:49:30,630 --> 00:49:36,960 それはかなり常になので<、決して<=。 614 00:49:36,960 --> 00:49:44,860 それでは、これは実際に壊れていた理由について考えてみましょう。 615 00:49:44,860 --> 00:49:53,370 誰もがなぜ私はループの各反復を通じて0にリセットされたと推測していますか? 616 00:50:01,300 --> 00:50:09,350 ここで起こっているの内側に唯一のものは、[i]は0に設定されている配列です。 617 00:50:09,350 --> 00:50:15,350 だから何とかして、このコード行ではiが0にセットされている私たちのintを引き起こしている。 618 00:50:16,730 --> 00:50:23,130 それが私のこの部分のメモリを上書きしているため[学生]それは次のようになります。 619 00:50:23,130 --> 00:50:27,970 それは配列の次の要素だと思っているとき? >> [ボーデン]はい。 620 00:50:27,970 --> 00:50:33,880 我々は、配列の終わりを越えているとき、 621 00:50:33,880 --> 00:50:39,870 我々がオーバーライドしていることをどうにかして、そのスペースは、iの値をオーバーライドしています。 622 00:50:39,870 --> 00:50:48,030 我々はbuggy4に見ればそれで、メイン破る実行、 623 00:50:48,030 --> 00:50:53,120 iのアドレスを印刷してみましょう。 624 00:50:53,120 --> 00:50:57,280 それはbffff124ているように見えます。 625 00:50:57,280 --> 00:51:03,930 今度は配列のアドレスを出力してみましょう[0]。 110。 626 00:51:03,930 --> 00:51:06,290 何について[1]? 114。 627 00:51:06,290 --> 00:51:07,920 [2] 118。 628 00:51:07,920 --> 00:51:14,530 11cは、120。配列[5] bfff124です。 629 00:51:14,530 --> 00:51:26,990 だから配列[5]私は、その配列[5]は、iであることを意味すると同じアドレスを持っています。 630 00:51:26,990 --> 00:51:30,720 彼らは同じアドレスを持つ場合、それらは同じものです。 631 00:51:30,720 --> 00:51:38,410 だから我々は配列[5]を設定した場合は0に、我々は0にiを設定しています。 632 00:51:38,410 --> 00:51:46,070 そして、あなたは、スタックの観点からこのことについて考えるならば、 633 00:51:46,070 --> 00:51:55,590 int型iがiがスタック上にいくつかのスペースを取得つまり、最初に宣言されています。 634 00:51:55,590 --> 00:52:04,730 次に配列[5]に割り当てられているため、その後20バイトがスタックに割り当てられます。 635 00:52:04,730 --> 00:52:08,400 私が最初に割り振られますので、これらの20バイトが割り当てられ得る。 636 00:52:08,400 --> 00:52:11,400 だから私は、右側の配列の前に起こる 637 00:52:11,400 --> 00:52:19,230 と方法のため、私は、スタックは下方に広がりどこに技術的には、先週言ったように 638 00:52:19,230 --> 00:52:28,520 もし配列へのインデックス、我々は、配列の0番目の位置にあることが保証されている場合 639 00:52:28,520 --> 00:52:31,970 常に配列内の最初の位置より前に発生します。 640 00:52:31,970 --> 00:52:35,900 これは私が先週それを描いた方法の一種です。 641 00:52:35,900 --> 00:52:42,210 一番下に我々はアドレス0を持ち、上部に我々はアドレスマックスを持っていることに注意してください。 642 00:52:42,210 --> 00:52:44,880 スタックは常に下に成長しています。 643 00:52:48,100 --> 00:52:53,500 それでは、例としては、iを割り当てると言う。 644 00:52:53,500 --> 00:52:59,680 私達はちょうど私が割り振られますここで整数までとしましょう​​つまり、iを整数に割り当てます。 645 00:52:59,680 --> 00:53:06,420 その後、我々はその下のことを意味し5つの整数の我々の配列を割り当て、 646 00:53:06,420 --> 00:53:11,230 スタックがダウンして成長しているので、それら5つの整数が割り当てられ得る。 647 00:53:11,230 --> 00:53:15,900 しかし、配列がどのように働くかのために、私たちは保証されている、その配列内の最初の位置 648 00:53:15,900 --> 00:53:22,260 常に配列の2番目のものよりも小さいアドレスを持っています。 649 00:53:22,260 --> 00:53:28,270 だから、配列の位置0は、常にメモリに最初に起こる必要があり、 650 00:53:28,270 --> 00:53:30,700 配列の位置1は、後に起こる必要があるのに対し、 651 00:53:30,700 --> 00:53:33,310 と配列位置2は、その後起こることがあります 652 00:53:33,310 --> 00:53:37,900 これは配列の位置0はここのどこかダウンが起こるかということ、 653 00:53:37,900 --> 00:53:40,690 配列の位置1はその上に起こるだろう 654 00:53:40,690 --> 00:53:45,530 最大アドレスはここにアップしているので、上に移動すると、上位アドレスを意味するので。 655 00:53:45,530 --> 00:53:50,490 ダウンここ配列[0]だから、array [1]はここまで、配列[2]ここまで、配列[3]ここまで。 656 00:53:50,490 --> 00:53:55,620 私たちはここで私はすべての方法を、整数を割り当て方法前に気付く 657 00:53:55,620 --> 00:54:01,040 我々は配列にさらに、さらに移動すると、私達は私達の整数iに近づくと近づいている。 658 00:54:01,040 --> 00:54:07,640 それはちょうど、その配列は、我々の配列のほかに、一つの位置である、[5]のように起こる 659 00:54:07,640 --> 00:54:13,010 iが割り当てられることが起こった場所を正確に整数です。 660 00:54:13,010 --> 00:54:16,920 だから我々は、スタック上にスペースを打つことが起こる点だ 661 00:54:16,920 --> 00:54:21,680 それは整数iのために割り当てられた、と我々は0に設定している。 662 00:54:21,680 --> 00:54:26,160 >> それはそれはどのように動作します。質問はありますか?うん。 663 00:54:26,160 --> 00:54:30,710 気にしないで[学生]。オーケー。 664 00:54:30,710 --> 00:54:33,090 [学生]はどのようにこれらのエラーのソートを回避するには? 665 00:54:33,090 --> 00:54:41,190 これらのエラーの一種?プログラミング言語としてC言語を使用しないでください。 666 00:54:41,190 --> 00:54:45,840 配列境界チェックを持っている言語を使用しています。 667 00:54:45,840 --> 00:54:55,900 限り、あなたは気をつけているとして、あなたは自分の配列の境界を越えて行くことは避けねばならない。 668 00:54:55,900 --> 00:54:58,300 そこでここでは[学生]我々はあなたの配列の境界を越えて行きました - 669 00:54:58,300 --> 00:55:01,840 [ボーデン]物事がうまく行き始めるところですね。 >> [生徒]ああ、大丈夫。 670 00:55:01,840 --> 00:55:05,730 あなたが配列に割り当てられたメモリ内にとどまる限り、あなたは大丈夫です。 671 00:55:05,730 --> 00:55:12,400 しかし、Cは、エラーチェックを行いません。私は配列[1000]をすれば、それは喜んでちょうど起ころう変更されます - 672 00:55:12,400 --> 00:55:16,500 それは配列の先頭に行く、それは後に1000年のポジションを行き、それを0に設定します。 673 00:55:16,500 --> 00:55:20,000 それは、ああ、これは実際にそれで1000年のものを持っていない任意のチェックは行いません。 674 00:55:20,000 --> 00:55:22,750 1000は、方法私は変化すべきかを超えています 675 00:55:22,750 --> 00:55:26,940 一方、Javaやあなたが境界のインデックスの配列を取得しますか 676 00:55:26,940 --> 00:55:29,820 または境界外のインデックスの例外。 677 00:55:29,820 --> 00:55:33,950 高水準言語の多くは、これらのものを持っている理由です 678 00:55:33,950 --> 00:55:37,340 あなたが配列の境界を越えて行けば、どこに、あなたは失敗する 679 00:55:37,340 --> 00:55:40,070 あなたは下から物事を変更できないように 680 00:55:40,070 --> 00:55:42,590 その後の事はただの例外を取得するよりもはるかに悪い行く 681 00:55:42,590 --> 00:55:44,940 あなたが配列の終わりを越えて行ったことが書かれています。 682 00:55:44,940 --> 00:55:50,970 [学生]そして、私たちはちょうど変更されているはずです<=にだけ<? >> [ボーデン]うん。 683 00:55:50,970 --> 00:55:54,800 それは、<はsizeof(配列)/ sizeof(int)をでなければなりません。 684 00:55:54,800 --> 00:55:59,560 はsizeof(配列)は20ですが、我々は唯一の5をしたいので。 >> [生徒]右。 685 00:55:59,560 --> 00:56:04,060 多くの質問?オーケー。 686 00:56:04,060 --> 00:56:07,380 >> [学生]私は質問があります。 >>うん。 687 00:56:07,380 --> 00:56:16,440 [学生]実際の配列変数とは何ですか? 688 00:56:16,440 --> 00:56:20,000 [ボーデン]のような配列は何ですか? 689 00:56:20,000 --> 00:56:24,930 配列自体はシンボルである。 690 00:56:24,930 --> 00:56:31,490 それはちょうど私たちが参照している20バイトの先頭のアドレスです。 691 00:56:31,490 --> 00:56:38,070 あなたはポインタとして考えることができますが、それは一定のポインタです。 692 00:56:38,070 --> 00:56:44,140 物事がコンパイルされるとすぐに、配列変数はもう存在しません。 693 00:56:44,140 --> 00:56:48,210 [学生]だからそれはどのように配列のサイズを見つけるのですか? 694 00:56:48,210 --> 00:56:54,130 配列のサイズは、そのシンボルが参照して、そのブロックのサイズを指します。 695 00:56:54,130 --> 00:57:01,240 私はprintfのような何かを( "%P \ n"の配列)を行うと、 696 00:57:01,240 --> 00:57:05,140 それを実行してみましょう。 697 00:57:12,960 --> 00:57:15,530 私は間違った何をしたのか? 698 00:57:15,530 --> 00:57:19,220 配列 '配列'はここに宣言した。 699 00:57:20,820 --> 00:57:23,200 ああ、ここまで。 700 00:57:23,200 --> 00:57:31,250 Clangのは賢いです、そして、それは、私は5つの要素として配列を宣言されたことに気づくことを起こる 701 00:57:31,250 --> 00:57:34,540 しかし、私は位置1000にインデックス化しています。 702 00:57:34,540 --> 00:57:38,450 それは、これらは単なる定数であるため、それを行うことができます。 703 00:57:38,450 --> 00:57:43,370 それだけで私は配列の範囲を超えていることに気付いつもりでこれまで行くことができます。 704 00:57:43,370 --> 00:57:46,880 しかし、私たちは、私が間違っている持っていたときに前に気付く 705 00:57:46,880 --> 00:57:51,040 それはおそらく、私がかかることがありますどのように多くの値を決定することはできません 706 00:57:51,040 --> 00:57:55,540 ので、私は、配列の末尾を超えていたことを判断することはできません。 707 00:57:55,540 --> 00:57:59,430 それはちょうど巧妙であるClangのだ。 708 00:57:59,430 --> 00:58:03,340 >> しかし、今buggy4を作る。だから、私は間違って他に何をやっている? 709 00:58:03,340 --> 00:58:05,970 暗黙のうちにライブラリ関数 'printfの'を宣言。 710 00:58:05,970 --> 00:58:14,960 私は#を入れようと思っています。 711 00:58:14,960 --> 00:58:18,710 オーケー。今すぐbuggy4を実行している。 712 00:58:18,710 --> 00:58:24,840 私はポインタとしてそれを印刷し、ここで行ったように配列の値を出力する 713 00:58:24,840 --> 00:58:30,060 このようなものを出力します - bfb8805c - いくつかのアドレスです。 714 00:58:30,060 --> 00:58:33,450 それはスタックっぽい地域であります。 715 00:58:33,450 --> 00:58:41,820 、配列自体はポインタのようですが、それは実際のポインタではありません 716 00:58:41,820 --> 00:58:45,410 通常のポインタ以来、我々は、変更することができます。 717 00:58:45,410 --> 00:58:54,700 アレイは、単にいくつかの定数である。メモリの20ブロックは、アドレス0xbfb8805cから始まります。 718 00:58:54,700 --> 00:59:09,020 このアドレスを使用してそうbfb8805c +20- - または私は-20を推測 - 719 00:59:09,020 --> 00:59:17,400 このアレイに割り当てられているメモリのすべてです。 720 00:59:17,400 --> 00:59:20,350 配列は、変数自体はどこにも格納されません。 721 00:59:20,350 --> 00:59:27,660 あなたは、コンパイラをコンパイルしているとき - それで手の波 - 722 00:59:27,660 --> 00:59:33,060 それがために配列を知っている場所が、コンパイラは単に使用されます。 723 00:59:33,060 --> 00:59:36,090 その配列が始まるところか知っており、 724 00:59:36,090 --> 00:59:40,910 ので、それは常にちょうどその先頭からのオフセットの観点で物事を行うことができます。 725 00:59:40,910 --> 00:59:43,960 これは配列を表す変数自体を必要としません。 726 00:59:43,960 --> 00:59:53,730 しかし、私は、int * pを=配列のような何かをするとき、今pは、その配列を指すポインタである 727 00:59:53,730 --> 00:59:57,830 そして今、pは、実際にスタック上に存在しません。 728 00:59:57,830 --> 01:00:01,950 私はpを変更することが自由だ。私は、p = mallocを行うことができます。 729 01:00:01,950 --> 01:00:06,500 だから、もともと配列が指すが、現在それは、ヒープ上にいくつかのスペースを指しています。 730 01:00:06,500 --> 01:00:09,620 私は配列= mallocを行うことはできません。 731 01:00:09,620 --> 01:00:13,710 Clangのが利口だ場合、それは右のバットから私に向かって怒鳴ります。 732 01:00:17,000 --> 01:00:21,430 実は、私はgccがあまりにもこれを行うだろうと確信しています。 733 01:00:21,430 --> 01:00:25,010 だから、配列型のint [5] 'は代入できません。 734 01:00:25,010 --> 01:00:28,040 あなたは、配列型に何かを割り当てることはできません 735 01:00:28,040 --> 01:00:30,500 配列は、定数だけであるためです。 736 01:00:30,500 --> 01:00:34,760 それは、それらを参照する20バイトのシンボルです。私はそれを変更することはできません。 737 01:00:34,760 --> 01:00:37,690 >> [学生]配列の大きさがどこに保存されますか? 738 01:00:37,690 --> 01:00:40,670 [ボーデン]それはどこにも保存されていない。それはコンパイル時だそれは。 739 01:00:40,670 --> 01:00:46,310 だから、配列のサイズはどこに保存されますか? 740 01:00:46,310 --> 01:00:51,870 あなただけの配列自体が宣言された関数の内部ではsizeof(array)を使用することができます。 741 01:00:51,870 --> 01:01:03,150 だから私は、いくつかの関数fooをやると私が行う場合(int型の配列[]) 742 01:01:03,150 --> 01:01:10,450 のprintf( "%d個\ n"ではsizeof(配列)); 743 01:01:10,450 --> 01:01:21,330 その後ダウンして、ここで私は、foo(array)を呼び出します。 744 01:01:21,330 --> 01:01:24,840 この関数の内部 - のは、それを実行してみましょう。 745 01:01:34,200 --> 01:01:36,840 これは再び巧妙であるClangのです。 746 01:01:36,840 --> 01:01:43,890 それは私に言って、その配列関数のパラメータにはsizeof 747 01:01:43,890 --> 01:01:46,690 'int型*'のサイズを返します。 748 01:01:46,690 --> 01:01:55,150 それは何が起こることを望んでいないなら、これはエラーになります。 749 01:01:55,150 --> 01:01:58,960 実際にWerrorをオフにしてみましょう。 750 01:02:14,950 --> 01:02:17,590 警告。警告は罰金です。 751 01:02:17,590 --> 01:02:19,960 それはまだ限り、それは警告があるとしてコンパイルされます。 752 01:02:19,960 --> 01:02:22,910 。/ a.outは4をプリントしようとしている。 753 01:02:22,910 --> 01:02:28,650 生成された警告は何が悪かったのかの明確な指標である。 754 01:02:28,650 --> 01:02:34,120 このint配列はただのsizeof(int *)を印刷しようとしている。 755 01:02:34,120 --> 01:02:39,790 私はここで、配列[5]を入れた場合でも、それはまだただのsizeof(int *)を印字することになっている。 756 01:02:39,790 --> 01:02:47,440 だから、できるだけ早くあなたには、この関数に渡すと配列とポインタの区別 757 01:02:47,440 --> 01:02:49,670 存在しません。 758 01:02:49,670 --> 01:02:52,640 これは、スタック上に宣言された配列であることを起こる 759 01:02:52,640 --> 01:02:58,300 しかし、すぐに我々は、その値を渡していることのみを返す何とか、何とか、この関数に何とか、 760 01:02:58,300 --> 01:03:03,350 このポインタは、スタック上にその配列を指しています。 761 01:03:03,350 --> 01:03:08,310 sizeof演算子は、配列が宣言された関数に適用することを意味しますので、 762 01:03:08,310 --> 01:03:11,230 これは、この関数をコンパイルしているときにあることを意味 763 01:03:11,230 --> 01:03:17,330 Clangのは、この関数を通過するとき、それは配列のサイズが5のint型の配列であることを認識します。 764 01:03:17,330 --> 01:03:20,640 だからそれは、sizeof(array)を見ている。まあ、それは20だ。 765 01:03:20,640 --> 01:03:26,440 それはsizeofは基本的にほぼすべてのケースのためにどのように動作するかを実際にです。 766 01:03:26,440 --> 01:03:31,150 sizeofは関数ではありません、それはオペレータだ。 767 01:03:31,150 --> 01:03:33,570 あなたは、sizeof関数を呼び出すことはありません。 768 01:03:33,570 --> 01:03:38,280 はsizeof(int)は、コンパイラはちょうどその4に変換されます。 769 01:03:41,480 --> 01:03:43,700 分かった?オーケー。 770 01:03:43,700 --> 01:03:47,520 >> [学生]だからメインでとfooのsizeof(配列)の違いは何ですか? 771 01:03:47,520 --> 01:03:52,840 我々はint *型であるとsizeof(配列)、と言っているためです 772 01:03:52,840 --> 01:03:57,120 ダウンここ配列がint *型ではないのに対し、これはint型の配列です。 773 01:03:57,120 --> 01:04:04,540 >> [学生]だからあなたは配列[]の代わりにint *の配列にパラメータを持っている場合は、 774 01:04:04,540 --> 01:04:09,230 それが今ではそれがポインタだからあなたはまだ配列を変えることができることを意味するでしょう? 775 01:04:09,230 --> 01:04:14,250 [ボーデン]これ、気に入りましたか? >> [生徒]うん。あなたは今、関数内の配列を変更することはできますか? 776 01:04:14,250 --> 01:04:18,420 [ボーデン]あなたはどちらの場合も、配列を変更することができます。 777 01:04:18,420 --> 01:04:23,130 これらの例の両方では、[4] = 0アレイを言うことは自由です。 778 01:04:23,130 --> 01:04:26,590 [学生]しかし、あなたが何か他のものに配列ポイントを作ることができますか? 779 01:04:26,590 --> 01:04:30,230 [ボーデン]ああ。うん。どちらの場合では - >> [生徒]うん。 780 01:04:30,230 --> 01:04:38,410 [ボーデン]配列[]とint *の配列の間の区別は、何もない。 781 01:04:38,410 --> 01:04:42,570 また、ここでいくつかの多次元の配列を得ることができます 782 01:04:42,570 --> 01:04:47,050 いくつかの便利な構文については、それはまだ単なるポインタだ。 783 01:04:47,050 --> 01:04:56,400 これは、私は配列=に、malloc(sizeof(int))を自由に行うことだということを意味し、そして今ではどこか別の場所を指す。 784 01:04:56,400 --> 01:04:59,610 しかし、これは永遠に、常にどのように動作するかだけが好き、 785 01:04:59,610 --> 01:05:03,210 それを作ることで、この配列を変更すると何か他のものを指す 786 01:05:03,210 --> 01:05:07,570 それは、引数のコピーであるため、ここでは、この配列を下に変更されることはありません 787 01:05:07,570 --> 01:05:10,780 その引数へのポインタではありません。 788 01:05:10,780 --> 01:05:16,070 そして、実際に、それは全く同じだということ以上を指標として - 789 01:05:16,070 --> 01:05:21,100 我々はすでに何を印字配列印刷物を見た - 790 01:05:21,100 --> 01:05:31,410 私たちは、配列のアドレスや配列のアドレスのアドレスを印刷する場合 791 01:05:31,410 --> 01:05:36,290 それらのいずれかに? 792 01:05:41,770 --> 01:05:45,220 この1を無視してみましょう。 793 01:05:48,140 --> 01:05:51,660 オーケー。これは問題ありません。それが今では。/ a.outを実行している。 794 01:05:51,660 --> 01:06:00,220 印字配列は、その配列のアドレスを印刷して、同じものです。 795 01:06:00,220 --> 01:06:02,870 アレイは、単に存在しません。 796 01:06:02,870 --> 01:06:08,190 それはあなたの配列を表示しているとき、あなたはそれらの20バイトを指す記号を印刷している知っている。 797 01:06:08,190 --> 01:06:11,940 配列のアドレスを印刷して、まあ、配列は存在しません。 798 01:06:11,940 --> 01:06:17,200 これは、アドレスを持っていないので、それはちょうどそれらの20バイトのアドレスを出力します。 799 01:06:20,820 --> 01:06:28,150 できるだけ早くあなたがダウンしてコンパイルすると、コンパイルされたbuggy4のように。/ a.outを 800 01:06:28,150 --> 01:06:30,340 配列は存在しません。 801 01:06:30,340 --> 01:06:33,640 ポインタが存​​在しています。配列はありません。 802 01:06:34,300 --> 01:06:38,060 配列を表すメモリのブロックは、まだ存在している 803 01:06:38,060 --> 01:06:43,270 しかし、その型の変数配列と変数は存在しません。 804 01:06:46,260 --> 01:06:50,270 それらは、配列とポインタの間の主な違いのようなもの 805 01:06:50,270 --> 01:06:55,590 できるだけ早くあなたが関数呼び出しを行うようですが、違いはありません。 806 01:06:55,590 --> 01:07:00,460 しかし、配列自体が宣言された関数の内部で、sizeofが異なる動作を 807 01:07:00,460 --> 01:07:05,190 あなたが代わりに型のサイズのブロックのサイズを印刷しているので、 808 01:07:05,190 --> 01:07:08,950 それはシンボルだから、あなたはそれを変更することはできません。 809 01:07:08,950 --> 01:07:14,370 事の印刷と実物のアドレスは同じものを出力します。 810 01:07:14,370 --> 01:07:18,480 そして、それはそれはかなりです。 811 01:07:18,480 --> 01:07:20,820 [学生]は、その1つのより多くの時間を言ってもらえますか? 812 01:07:21,170 --> 01:07:24,170 私は何かを見逃していたかもしれない。 813 01:07:24,170 --> 01:07:29,260 配列の印字配列とアドレスは同じものを出力し、 814 01:07:29,260 --> 01:07:33,180 一方、あなたはポインタのアドレスに対するポインタを印刷する場合、 815 01:07:33,180 --> 01:07:36,010 一つのことはあなたが指しているもののアドレスを出力し、 816 01:07:36,010 --> 01:07:40,360 もう一つは、スタック上のポインタのアドレスを出力します。 817 01:07:40,360 --> 01:07:47,040 あなたは、ポインタを変更することができ、あなたは配列のシンボルを変更することはできません。 818 01:07:47,740 --> 01:07:53,270 とsizeofポインタはポインタ型のサイズで印刷しようとしている。 819 01:07:53,270 --> 01:07:57,470 だからます。int * pはsizeof(p)は、4をプリントしようとしている 820 01:07:57,470 --> 01:08:04,110 しかし、int型の配列[5]プリントはsizeof(配列)は20をプリントしようとしている。 821 01:08:04,110 --> 01:08:07,480 [学生]だからint型の配列[5]は20を出力します? >>はい。 822 01:08:07,480 --> 01:08:13,300 なぜ内部buggy4のそれはsizeof(配列)になるように使用されるときだ 823 01:08:13,300 --> 01:08:16,660 これは、i <20をやっていた、それは私たちが望んだものではありません。 824 01:08:16,660 --> 01:08:20,880 我々は、i <5が欲しい。 >> [生徒]オーケー。 825 01:08:20,880 --> 01:08:25,569 [ボーデン]そして、できるだけ早くあなたが関数に渡して起動するように、 826 01:08:25,569 --> 01:08:34,340 私たちがやってint * pを=配列; 827 01:08:34,340 --> 01:08:39,779 この関数の内部で、我々は基本的には、まったく同じ方法でpと配列を使うことができます。 828 01:08:39,779 --> 01:08:43,710 sizeofの問題と変化問題を除いて。 829 01:08:43,710 --> 01:08:49,810 しかし、pはa [0] = 1;配列[0] = 1を言うと同じです。 830 01:08:49,810 --> 01:08:55,600 とすぐに我々は、foo(array)が言うように、または、関数foo(p)を; 831 01:08:55,600 --> 01:08:59,760 foo関数の内部では、これは二度同じ呼び出しです。 832 01:08:59,760 --> 01:09:03,350 以下の二つの呼び出しの間に違いはありません。 833 01:09:07,029 --> 01:09:11,080 >> その上で良い誰?オーケー。 834 01:09:14,620 --> 01:09:17,950 我々は10分を持っています。 835 01:09:17,950 --> 01:09:28,319 >> 我々は、このハッカータイパープログラムを介して取得しようとするでしょう 836 01:09:28,319 --> 01:09:32,350 去年か何か出てきたこのサイト。 837 01:09:34,149 --> 01:09:41,100 それはちょうどあなたがランダムに入力し、それをプリントアウトのようなことになっている - 838 01:09:41,100 --> 01:09:46,729 それが読み込まれていることを起こるどんなファイルあなたが入力しているように見えるものです。 839 01:09:46,729 --> 01:09:52,069 これは、オペレーティング·システムのコードのいくつかの種類のように見えます。 840 01:09:53,760 --> 01:09:56,890 それは我々が実装したいものだ。 841 01:10:08,560 --> 01:10:11,690 あなたはhacker_typerという名前のバイナリ実行ファイルがあるはずです 842 01:10:11,690 --> 01:10:14,350 それは、ファイル、単一の引数を取り、 "ハッカータイプ。" 843 01:10:14,350 --> 01:10:16,480 実行可​​能ファイルを実行すると、画面をクリアする必要があります 844 01:10:16,480 --> 01:10:20,850 その後、ユーザーがキーを押すたびに、渡されたファイルから1文字を出力します。 845 01:10:20,850 --> 01:10:24,990 ですから、どんなキーを押し、それは捨てて、代わりにファイルから文字を印刷する必要があります 846 01:10:24,990 --> 01:10:27,810 それは引数です。 847 01:10:29,880 --> 01:10:34,350 私はかなり私たちが知っておく必要があるとしているものが何であるかを教えてあげる。 848 01:10:34,350 --> 01:10:36,440 しかし、我々はtermiosライブラリをチェックアウトしたい。 849 01:10:36,440 --> 01:10:44,840 私は私の生涯でこのライブラリを使用したことがないので、それは非常に最小限の目的を持っています。 850 01:10:44,840 --> 01:10:48,610 しかし、これは、我々はあなたが打つ文字を捨てるために使用できるライブラリであることを行っている 851 01:10:48,610 --> 01:10:52,390 あなたはインチ規格に入力しているとき 852 01:10:56,970 --> 01:11:05,840 だからhacker_typer.c、我々は#を含むようにするつもりだ。 853 01:11:05,840 --> 01:11:12,870 は、termiosのmanページを見て - それの端末のOSや何かを推測 - 私 -​​ 854 01:11:12,870 --> 01:11:16,240 私はそれを読む方法を知りません。 855 01:11:16,240 --> 01:11:21,040 これを見ると、それは、これらの2つのファイルを含めるように言うので、私たちはそうするだろう。 856 01:11:37,620 --> 01:11:46,820 >> 最初のものは、最初に、私達は私達が開くべきファイルである単一の引数に取りたい。 857 01:11:46,820 --> 01:11:52,420 だから私は何をすべきかをしたいですか?どのように私は、私は単一の引数を持っているかを確認するのですか? 858 01:11:52,420 --> 01:11:56,480 [学生] argcはそれに等しい場合。 >> [ボーデン]うん。 859 01:11:56,480 --> 01:12:21,250 もしそうなら(argcは= 2!)のprintf( "使い方:%s [ファイル開くには]")。 860 01:12:21,250 --> 01:12:32,750 だから今、私は2番目の引数を提供せずに、これを実行する場合 - ああ、私は、新しい行を必要とする - 861 01:12:32,750 --> 01:12:36,240 あなたはそれが言う用法がわかります。/ hacker_typer、 862 01:12:36,240 --> 01:12:39,770 し、2番目の引数は、私は開きたいファイルである必要があります。 863 01:12:58,430 --> 01:13:01,260 今私は何をすればいいですか? 864 01:13:01,260 --> 01:13:08,490 私は、このファイルから読みたい。どうすれば、ファイルから読み込むのですか? 865 01:13:08,490 --> 01:13:11,920 [学生]あなたが最初に開いた。 >>うん。 866 01:13:11,920 --> 01:13:15,010 だから、fopenの。 fopenはどのように見えますか? 867 01:13:15,010 --> 01:13:22,980 [学生]ファイル名。 >> [ボーデン]ファイル名はargv [1]になるだろう。 868 01:13:22,980 --> 01:13:26,110 [学生]そして何がそれで何をしたいので、 - >> [ボーデン]うん。 869 01:13:26,110 --> 01:13:28,740 あなたは覚えていなかった場合、だから、あなたは、男のfopenを行うだけでした 870 01:13:28,740 --> 01:13:32,960 それはパスがファイル名であるconst char *のパスになるだろうここで、 871 01:13:32,960 --> 01:13:34,970 const char *のモード。 872 01:13:34,970 --> 01:13:38,660 あなたはモードとは何か覚えていないために起こる場合は、モードを探すことができます。 873 01:13:38,660 --> 01:13:44,660 manページの内部では、スラッシュ文字は、物事を検索するために使用できるものです。 874 01:13:44,660 --> 01:13:49,790 だから私は、モードを検索する/モードを入力します。 875 01:13:49,790 --> 01:13:57,130 nとNを使用すると、検索がマッチを循環するために使用できるものです。 876 01:13:57,130 --> 01:13:59,800 ここでは文字列に引数modeポイントを語る 877 01:13:59,800 --> 01:14:01,930 次のいずれかのシーケンスで始まる。 878 01:14:01,930 --> 01:14:06,480 だからrを、読み込み用にオープンしたテキストフ​​ァイル。それは我々が何をしたいです。 879 01:14:08,930 --> 01:14:13,210 読書のための、と私はそれを保存したい。 880 01:14:13,210 --> 01:14:18,720 事は、FILE *になるだろう。今私はどのように過ごしたいですか? 881 01:14:18,720 --> 01:14:21,200 私に第二を与える。 882 01:14:28,140 --> 01:14:30,430 オーケー。今私はどのように過ごしたいですか? 883 01:14:30,430 --> 01:14:32,940 [学生]がNULLの場合にチェックします。 >> [ボーデン]うん。 884 01:14:32,940 --> 01:14:38,690 ファイルを開くときはいつでも、あなたはそれを正常に開くことができるしていることを確認してください。 885 01:14:58,930 --> 01:15:10,460 >> 今私は私が最初に私の現在の設定を読みたいtermiosのものをやってみたい 886 01:15:10,460 --> 01:15:14,050 と何かにそれらを保存し、私は私の設定を変更したい 887 01:15:14,050 --> 01:15:19,420 私が入力した任意の文字を捨てることができ、 888 01:15:19,420 --> 01:15:22,520 そして私はそれらの設定を更新する必要があります。 889 01:15:22,520 --> 01:15:27,250 そして、プログラムの最後に、私は元の設定に戻って変更したいと思います。 890 01:15:27,250 --> 01:15:32,080 だからstructはtermios型になるだろう、と私はそれらのうちの2つをしたいつもりです。 891 01:15:32,080 --> 01:15:35,600 一つ目は、私のcurrent_settingsになるだろう 892 01:15:35,600 --> 01:15:42,010 その後、彼らは私のhacker_settingsことになるだろう。 893 01:15:42,010 --> 01:15:48,070 まず、私は、私の現在の設定を保存するつもりです 894 01:15:48,070 --> 01:15:53,790 それから私は、hacker_settingsを更新するつもりです 895 01:15:53,790 --> 01:16:01,570 そしてその後、私のプログラムの終了時にせよ、私は現在の設定に戻したい。 896 01:16:01,570 --> 01:16:08,660 だから、私たち人間のtermiosを動作する方法は、現在の設定を保存する。 897 01:16:08,660 --> 01:16:15,810 我々はこのintのtcsetattr、int型tcgetattrを持っていることを参照してください。 898 01:16:15,810 --> 01:16:22,960 私は、そのポインタによっては、termios構造体に渡します。 899 01:16:22,960 --> 01:16:30,640 これは見ていきます方法です - I'veは既に関数が呼び出されたか忘れてしまった。 900 01:16:30,640 --> 01:16:34,930 コピーと貼り付けます。 901 01:16:39,150 --> 01:16:45,500 tcgetattrので、それから私は、私は情報を保存していることを構造体に渡したい 902 01:16:45,500 --> 01:16:49,650 current_settingsになるだろうされている、 903 01:16:49,650 --> 01:16:59,120 最初の引数は、私がの属性を保存したいもののためにファイル記述子です。 904 01:16:59,120 --> 01:17:04,360 どのようなファイル記述子があると、ファイルを開く、任意の時間のようですが、それはファイル記述子を取得します。 905 01:17:04,360 --> 01:17:14,560 ときに私のfopen argv [1]が、それはあなたが参照しているファイル記述子を取得します 906 01:17:14,560 --> 01:17:16,730 あなたがそれに読み取りまたは書き込みをしたいとき。 907 01:17:16,730 --> 01:17:19,220 それは私がここで使用するファイル記述子ではありません。 908 01:17:19,220 --> 01:17:21,940 あなたがデフォルトで持っている3つのファイル記述子がありますが、 909 01:17:21,940 --> 01:17:24,310 これは、標準で標準出力、標準エラーです。 910 01:17:24,310 --> 01:17:29,960 デフォルトでは、私はそれが0で標準だと思うが、標準出力は1であり、標準誤差は2です。 911 01:17:29,960 --> 01:17:33,980 だから私は、設定を変更したいのですか? 912 01:17:33,980 --> 01:17:37,370 私は、文字を打つたびに設定を変更したい 913 01:17:37,370 --> 01:17:41,590 私はそれが、それを画面に出力する代わりに離れて、その文字をスローするようにしたい。 914 01:17:41,590 --> 01:17:45,960 何ストリーム - - 標準出力、または標準エラーで標準 915 01:17:45,960 --> 01:17:52,050 私はキーボードで入力するときに物事に反応? >> >>うんインチ[学生]スタンダード。 916 01:17:52,050 --> 01:17:56,450 だから私は、0を行うことができますか私は、stdinを行うことができます。 917 01:17:56,450 --> 01:17:59,380 私はインチ規格のcurrent_settingsを取得しています 918 01:17:59,380 --> 01:18:01,720 >> 今私は、これらの設定を更新する 919 01:18:01,720 --> 01:18:07,200 ので、最初私はcurrent_settingsが何であるかhacker_settingsにコピーします。 920 01:18:07,200 --> 01:18:10,430 と構造体の仕事がどのようにそれだけがコピーされます。 921 01:18:10,430 --> 01:18:14,510 ご想像のとおり、これは、すべてのフィールドをコピーします。 922 01:18:14,510 --> 01:18:17,410 >> 今、私はいくつかのフィールドを更新したい。 923 01:18:17,410 --> 01:18:21,670 termiosのを見ると、この多くを通読しなければならないでしょう 924 01:18:21,670 --> 01:18:24,110 ちょうどあなたが見たいものを見るために、 925 01:18:24,110 --> 01:18:28,210 しかし、あなたが見てみたいとしているフラグは、エコーです 926 01:18:28,210 --> 01:18:33,110 そうエコー入力文字はエコー。 927 01:18:33,110 --> 01:18:37,710 最初に私が設定したい - フィールドが何であるかもう忘れI've。 928 01:18:45,040 --> 01:18:47,900 これは、構造体がどのように見えるかです。 929 01:18:47,900 --> 01:18:51,060 入力モードだから私たちは変更したいと思います。 930 01:18:51,060 --> 01:18:54,210 我々はそれを私たちが変えたいと思っているのだと確信するために解決策を見てみましょう。 931 01:19:04,060 --> 01:19:12,610 我々は、すべてのこれらに目を通す必要がないようにするためにlflagを変更したい。 932 01:19:12,610 --> 01:19:14,670 我々は地元のモードを変更したい。 933 01:19:14,670 --> 01:19:17,710 あなたはすべてのものが属するのかを理解するために、この全体の事を通読しなければならないでしょう 934 01:19:17,710 --> 01:19:19,320 我々は、変更したい。 935 01:19:19,320 --> 01:19:24,120 しかし、それは我々がそれを変更したいとしているローカルのモードの内部です。 936 01:19:27,080 --> 01:19:33,110 だからhacker_settings.cc_lmodeは、それが呼ばれるものです。 937 01:19:39,630 --> 01:19:43,020 c_lflag。 938 01:19:49,060 --> 01:19:52,280 我々はビット演算子に入るところです。 939 01:19:52,280 --> 01:19:54,860 我々は時間のうちの​​一種だが、我々はそれで実際に素早く通過するでしょう。 940 01:19:54,860 --> 01:19:56,600 我々はビット演算子に入るところであり、 941 01:19:56,600 --> 01:19:59,950 私はあなたが起動するたびにフラグを扱うことをずっと前に一度だけ言ったと思う場合には、 942 01:19:59,950 --> 01:20:03,370 あなたは、ビット演算子をたくさん使うことになるだろう。 943 01:20:03,370 --> 01:20:08,240 フラグの各ビットは、行動のいくつかの並べ替えに対応しています。 944 01:20:08,240 --> 01:20:14,090 そこでここでは、このフラグは、それらのすべてが別の何かを意味し、さまざまなものの束を持っています。 945 01:20:14,090 --> 01:20:18,690 しかし、私がやりたいことだけエコーに対応するビットをオフにされています。 946 01:20:18,690 --> 01:20:25,440 だからオフに私が&=¬ECHOを行うことをオフにします。 947 01:20:25,440 --> 01:20:30,110 実際に、私はそれは手帳か何かのようだと思う。私は再度確認するつもりです。 948 01:20:30,110 --> 01:20:34,050 私はそれをtermiosにすることができます。それはちょうど、ECHOです。 949 01:20:34,050 --> 01:20:38,440 ECHOは、単一のビットになるだろう。 950 01:20:38,440 --> 01:20:44,230 ¬ECHOは全てのフラグがtrueに設定されていることを意味し、すべてのビットが1にセットされていることを意味しようとしている 951 01:20:44,230 --> 01:20:47,140 エコービットを除く。 952 01:20:47,140 --> 01:20:53,830 これで私の地元のフラグを終了することによって、それが現在trueに設定されているすべてのフラグを意味します 953 01:20:53,830 --> 01:20:56,520 まだtrueに設定されます。 954 01:20:56,520 --> 01:21:03,240 私のエコーフラグがtrueに設定されている場合、これは必ずしもechoフラグをfalseに設定されています。 955 01:21:03,240 --> 01:21:07,170 だから、このコード行は、単にechoフラグをオフにします。 956 01:21:07,170 --> 01:21:16,270 コー​​ドの他の行は、私はちょうど時間の関係でそれらをコピーして、それらを説明するでしょう。 957 01:21:27,810 --> 01:21:30,180 溶液中では、彼は0を言った。 958 01:21:30,180 --> 01:21:33,880 これは、明示的にstdinを言って良いでしょう。 959 01:21:33,880 --> 01:21:42,100 >> ここICANON |私は、エコーをやっていることに注意してください。 960 01:21:42,100 --> 01:21:46,650 ICANONはカノニカルモードを意味する別の何かを指しています。 961 01:21:46,650 --> 01:21:50,280 あなたがコマンドラインを入力しているときに何カノニカルモードが意味するものは、通常は 962 01:21:50,280 --> 01:21:54,670 あなたは改行を打つまでで標準では何も処理しません。 963 01:21:54,670 --> 01:21:58,230 だからあなたがgetStringないとき、あなたは改行をヒットしてから、物事の束を入力します。 964 01:21:58,230 --> 01:22:00,590 それはインチ標準に送信されたときだ 965 01:22:00,590 --> 01:22:02,680 これはデフォルトです。 966 01:22:02,680 --> 01:22:05,830 私はあなたを押し、すべての文字今、カノニカルモードをオフにすると 967 01:22:05,830 --> 01:22:10,910 、それはこれらの事を処理するのが遅いですので、通常は悪いの一種である、処理されるものです 968 01:22:10,910 --> 01:22:14,330 それは全体のラインにそれをバッファリングするために良いことだ理由である。 969 01:22:14,330 --> 01:22:16,810 しかし、私は、各文字が処理されるようにしたい 970 01:22:16,810 --> 01:22:18,810 私は私が改行にヒットするのは待ちたくないので、 971 01:22:18,810 --> 01:22:21,280 それはすべての文字を処理する前に、私が入力してきた。 972 01:22:21,280 --> 01:22:24,760 これはカノニカルモードをオフにします。 973 01:22:24,760 --> 01:22:31,320 それは実際に文字を処理するときにこのようなものはただ意味します。 974 01:22:31,320 --> 01:22:35,830 できるだけ早く私はそれらを入力していますので、それらを処理しますが、これはすぐに処理することを意味する。 975 01:22:35,830 --> 01:22:42,510 そして、これは、内標準に自分の設定を更新している関数です。 976 01:22:42,510 --> 01:22:45,480 とTCSA手段は今それを行う。 977 01:22:45,480 --> 01:22:50,310 ストリーム上に現在あるすべてのものが処理されるまで、他のオプションは待機しています。 978 01:22:50,310 --> 01:22:52,030 それは本当に問題ではありません。 979 01:22:52,030 --> 01:22:56,920 ちょうど今hacker_typer_settingsに現在あるものは何でもであることが私の設定を変更します。 980 01:22:56,920 --> 01:23:02,210 私はそれhacker_settings呼ば思われるので、それを変更してみましょう。 981 01:23:09,610 --> 01:23:13,500 hacker_settingsにすべてを変える。 982 01:23:13,500 --> 01:23:16,870 >> 現在、私たちのプログラムの最後に、我々は元に戻したいとしている 983 01:23:16,870 --> 01:23:20,210 現在normal_settingsの内側にあるもの、 984 01:23:20,210 --> 01:23:26,560 これは、単に&normal_settingsのように起こっています。 985 01:23:26,560 --> 01:23:30,650 私はもともとそれを得るので、私のnormal_settingsのいずれかを変更していないことに注意してください。 986 01:23:30,650 --> 01:23:34,520 それからちょうどそれらを戻すために、私は年末に戻ってそれらを渡す。 987 01:23:34,520 --> 01:23:38,390 これはアップデートしました。オーケー。 988 01:23:38,390 --> 01:23:43,900 >> 内部ここから今私はちょうど時間の関係でコードを説明します。 989 01:23:43,900 --> 01:23:46,350 それは多くのコードではありません。 990 01:23:50,770 --> 01:24:03,750 我々は、ファイルから文字を読み取ってください。我々は、それfを呼んだ。 991 01:24:03,750 --> 01:24:07,850 今、あなたは男fgetcはできますが、どのようにfgetcは、仕事に行くのです 992 01:24:07,850 --> 01:24:11,910 ただ、それはあなたがちょうど読んまたはEOFという文字を返すために起こっており、 993 01:24:11,910 --> 01:24:15,680 どのファイルまたはいくつかのエラーが起こっての終了に対応しています。 994 01:24:15,680 --> 01:24:19,900 我々は、ファイルから1文字を読むことを続けて、ループしている 995 01:24:19,900 --> 01:24:22,420 我々は、読むために文字を使い果たしたまで。 996 01:24:22,420 --> 01:24:26,650 我々はそれをしている間と、我々は、インチ規格から1文字を待つ 997 01:24:26,650 --> 01:24:29,090 毎回あなたは、コマンドラインで何かを入力します 998 01:24:29,090 --> 01:24:32,820 インチ規格から文字で読んだ 999 01:24:32,820 --> 01:24:38,330 その後、putcharは、ただファイルから標準出力にここまで読んでchar型を置くとしている。 1000 01:24:38,330 --> 01:24:42,890 あなたは男のputcharことができますが、それは単に標準出力に入れていると、その文字を印刷している。 1001 01:24:42,890 --> 01:24:51,600 同じ考え方、また、単にのprintf( "%c"は、c)を行うことができます。 1002 01:24:53,330 --> 01:24:56,670 それが私たちの仕事の大半をするつもりだ。 1003 01:24:56,670 --> 01:25:00,300 >> 私たちがやりたいとしている最後のことは、弊社のファイルをfclose関数である。 1004 01:25:00,300 --> 01:25:03,310 あなたはfcloseをしない場合、それはメモリリークだ。 1005 01:25:03,310 --> 01:25:06,680 我々は、我々が最初に開いたファイルをfcloseをしたい、と私はそれだと思う。 1006 01:25:06,680 --> 01:25:13,810 我々はそれを行う場合、私はすでに問題になった。 1007 01:25:13,810 --> 01:25:17,260 見てみましょう。 1008 01:25:17,260 --> 01:25:19,960 それは何を文句でしたか? 1009 01:25:19,960 --> 01:25:30,220 'int'の期待が、引数の型は '構造_IO_FILE *'である。 1010 01:25:36,850 --> 01:25:39,370 それが動作するかどうかを我々が表示されます。 1011 01:25:45,210 --> 01:25:53,540 C99でのみ許可されて。キャーッ。さて、hacker_typerを作る。 1012 01:25:53,540 --> 01:25:57,760 今、私たちは、より有用な説明を取得します。 1013 01:25:57,760 --> 01:25:59,900 そう宣言されていない識別子 'normal_settings'の使用。 1014 01:25:59,900 --> 01:26:04,170 私はそれnormal_settings呼び出していませんでした。私はそれcurrent_settings呼ばれる。 1015 01:26:04,170 --> 01:26:12,090 だから、すべてのことを変更してみましょう。 1016 01:26:17,920 --> 01:26:21,710 今の引数を渡す。 1017 01:26:26,290 --> 01:26:29,500 私は今のところ、この0を作ってあげる。 1018 01:26:29,500 --> 01:26:36,720 オーケー。 。/ hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 私も初めに画面をクリアしていませんでした。 1020 01:26:39,590 --> 01:26:42,960 しかし、あなたは画面をクリアする方法を確認するために設定された最後の問題を振り返ることができます。 1021 01:26:42,960 --> 01:26:45,160 それはちょうど、いくつかの文字を印刷している 1022 01:26:45,160 --> 01:26:47,210 これは私がやりたいことをやっている間に。 1023 01:26:47,210 --> 01:26:48,900 オーケー。 1024 01:26:48,900 --> 01:26:55,280 そして、これは0の代わりに標準入力であることが必要となった理由を考える 1025 01:26:55,280 --> 01:27:00,560 #0を定義すべき 1026 01:27:00,560 --> 01:27:03,890 これがあることを不平を言っている - 1027 01:27:13,150 --> 01:27:19,360 私は、ファイル記述子があることを述べたが、その後、また、あなたのFILE *を持っているときに前に、 1028 01:27:19,360 --> 01:27:23,210 ファイル記述子は、ただ一つの整数である 1029 01:27:23,210 --> 01:27:26,970 のFILE *のに対し、それに関連付けられているものの全体の束を持っています。 1030 01:27:26,970 --> 01:27:30,380 我々は標準入力の代わりに0を言う必要がある理由 1031 01:27:30,380 --> 01:27:37,480 そのstdinがファイルディスクリプタ0を参照しているものを指すのFI​​LE *です。 1032 01:27:37,480 --> 01:27:45,070 そうであってもここまで私はfopenを行うとき(argv [1]を、私は戻ってFILE *を取得しています。 1033 01:27:45,070 --> 01:27:51,180 しかし、どこかにそのファイル*に、そのファイルのファイル記述子に対応するものです。 1034 01:27:51,180 --> 01:27:57,430 あなたが開いているのmanページを見れば、私はあなたが開いて男3を行う必要があるでしょうと思う - いや - 1035 01:27:57,430 --> 01:27:59,380 男2オープン - ええ。 1036 01:27:59,380 --> 01:28:06,250 あなたが開いているのためのページを見れば、オープンは、下位レベルのfopenのようなものです 1037 01:28:06,250 --> 01:28:09,350 そしてそれは実際のファイル記述子を返している。 1038 01:28:09,350 --> 01:28:12,050 fopenはオープンの上に原料の束を行い、 1039 01:28:12,050 --> 01:28:17,640 ファイル記述子は、全体のFILE *のポインタを返すことだけを返すのではなく、どの 1040 01:28:17,640 --> 01:28:20,590 の内部は私たちの小さなファイル記述子です。 1041 01:28:20,590 --> 01:28:25,020 のFILE *の事を指しますので、標準で、 1042 01:28:25,020 --> 01:28:29,120 一方0は、それ自体は単なるファイル·ディスクリプタの規格を指します。 1043 01:28:29,120 --> 01:28:32,160 >> 質問はありますか? 1044 01:28:32,160 --> 01:28:35,930 [笑]はなってしまった。 1045 01:28:35,930 --> 01:28:39,140 かしこまりました。我々はおしまいです。 [笑] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]