1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Sección 5 - máis cómodo] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [Esta é CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Como dixo no meu correo electrónico, hai unha morea de cousas que podes usar 5 00:00:14,250 --> 00:00:17,060 Ademais do aparello de realmente facer os conxuntos de problemas. 6 00:00:17,060 --> 00:00:19,910 Recomendamos que faga iso no aparello só porque entón nós podemos axudar con máis facilidade 7 00:00:19,910 --> 00:00:22,070 e sabemos como todo vai funcionar. 8 00:00:22,070 --> 00:00:26,950 Pero, como un exemplo de onde pode facer cousas, digamos, se non ten acceso 9 00:00:26,950 --> 00:00:31,570 para un dispositivo ou quere traballar no soto do Centro de Ciencias - 10 00:00:31,570 --> 00:00:33,090 que en realidade teñen o aparello tamén - 11 00:00:33,090 --> 00:00:35,150 se quere traballar en calquera lugar. 12 00:00:35,150 --> 00:00:42,370 Un exemplo é xa viu / escoitou falar de SSH? 13 00:00:44,380 --> 00:00:47,780 O SSH é basicamente como conectarse a algunha cousa. 14 00:00:47,780 --> 00:00:51,340 En realidade, agora eu estou SSHed no aparello. 15 00:00:51,340 --> 00:00:54,290 Eu nunca traballar directamente no aparello. 16 00:00:55,930 --> 00:01:01,060 Aquí está o aparello, e se ollar para abaixo aquí ve este enderezo IP. 17 00:01:01,060 --> 00:01:03,650 Eu nunca traballar no propio aparello; 18 00:01:03,650 --> 00:01:08,840 Eu sempre viña dunha xanela xanela de terminal / iTerm2. 19 00:01:08,840 --> 00:01:15,910 Pode SSH para que o enderezo IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Lembro que ese número moi facilmente porque é un estándar tan agradable. 21 00:01:20,390 --> 00:01:24,920 Pero iso me vai pedir o meu contrasinal, e agora eu estou no aparello. 22 00:01:24,920 --> 00:01:33,060 Basicamente, neste momento, se abriu un terminal dentro do propio dispositivo, 23 00:01:33,060 --> 00:01:36,350 esta interface, pero usalo, é exactamente a mesma 24 00:01:36,350 --> 00:01:40,010 como a interface que está a usar aquí, pero agora está SSHed. 25 00:01:42,240 --> 00:01:44,920 Non ten que SSH para o aparello. 26 00:01:44,920 --> 00:01:52,360 Un exemplo de outro lugar podería SSH é que eu estou seguro que ten por defecto - 27 00:01:52,360 --> 00:01:55,020 Oh Maior. 28 00:01:55,020 --> 00:02:01,130 Todos vostedes deben ter por contas estándar FAS nos servidores da FAS. 29 00:02:01,130 --> 00:02:06,840 Para min, eu faría o SSH para rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Vai pedirlle que a primeira vez, e di que si. 31 00:02:11,610 --> 00:02:15,840 O meu contrasinal é só vai ser o meu contrasinal fans. 32 00:02:15,840 --> 00:02:22,650 E agora, eu estou SSHed aos servidores agradable, e podo facer o que eu queira aquí. 33 00:02:22,650 --> 00:02:28,560 Unha morea de clases que poden ser adoptadas, como a 124, vai ter que cargar cousas para aquí 34 00:02:28,560 --> 00:02:30,950 para realmente presentar os seus conxuntos de problemas. 35 00:02:30,950 --> 00:02:34,100 Pero digamos que non ten acceso ao seu dispositivo. 36 00:02:34,100 --> 00:02:37,910 Entón podes facer cousas, como aquí, que vai dicir - 37 00:02:37,910 --> 00:02:42,160 Este é só nosa sección de preguntas. 38 00:02:42,160 --> 00:02:45,070 El vai pedir para facer iso no aparello. 39 00:02:45,070 --> 00:02:47,790 En vez diso eu vou facelo no servidor. 40 00:02:47,790 --> 00:02:50,560 Eu estou indo para descomprimir iso. 41 00:02:50,560 --> 00:02:55,670 O problema vai ser que está acostumado a usar algo como gedit 42 00:02:55,670 --> 00:02:58,160 ou o que quere no interior do aparello. 43 00:02:58,160 --> 00:03:01,830 Non vai ter que o servidor fans. 44 00:03:01,830 --> 00:03:04,110 É todo só vai ser esta interface textual. 45 00:03:04,110 --> 00:03:09,180 Entón, vostede podería un ou outro, tratar de aprender un editor de texto que eles teñen. 46 00:03:09,180 --> 00:03:12,130 Teñen Nano. 47 00:03:12,130 --> 00:03:14,990 Nano é normalmente moi doado de usar. 48 00:03:14,990 --> 00:03:19,470 Pode usar as súas frechas e escriba normalmente. 49 00:03:19,470 --> 00:03:21,250 Entón, iso non é difícil. 50 00:03:21,250 --> 00:03:24,720 Se queres comezar realmente a fantasía que pode usar o Emacs, 51 00:03:24,720 --> 00:03:29,850 que probablemente non debería ter aberto porque eu non sei nin como pechar Emacs. 52 00:03:29,850 --> 00:03:32,760 Control X, Control C? Si 53 00:03:32,760 --> 00:03:35,310 Ou pode utilizar o Vin, que é o que eu uso. 54 00:03:35,310 --> 00:03:37,800 E así esas son as súas opcións. 55 00:03:37,800 --> 00:03:43,830 Se non queres facer iso, tamén se pode, se ollar para manual.cs50.net - 56 00:03:43,830 --> 00:03:45,410 Oh 57 00:03:45,410 --> 00:03:49,920 Nun PC, pode SSH usando putty, 58 00:03:49,920 --> 00:03:51,940 que vai ter que baixar por separado. 59 00:03:51,940 --> 00:03:55,460 En un Mac, pode só polo terminal de uso estándar ou podes baixar iTerm2, 60 00:03:55,460 --> 00:03:58,490 que é como un terminal, agradable fantasía. 61 00:03:58,490 --> 00:04:03,780 Se vai para manual.cs50.net podes ver un link para o Notepad + +, 62 00:04:03,780 --> 00:04:07,120 que é o que pode usar en un PC. 63 00:04:07,120 --> 00:04:13,340 El permite que SFTP de Notepad + +, que é basicamente SSH. 64 00:04:13,340 --> 00:04:17,750 O que isto vai deixar facer é editar os seus arquivos locais, 65 00:04:17,750 --> 00:04:20,670 e sempre que quere garda-los, el ha salvar a nice.fas, 66 00:04:20,670 --> 00:04:23,670 onde podes executa-los. 67 00:04:23,670 --> 00:04:26,880 É o equivalente en un Mac vai ser TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Entón, el permite que fai a mesma cousa. 69 00:04:28,760 --> 00:04:32,800 El permite que edite arquivos localmente e garda-los en nice.fas, 70 00:04:32,800 --> 00:04:35,730 onde podes executa-los. 71 00:04:35,730 --> 00:04:40,400 Entón, se está sempre preso sen un aparello, ten estas opcións 72 00:04:40,400 --> 00:04:44,230 aínda facer os seus xogos de problemas. 73 00:04:44,230 --> 00:04:48,250 O único problema vai ser que non vai ter a biblioteca CS50 74 00:04:48,250 --> 00:04:51,580 porque nice.fas non por defecto ten iso. 75 00:04:51,580 --> 00:04:55,970 Podes baixar a biblioteca CS50 - 76 00:04:55,970 --> 00:04:58,470 Eu non creo que eu teño neste momento. 77 00:04:58,470 --> 00:05:03,270 Podes baixar a biblioteca CS50 e copia-lo para nice.fas, 78 00:05:03,270 --> 00:05:07,450 ou eu creo que neste momento non usalo máis de calquera maneira. 79 00:05:07,450 --> 00:05:12,720 Ou nós, pode, polo de agora, substituílo por 80 00:05:12,720 --> 00:05:18,480 as implementacións das funcións na biblioteca CS50 de calquera maneira. 81 00:05:18,480 --> 00:05:21,370 De xeito que non debe ser moi dunha restrición. 82 00:05:21,370 --> 00:05:23,710 E é iso. 83 00:05:26,460 --> 00:05:29,820 >> Vou volver para o aparello agora, nós imos facer todo o aparello. 84 00:05:29,820 --> 00:05:37,510 Mirando para a nosa sección de preguntas, en principio, como dixen no meu correo electrónico, 85 00:05:37,510 --> 00:05:43,620 temos que falar do curto debería asistir. 86 00:05:43,620 --> 00:05:51,980 Temos a redirección e Pipes e esas tres preguntas. 87 00:05:51,980 --> 00:05:56,070 >> Para que fluxo que funciona como printf escribir por defecto? 88 00:05:56,070 --> 00:05:59,130 Entón córrego. ¿Que é un fluxo? 89 00:06:06,520 --> 00:06:15,100 Un fluxo é basicamente como se fose só algúns - 90 00:06:15,100 --> 00:06:21,450 Non é mesmo unha fonte de 1s e 0s. 91 00:06:21,450 --> 00:06:24,920 O fluxo é pedir aquí é a estándar. 92 00:06:24,920 --> 00:06:27,250 E así por defecto é un fluxo que cando escribir para el, 93 00:06:27,250 --> 00:06:30,940 aparece na pantalla. 94 00:06:30,940 --> 00:06:36,860 A Standard, por stream, isto significa que acaba de escribir 1s e 0s a el, 95 00:06:36,860 --> 00:06:40,220 E a outra extrema de saída estándar só le a partir dese fluxo. 96 00:06:40,220 --> 00:06:43,540 É só unha secuencia de 1s e 0s. 97 00:06:43,540 --> 00:06:45,570 Podes escribir para córregos ou pode ler a partir de fluxos 98 00:06:45,570 --> 00:06:47,950 dependendo do que o fluxo é realmente. 99 00:06:47,950 --> 00:06:52,800 Os outros dous fluxos estándar son estándar e erro estándar. 100 00:06:52,800 --> 00:06:57,540 Estándar en sempre que GetString, está esperando por ti para material de entrada. 101 00:06:57,540 --> 00:07:01,570 Por iso, esperando por ti, é realmente esperando por defecto en, 102 00:07:01,570 --> 00:07:04,880 o que é realmente o que comeza cando escribe no teclado. 103 00:07:04,880 --> 00:07:07,530 Vostede está escribindo en estándar dentro 104 00:07:07,530 --> 00:07:10,050 Erro estándar é basicamente equivalente á saída estándar, 105 00:07:10,050 --> 00:07:13,280 pero está especializada en que cando imprimir para o erro estándar, 106 00:07:13,280 --> 00:07:16,770 debería só imprimir mensaxes de erro para que 107 00:07:16,770 --> 00:07:20,200 para que poida distinguir entre mensaxes regulares impresos na pantalla 108 00:07:20,200 --> 00:07:24,560 contra mensaxes de erro, dependendo se eles foron para fóra estándar ou erro estándar. 109 00:07:24,560 --> 00:07:28,660 Arquivos tamén. 110 00:07:28,660 --> 00:07:32,440 Fóra estándar, patrón, e erro estándar son fluxos só especiais, 111 00:07:32,440 --> 00:07:36,810 pero realmente calquera arquivo, cando abre un arquivo, el torna-se un fluxo de bytes 112 00:07:36,810 --> 00:07:40,740 onde podes só ler este fluxo. 113 00:07:40,740 --> 00:07:47,770 Vostede, no seu maior parte, pode só pensar nun ficheiro como un fluxo de bytes. 114 00:07:47,770 --> 00:07:51,190 Entón, o que os fluxos que escriben para por defecto? Saída estándar. 115 00:07:51,190 --> 00:07:56,980 >> Cal é a diferenza entre> e? >> 116 00:07:58,140 --> 00:08:03,710 Será que alguén asistir ao vídeo antes? Okay. 117 00:08:03,710 --> 00:08:10,960 > Vai ser como redireccionar en arquivos, 118 00:08:10,960 --> 00:08:15,240 e >> tamén vai redireccionar a saída en arquivos, 119 00:08:15,240 --> 00:08:17,820 pero é en vez de ir para engadir o ficheiro. 120 00:08:17,820 --> 00:08:23,430 Por exemplo, digamos que eu ocorrer de ter Dict aquí, 121 00:08:23,430 --> 00:08:27,020 e as cousas só dentro Dict é gato, gato, can, peixe, can. 122 00:08:27,020 --> 00:08:31,530 Un comando que ten na liña de comandos é gato, 123 00:08:31,530 --> 00:08:34,539 que está indo só para imprimir o que está nun arquivo. 124 00:08:34,539 --> 00:08:40,679 Polo tanto, cando digo Dict gato, que vai imprimir gato, can, gato, peixe, can. Isto é todo o gato fai. 125 00:08:40,679 --> 00:08:46,280 Isto significa que impresa na saída estándar, gato, can, gato, peixe, can. 126 00:08:46,280 --> 00:08:53,240 Se eu xa quere redireccionar iso para un arquivo, podo usar>, redireccionándoos para o que é o ficheiro. 127 00:08:53,240 --> 00:08:56,460 Vou chamar o ficheiro de arquivo. 128 00:08:56,460 --> 00:09:00,320 Entón agora eu ls, eu vou ver eu teño un novo ficheiro chamado ficheiro. 129 00:09:00,320 --> 00:09:05,700 E se eu abri-lo, el vai ter exactamente o gato poñer na liña de comandos. 130 00:09:05,700 --> 00:09:11,040 Polo tanto, agora se eu fai iso de novo, entón vai redireccionar a saída en arquivo, 131 00:09:11,040 --> 00:09:13,930 e eu vou ter exactamente a mesma cousa. 132 00:09:13,930 --> 00:09:17,910 Entón, tecnicamente, é completamente anulou o que tiñamos. 133 00:09:17,910 --> 00:09:22,970 E imos ver se eu cambiar Dict, eu tirei can. 134 00:09:22,970 --> 00:09:29,980 Agora, se nós gato Dict en arquivo novo, nós imos ter a nova versión co can eliminado. 135 00:09:29,980 --> 00:09:32,400 Entón está completamente substitúe-lo. 136 00:09:32,400 --> 00:09:36,640 En vez diso, se usarmos >>, que vai engadir o ficheiro. 137 00:09:36,640 --> 00:09:40,860 Agora, abra o ficheiro, vemos que temos exactamente a mesma cousa dúas veces impresa 138 00:09:40,860 --> 00:09:44,920 porque alí unha vez máis, a continuación, engade ao orixinal. 139 00:09:44,920 --> 00:09:48,130 Entón é iso que >>> e facer. 140 00:09:48,130 --> 00:09:50,580 Será que a seguinte pregunta - Non preguntar sobre iso. 141 00:09:50,580 --> 00:09:59,050 >> O outro que temos é <, que se> redirecciona saída estándar, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Imos ver se temos un exemplo. 144 00:10:14,750 --> 00:10:16,930 Eu podo escribir un rápido. 145 00:10:17,870 --> 00:10:25,700 Imos dar calquera arquivo, hello.c. 146 00:10:56,060 --> 00:10:59,070 Arquivo relativamente simple. 147 00:10:59,070 --> 00:11:03,570 Estou só comezando unha secuencia e despois imprimir "Ola" calquera que sexa a secuencia de carácteres que acababa de entrar era. 148 00:11:03,570 --> 00:11:07,990 Entón faga Ola e despois. / Olá 149 00:11:07,990 --> 00:11:10,720 Agora está me levando para entrar algo, 150 00:11:10,720 --> 00:11:15,070 o que significa que está esperando as cousas a ser celebrado estándar dentro 151 00:11:15,070 --> 00:11:20,450 Entón o que eu queira poñerse en estándar dentro Nós só estamos indo a dicir Ola, Rob! 152 00:11:20,450 --> 00:11:23,310 Entón está imprimindo a saída estándar Ola, Rob! 153 00:11:23,310 --> 00:11:28,860 Se eu fai. / Ola e despois redireccionar, 154 00:11:30,740 --> 00:11:34,310 por agora só se pode redireccionar a partir dun arquivo. 155 00:11:34,310 --> 00:11:41,720 Entón, se eu poñer nalgún arquivo, txt, e eu coloque Rob, 156 00:11:41,720 --> 00:11:52,300 se eu executar Ola e entón redireccionar o ficheiro txt en. / Ola, que vai dicir Ola, Rob! inmediatamente. 157 00:11:52,300 --> 00:11:57,160 Cando se chega por primeira vez GetString e está á espera de patrón en, 158 00:11:57,160 --> 00:12:01,730 estándar en non máis esperando no teclado para que os datos inseridos. 159 00:12:01,730 --> 00:12:05,980 En vez diso, temos redirixido estándar para ler o ficheiro txt. 160 00:12:05,980 --> 00:12:10,290 E así vai ler o txt, que é só o Rob liña, 161 00:12:10,290 --> 00:12:13,380 e, a continuación, que vai imprimir Ola, Rob! 162 00:12:13,380 --> 00:12:18,180 E se eu quixese, eu tamén podería facer. / Ola 00:12:21,500 e entón o patrón que é impresión, o que é Ola, Rob!, 164 00:12:21,500 --> 00:12:24,700 Eu podo redirección que no seu propio arquivo. 165 00:12:24,700 --> 00:12:29,790 Vou chamar o arquivo Ola - non, eu non vou, porque ese é o executable - txt2. 166 00:12:29,790 --> 00:12:40,150 Agora, txt2 terá a saída do. / Ola 00:12:43,520 >> Preguntas? 168 00:12:45,900 --> 00:12:49,090 >> Okay. Entón aquí temos pipeline. 169 00:12:49,090 --> 00:12:53,510 Pipes son a última unidade de redirección. 170 00:12:53,510 --> 00:12:58,750 >> Oh Eu creo que unha unidade de redirección é en vez de> fai 2>, 171 00:12:58,750 --> 00:13:01,070 que está redirixido erro estándar. 172 00:13:01,070 --> 00:13:06,280 Entón, se algo deu o erro estándar, non tería colocado en txt2. 173 00:13:06,280 --> 00:13:12,480 Pero repare se eu fai 2>, entón aínda está imprimindo Ola, Rob! para a liña de comandos 174 00:13:12,480 --> 00:13:18,600 porque eu estou só redirixido erro estándar, eu non estou redirixido a saída estándar. 175 00:13:18,600 --> 00:13:22,210 Erro estándar e saída estándar son diferentes. 176 00:13:24,210 --> 00:13:27,080 Se quixese realmente escribir para o erro estándar, 177 00:13:27,080 --> 00:13:35,080 entón eu podería cambiar isto para fprintf para stderr. 178 00:13:35,080 --> 00:13:37,850 Entón printf, por defecto, imprime para a saída estándar. 179 00:13:37,850 --> 00:13:41,720 Se eu queira imprimir a erro estándar man, entón eu teño que usar fprintf 180 00:13:41,720 --> 00:13:45,010 e especificar o que quere imprimir. 181 00:13:45,010 --> 00:13:49,720 Se en vez fixen saída estándar fprintf, a continuación, que é basicamente equivalente a printf. 182 00:13:49,720 --> 00:13:55,530 Pero fprintf para o erro estándar. 183 00:13:57,790 --> 00:14:03,650 Entón, agora, se eu redireccionar isto txt2, Ola, Rob! aínda está a ser impresas na liña de comandos 184 00:14:03,650 --> 00:14:08,270 unha vez que está a ser impresas para o erro estándar e eu só estou redirixido a saída estándar. 185 00:14:08,270 --> 00:14:16,420 Se eu agora redireccionar o erro estándar, agora non se impreso, e txt2 será Ola, Rob! 186 00:14:16,420 --> 00:14:21,910 Entón, agora, pode imprimir os seus erros reais para o erro estándar 187 00:14:21,910 --> 00:14:24,720 e imprimir as súas mensaxes regulares para a saída estándar. 188 00:14:24,720 --> 00:14:31,420 E así, cando executar o programa, pode executa-lo como. / Ola, este tipo co 2> 189 00:14:31,420 --> 00:14:33,800 para que o seu programa vai funcionar normalmente, 190 00:14:33,800 --> 00:14:38,400 pero as mensaxes de erro que comeza pode comprobar máis tarde, no seu rexistro de erro, 191 00:14:38,400 --> 00:14:44,500 así os erros, e logo mirar máis tarde eo seu arquivo de erros terá posibles erros que se produciron. 192 00:14:45,200 --> 00:14:47,540 >> Preguntas? 193 00:14:47,540 --> 00:14:58,070 >> A última é a tubulação, que pode pensar en como aproveitar a saída estándar dun comando 194 00:14:58,070 --> 00:15:01,210 e tornándose o patrón do comando seguinte. 195 00:15:01,210 --> 00:15:05,570 Un exemplo aquí é o eco é unha cousa de liña de comandos 196 00:15:05,570 --> 00:15:11,840 que é só ir a ecoar o que eu coloque como o seu argumento. Non vou poñer comiñas. 197 00:15:11,840 --> 00:15:16,150 Eco bla, bla, bla é só ir para imprimir bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Antes, cando dixo que eu tiña que poñer Rob nun arquivo txt 199 00:15:20,600 --> 00:15:28,830 porque eu só podo redireccionar os arquivos txt, en vez diso, / se eu echo Rob 200 00:15:28,830 --> 00:15:35,520 e despois canaliza-lo. / Ola, que tamén vai facer o mesmo tipo de cousas. 201 00:15:35,520 --> 00:15:39,160 Isto está levando a saída deste comando, eco Rob, 202 00:15:39,160 --> 00:15:43,610 e usalo como entrada. / Olá 203 00:15:44,790 --> 00:15:49,560 Podes pensar niso como primeira redirección eco Rob nun arquivo 204 00:15:49,560 --> 00:15:54,160 e despois da entrada en. / Ola, este arquivo que acaba de ser emitidas. 205 00:15:54,160 --> 00:15:57,850 Mais é preciso o ficheiro temporal fóra do cadro. 206 00:16:01,890 --> 00:16:04,460 >> Preguntas sobre iso? 207 00:16:04,460 --> 00:16:07,150 >> A seguinte pregunta vai implicar iso. 208 00:16:07,150 --> 00:16:15,310 O gasoduto podería usar para atopar o número de nomes exclusivos nun arquivo chamado names.txt? 209 00:16:15,310 --> 00:16:24,160 Os comandos que imos querer usar aquí son únicos, por iso uniq, e WC. 210 00:16:24,160 --> 00:16:28,840 Podes facer uniq home para realmente ollar para o que fai, 211 00:16:28,840 --> 00:16:34,840 e el só vai para filtrar liñas correspondentes adxacentes a partir da entrada. 212 00:16:34,840 --> 00:16:40,690 E o home baño vai imprimir a palabra, salto de liña, e máis para cada ficheiro. 213 00:16:40,690 --> 00:16:43,760 E a última que imos querer usar é tipo, 214 00:16:43,760 --> 00:16:47,410 que está indo só para clasificar liñas dun ficheiro txt. 215 00:16:47,410 --> 00:16:58,080 Se eu fai un arquivo txt, names.txt, e Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 o que quero facer aquí é atopar o número de nomes únicos neste arquivo. 217 00:17:03,910 --> 00:17:08,750 Entón, o que debe ser a resposta? >> [Alumno] 4. Si >>. 218 00:17:08,750 --> 00:17:13,780 Debe ser 4, pois Rob, Tommy, Joseph, RJ son os nomes orixinais só neste arquivo. 219 00:17:13,780 --> 00:17:20,180 O primeiro paso, se eu só facer reconto de palabras na names.txt, 220 00:17:20,180 --> 00:17:24,290 é dicir, en realidade, me contando todo. 221 00:17:24,290 --> 00:17:32,560 Esta é realmente a impresión - Imos ver, o home baño - novas liñas, palabras e contador de bytes. 222 00:17:32,560 --> 00:17:38,270 Se eu só me importa as liñas, entón podo só facer baño-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Entón ese é un paso. 224 00:17:44,300 --> 00:17:50,510 Pero eu non quero baño-l names.txt porque names.txt só contén todos os nomes, 225 00:17:50,510 --> 00:17:54,170 e quero filtrar as non orixinais. 226 00:17:54,170 --> 00:18:01,200 Entón, se eu fai names.txt uniq, que non chega a me dar o que quero 227 00:18:01,200 --> 00:18:03,760 porque os nomes duplicados aínda están alí. 228 00:18:03,760 --> 00:18:07,690 Por que isto? Por que non uniq facendo o que quero? 229 00:18:07,690 --> 00:18:10,500 [Alumno] O dobre non son [inaudível] >> Yeah. 230 00:18:10,500 --> 00:18:16,370 Teña en conta que a páxina de manual para uniq di filtrar liñas correspondentes adxacentes. 231 00:18:16,370 --> 00:18:19,680 Eles non son adxacentes, polo que non pode filtra-los. 232 00:18:19,680 --> 00:18:31,100 Se eu clasificalos en primeiro lugar, names.txt tipo vai poñer todas as liñas duplicadas xuntos. 233 00:18:31,100 --> 00:18:34,450 Entón agora é que tipo names.txt. 234 00:18:34,450 --> 00:18:40,550 Vou querer usar isto como a entrada uniq, que é | uniq. 235 00:18:40,550 --> 00:18:43,390 Iso dáme José, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 e quero usar isto como a entrada para o baño-l, 237 00:18:49,260 --> 00:18:52,740 que me vai dar 4. 238 00:18:52,740 --> 00:18:56,930 Como di aquí, o gasoduto podería usar? 239 00:18:56,930 --> 00:19:01,390 Podes facer unha chea de cousas como usar unha serie de comandos 240 00:19:01,390 --> 00:19:05,130 onde se utiliza a saída dun comando como entrada para o próximo mando. 241 00:19:05,130 --> 00:19:08,780 Podes facer unha chea de cousas, unha morea de cousas intelixentes. 242 00:19:08,780 --> 00:19:11,440 >> Preguntas? 243 00:19:12,910 --> 00:19:14,600 Okay. 244 00:19:14,600 --> 00:19:17,880 Isto é todo para tubos e redirección. 245 00:19:18,370 --> 00:19:24,090 >> Agora imos para a cousa real, o material de codificación. 246 00:19:24,090 --> 00:19:29,100 Dentro deste PDF, podes ver este comando, 247 00:19:29,100 --> 00:19:32,950 e quere executar este comando no seu dispositivo. 248 00:19:36,240 --> 00:19:42,250 wget é o comando para só incorporarse algo de Internet, basicamente, 249 00:19:42,250 --> 00:19:45,180 así wget e este URL. 250 00:19:45,180 --> 00:19:49,110 Se foi para este URL no seu navegador, sería baixar o arquivo. 251 00:19:49,110 --> 00:19:52,510 Eu só facer clic sobre el, por iso a descarga do ficheiro para min. 252 00:19:52,510 --> 00:19:55,650 Pero escribir wget de que a cousa dentro do terminal 253 00:19:55,650 --> 00:19:58,620 é só ir a baixa-lo no seu terminal. 254 00:19:58,620 --> 00:20:02,750 Eu teño section5.zip, e queres descomprimir section5.zip, 255 00:20:02,750 --> 00:20:06,520 que vai dar-lle unha carpeta chamada section5, 256 00:20:06,520 --> 00:20:11,550 que vai ter todos os arquivos que imos estar usando hoxe dentro del. 257 00:20:33,380 --> 00:20:37,710 Como os nomes destes programas de arquivo suxerir, son un pouco buggy, 258 00:20:37,710 --> 00:20:40,990 así que a súa misión é descubrir por que usar gdb. 259 00:20:40,990 --> 00:20:44,560 Será que todos eles teñen baixado / saber como se atope los baixo 260 00:20:44,560 --> 00:20:47,480 no seu dispositivo? Okay. 261 00:20:47,480 --> 00:20:56,400 >> Correndo ./buggy1, que vai dicir fallo de segmento (núcleo), 262 00:20:56,400 --> 00:21:00,500 que en calquera momento comeza un segfault, é unha cousa mala. 263 00:21:00,500 --> 00:21:03,810 Baixo que circunstancias comeza un segfault? 264 00:21:03,810 --> 00:21:08,210 [Alumno] desreferenciação un punteiro nulo. Si >>. De xeito que é un exemplo. 265 00:21:08,210 --> 00:21:11,580 Dereferencing un punteiro nulo está indo para obter un segfault. 266 00:21:11,580 --> 00:21:16,720 O que un segfault significa que está tocando memoria que non debe tocar. 267 00:21:16,720 --> 00:21:21,350 Entón dereferencing un punteiro nulo é tocar o enderezo 0, 268 00:21:21,350 --> 00:21:28,060 e, basicamente, todos os ordenadores hoxe en día dicir que 0 enderezo é a memoria que non debe tocar. 269 00:21:28,060 --> 00:21:31,920 É por iso que unha dereferencing resultados punteiro nulo nun segfault. 270 00:21:31,920 --> 00:21:37,210 Cando ocorrer de non iniciar un punteiro, el ten un valor de lixo, 271 00:21:37,210 --> 00:21:41,520 e así, cando tenta eliminar a referencia que, con toda probabilidade que está tocando memoria 272 00:21:41,520 --> 00:21:43,540 que está no medio da nada. 273 00:21:43,540 --> 00:21:45,650 Se ocorrer de ter sorte e do valor de lixo 274 00:21:45,650 --> 00:21:48,440 pasou para apuntar a algún lugar na pila ou algo así, 275 00:21:48,440 --> 00:21:50,820 entón cando dereference que o punteiro que non lle inicializar, 276 00:21:50,820 --> 00:21:52,730 nada vai dar mal. 277 00:21:52,730 --> 00:21:55,480 Pero se está a apuntar cara, digamos, en algún lugar entre a pila eo heap, 278 00:21:55,480 --> 00:21:59,850 ou está a apuntar só para algún lugar que non foi utilizado polo seu programa, sen embargo, 279 00:21:59,850 --> 00:22:02,240 entón está tocando memoria que non debe estar tocando e segfault. 280 00:22:02,240 --> 00:22:06,370 Cando escribir unha función recursiva e recurses moitas veces 281 00:22:06,370 --> 00:22:08,720 ea súa pila crece moi grande e as colide pila en cousas 282 00:22:08,720 --> 00:22:12,270 que non debe ser colidindo con, está tocando memoria que non debe tocar, 283 00:22:12,270 --> 00:22:14,810 así segfault. 284 00:22:14,810 --> 00:22:17,010 Isto é que é segfault. 285 00:22:17,010 --> 00:22:21,810 >> É tamén a mesma razón que se ten unha secuencia como - 286 00:22:21,810 --> 00:22:23,930 imos volver ao programa anterior. 287 00:22:23,930 --> 00:22:28,530 En hello.c-estou indo só para facer outra cousa. 288 00:22:28,530 --> 00:22:33,770 char * s = "Ola mundo!"; 289 00:22:33,770 --> 00:22:42,310 Se eu usar * s = algo ou s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 entón faga Ola,. / Ola, por que iso segfault? 291 00:22:48,410 --> 00:22:51,250 Por que isto segfault? 292 00:22:55,660 --> 00:22:57,890 O que espera que aconteza? 293 00:22:57,890 --> 00:23:06,640 Se eu fixen printf ("% s \ n" s), o que espera para ser impreso? 294 00:23:06,640 --> 00:23:09,930 [Estudante] X Olá Si >>. 295 00:23:09,930 --> 00:23:15,140 O problema é que cando declarar unha secuencia como esta, 296 00:23:15,140 --> 00:23:18,190 s é un punteiro que está indo a ir a pila, 297 00:23:18,190 --> 00:23:25,880 e que s está destacar é esta corda que está contido na memoria só de lectura. 298 00:23:25,880 --> 00:23:30,560 Entón, só pola memoria o nome, só de lectura, ten que ter a idea 299 00:23:30,560 --> 00:23:33,010 que se tentar cambiar o que está na memoria só de lectura, 300 00:23:33,010 --> 00:23:36,670 está facendo algo que non debería estar facendo a memoria e segfault. 301 00:23:36,670 --> 00:23:45,360 Esta é realmente unha gran diferenza entre char * s e s char []. 302 00:23:45,360 --> 00:23:48,790 Entón char s [], agora esta cadea será colocado na pila, 303 00:23:48,790 --> 00:23:53,960 ea pila non é só de lectura, o que significa que este debe funcionar perfectamente ben. 304 00:23:55,500 --> 00:23:57,370 E el fai. 305 00:23:57,370 --> 00:24:06,250 Lembre que cando fago char * s = "Ola mundo!", S en si é na pila 306 00:24:06,250 --> 00:24:10,390 s puntos, pero en outro lugar, en outro lugar e que pasa a ser de só lectura. 307 00:24:10,390 --> 00:24:15,640 Pero char s [] é só algo sobre a pila. 308 00:24:17,560 --> 00:24:21,760 Entón, iso é outro exemplo dun segfault suceder. 309 00:24:21,760 --> 00:24:27,820 >> Vimos que ./buggy1 resultou nun segfault. 310 00:24:27,820 --> 00:24:31,810 En teoría, non debe ollar para buggy1.c inmediatamente. 311 00:24:31,810 --> 00:24:35,170 En vez diso, nós imos ollar para el a través gdb. 312 00:24:35,170 --> 00:24:37,750 Teña en conta que cando comeza un fallo de segmentación (núcleo), 313 00:24:37,750 --> 00:24:40,850 tes este arquivo sobre o núcleo aquí chamado. 314 00:24:40,850 --> 00:24:45,200 Se ls-l, imos ver que o núcleo xeralmente é un arquivo moi grande. 315 00:24:45,200 --> 00:24:51,580 Este é o número de bytes do arquivo, por iso parece que é 250 e poucos kilobytes. 316 00:24:51,580 --> 00:24:56,120 A razón para isto é que o despejo do núcleo, en realidade, é 317 00:24:56,120 --> 00:25:01,410 é cando as súas fallos do programa, o estado da memoria do seu programa 318 00:25:01,410 --> 00:25:05,230 só é copiado e pegado a este ficheiro. 319 00:25:05,230 --> 00:25:07,270 El é despejada dentro do arquivo. 320 00:25:07,270 --> 00:25:13,060 Este programa, mentres estaba correndo, pasou a ter un uso de memoria de preto de 250 kilobytes, 321 00:25:13,060 --> 00:25:17,040 e iso é o que ten despexado neste arquivo. 322 00:25:17,040 --> 00:25:23,630 Agora podes ollar para o arquivo, se facemos gdb núcleo buggy1. 323 00:25:23,630 --> 00:25:30,130 Podemos só facer o gdb buggy1, e que só vai comezar a gdb regularmente, 324 00:25:30,130 --> 00:25:33,800 usando buggy1 como o seu ficheiro de entrada. 325 00:25:33,800 --> 00:25:38,260 Pero se fai gdb núcleo buggy1, entón é especialmente indo para iniciar gdb 326 00:25:38,260 --> 00:25:40,330 mirando o arquivo do núcleo. 327 00:25:40,330 --> 00:25:45,560 E dicindo buggy1 gdb medio sabe que o arquivo vén de núcleo do programa buggy1. 328 00:25:45,560 --> 00:25:49,580 Entón gdb buggy1 núcleo vai traer connosco inmediatamente 329 00:25:49,580 --> 00:25:52,060 onde o programa pasou a rematar. 330 00:25:57,720 --> 00:26:02,340 Vemos aquí programa rematou con sinal de 11, fallo de segmento. 331 00:26:02,340 --> 00:26:10,110 Nós ocorrer para ver unha liña de montaxe, que probablemente non é moi útil. 332 00:26:10,110 --> 00:26:15,360 Pero se escribir BT ou backtrace, que vai ser a función 333 00:26:15,360 --> 00:26:19,430 que nos dá a lista dos nosos cadros de pila actuais. 334 00:26:19,430 --> 00:26:23,150 Entón backtrace. Parece que só temos dous cadros de pila. 335 00:26:23,150 --> 00:26:26,310 O primeiro é o noso cadro de pila principal, 336 00:26:26,310 --> 00:26:29,810 eo segundo é o cadro de pila para esta función que acontecer para ser, 337 00:26:29,810 --> 00:26:34,440 que parece que só temos o código de montaxe para. 338 00:26:34,440 --> 00:26:38,050 Entón, imos voltar a nosa función principal, 339 00:26:38,050 --> 00:26:42,300 e para iso podemos facer un cadro, e creo que tamén pode facerse, 340 00:26:42,300 --> 00:26:45,160 pero eu case nunca cara abaixo - ou cara arriba. Si 341 00:26:45,160 --> 00:26:50,710 Arriba e abaixo. Up leva ata un cadro de pila, para abaixo leva a un cadro de pila. 342 00:26:50,710 --> 00:26:53,240 Teño tendencia a non usar isto. 343 00:26:53,240 --> 00:26:59,120 Eu só dicir especificamente o cadro 1, que é volver para o cadro co 1. 344 00:26:59,120 --> 00:27:01,750 Cadro 1 vai traer-nos en cadro de pila principal, 345 00:27:01,750 --> 00:27:05,570 e el di que aquí a liña de código que esteamos menos. 346 00:27:05,570 --> 00:27:07,950 Se quixésemos liñas máis un par de código, podemos dicir lista 347 00:27:07,950 --> 00:27:11,280 e que vai dar todas as liñas de código ao seu redor. 348 00:27:11,280 --> 00:27:13,360 A liña que foi segfaulted en 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 rochas", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Se non é obvio aínda, pode obterse directamente aquí só pensar por que segfaulted. 351 00:27:24,130 --> 00:27:28,800 Pero podemos dar un paso máis lonxe e dicir: "Por que argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Imos impresión argv [1], e parece que é 0x0, que é o punteiro nulo. 353 00:27:38,830 --> 00:27:44,750 Estamos strcmping CS50 rochas e nulos, e así que vai segfault. 354 00:27:44,750 --> 00:27:48,280 E por que é argv [1] nulo? 355 00:27:48,640 --> 00:27:51,280 [Alumno] Porque non dar calquera argumentos de liña de comandos. 356 00:27:51,280 --> 00:27:53,390 Si Non dar os argumentos de liña de comandos. 357 00:27:53,390 --> 00:27:58,460 Entón ./buggy1 só vai ter argv [0] ser ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Non vai ter unha argv [1], de xeito que vai segfault. 359 00:28:02,100 --> 00:28:07,450 Pero, en vez diso, eu só CS50, que vai dicir que comeza un D 360 00:28:07,450 --> 00:28:09,950 porque iso é o que é suposta facer. 361 00:28:09,950 --> 00:28:15,240 Mirando buggy1.c, suporía para imprimir "Ten un D" - 362 00:28:15,240 --> 00:28:20,820 Se argv [1] non é "CS50 rochas", "Ten un D", máis "gañou un!" 363 00:28:20,820 --> 00:28:25,660 Polo tanto, se queremos un A, temos que para comparar como certa, 364 00:28:25,660 --> 00:28:28,710 o que significa que compara a 0. 365 00:28:28,710 --> 00:28:31,100 Entón, argv [1] que ser "CS50 pedras". 366 00:28:31,100 --> 00:28:35,660 Se queres facer iso na liña de comandos, ten que usar \ para escapar do espazo. 367 00:28:35,660 --> 00:28:41,690 Entón CS50 \ rochas e gaña un! 368 00:28:41,690 --> 00:28:44,060 Se non fai a barra invertida, porque isto non funciona? 369 00:28:44,060 --> 00:28:47,190 [Estudante] e dous argumentos diferentes. Si >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] vai ser CS50, e argv [2] vai ser rochas. Okay. 371 00:28:52,540 --> 00:28:56,470 >> Agora ./buggy2 vai segfault novo. 372 00:28:56,470 --> 00:29:01,880 En vez de abri-lo co seu arquivo de núcleo, imos abrir buggy2 directamente, 373 00:29:01,880 --> 00:29:05,000 así gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Agora, se nós simplemente executar o noso programa, entón el vai dicir Programa recibiu sinal SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 que é o segfault sinal, e este é o lugar onde se produciu a acontecer. 376 00:29:15,530 --> 00:29:21,250 Mirando para o noso backtrace, vemos que estabamos no oh_no función, 377 00:29:21,250 --> 00:29:23,900 que foi chamado polo Dinky función, que foi chamado polo binky función, 378 00:29:23,900 --> 00:29:26,460 que foi chamado por principal. 379 00:29:26,460 --> 00:29:31,680 Tamén podemos ver os argumentos para estas funcións. 380 00:29:31,680 --> 00:29:34,680 O argumento para Dinky e binky foi 1. 381 00:29:34,680 --> 00:29:44,390 Se incluír a función oh_no, vemos que oh_no está só facendo char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "boom"; 383 00:29:47,410 --> 00:29:50,330 Por que isto non? 384 00:29:54,330 --> 00:29:58,380 [Alumno] Non pode cancelar o punteiro nulo? Si >>. 385 00:29:58,380 --> 00:30:06,090 Este é só dicir s NULL, independentemente de se isto acontece de ser un char **, 386 00:30:06,090 --> 00:30:12,070 o que, dependendo da forma como o interpretar, que podería ser un enlace a un enlace a unha cadea 387 00:30:12,070 --> 00:30:15,550 ou unha matriz de cadeas. 388 00:30:15,550 --> 00:30:21,430 É s NULL, entón * s é dereferencing un punteiro nulo, 389 00:30:21,430 --> 00:30:24,800 e así é que isto vai funcionar. 390 00:30:24,800 --> 00:30:27,540 Esta é unha das formas máis rápidas que pode posiblemente segfault. 391 00:30:27,540 --> 00:30:31,300 É só declarar un punteiro nulo e inmediatamente segmento estándar. 392 00:30:31,300 --> 00:30:34,570 Isto é o que está facendo oh_no. 393 00:30:34,570 --> 00:30:43,400 Ou tamén ata un cadro, entón imos entrar na función que chamou oh_no. 394 00:30:43,400 --> 00:30:44,830 Eu teño que facer iso para abaixo. 395 00:30:44,830 --> 00:30:48,610 Se non escribir un comando e só prema Intro novamente, 396 00:30:48,610 --> 00:30:52,350 el vai só repetir o mando anterior que foi. 397 00:30:52,350 --> 00:30:56,610 Estamos no cadro 1. 398 00:30:56,610 --> 00:31:04,650 Listado este cadro, vemos aquí é a nosa función. 399 00:31:04,650 --> 00:31:08,520 Podes bater lista de novo, ou pode facer lista de 20 e ha incluír máis. 400 00:31:08,520 --> 00:31:13,640 O Dinky función di que se eu for 1, entón vai para a función oh_no, 401 00:31:13,640 --> 00:31:15,960 senón vai para a función furtivo. 402 00:31:15,960 --> 00:31:18,700 E sabemos que é un i porque pasou de verse aquí 403 00:31:18,700 --> 00:31:22,560 Dinky que foi chamado o argumento 1. 404 00:31:22,560 --> 00:31:27,560 Ou pode simplemente non imprimir I e vai dicir que eu é 1. 405 00:31:27,560 --> 00:31:33,770 Estamos actualmente en Dinky, e subir outro cadro, sabemos que vai acabar en binky. 406 00:31:33,770 --> 00:31:36,600 Up Agora estamos en binky. 407 00:31:36,600 --> 00:31:41,340 Listado esta función - a lista de antes de media me cortou - 408 00:31:41,340 --> 00:31:52,670 empezou como se eu é 0, entón imos chamalo oh_no, senón chamar Dinky. 409 00:31:52,670 --> 00:31:57,000 Sabemos que eu era un, por iso chamado Dinky. 410 00:31:57,000 --> 00:32:05,030 E agora estamos de volta no inicio, e principal só vai ser int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Isto só lle vai dar un número aleatorio que é 0, 1 ou 2. 412 00:32:08,790 --> 00:32:12,780 Vai chamar binky con ese número, e ha voltar 0. 413 00:32:12,780 --> 00:32:16,700 Mirando para iso, 414 00:32:16,700 --> 00:32:19,880 só camiñando a través do programa manualmente, sen executa-lo inmediatamente, 415 00:32:19,880 --> 00:32:25,400 ten que definir un punto de ruptura na principal, o que significa que, cando executar o programa 416 00:32:25,400 --> 00:32:31,020 seu programa é executado ata que chega a un punto de ruptura. 417 00:32:31,020 --> 00:32:35,450 Así, a execución do programa, será executado e logo vai bater a función principal e deixar de funcionar. 418 00:32:35,450 --> 00:32:44,700 Agora estamos dentro da principal, e paso ou a próxima vai traer-nos para a próxima liña de código. 419 00:32:44,700 --> 00:32:47,050 Podes facer a paso ou o próximo. 420 00:32:47,050 --> 00:32:51,800 Bater seguinte, agora eu fose definido para Rand () do 3%, de modo que pode imprimir o valor de i, 421 00:32:51,800 --> 00:32:55,280 e el vai dicir que eu é 1. 422 00:32:55,280 --> 00:32:58,110 Agora, non importa se usan preto ou paso. 423 00:32:58,110 --> 00:33:01,000 Eu creo que importaba o anterior, pero quere usar a continuación. 424 00:33:01,000 --> 00:33:06,000 Se usarmos paso, paso para a función, o que significa ollar para a cousa real 425 00:33:06,000 --> 00:33:07,940 que está a suceder dentro binky. 426 00:33:07,940 --> 00:33:10,510 Se usarmos seguinte, entón isto significa pasar por riba da función 427 00:33:10,510 --> 00:33:14,070 e vaia á seguinte liña de código na nosa función principal. 428 00:33:14,070 --> 00:33:17,900 Aquí nesta liña, eu estaba onde dixo Rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 se eu paso, ía para a implementación de rand 430 00:33:21,320 --> 00:33:25,110 e ollar para o que está a suceder alí, e eu podería pisar a través da función rand. 431 00:33:25,110 --> 00:33:26,920 Pero eu non me importa a función rand. 432 00:33:26,920 --> 00:33:30,190 Eu só quero ir á seguinte liña de código na principal, entón eu uso seguinte. 433 00:33:30,190 --> 00:33:35,800 Pero agora eu me importa a función binky, así que quero entrar niso. 434 00:33:35,800 --> 00:33:37,730 Agora estou en binky. 435 00:33:37,730 --> 00:33:42,040 A primeira liña de código que vai dicir se (i == 0), dou un paso, 436 00:33:42,040 --> 00:33:44,930 vemos que acabar en Dinky. 437 00:33:44,930 --> 00:33:51,620 Se as cousas nos da lista, vemos que é marcada i = 0. 438 00:33:51,620 --> 00:33:55,470 i non é igual a 0, de modo que foi a condición máis, 439 00:33:55,470 --> 00:33:59,540 que vai chamar Dinky (i). 440 00:33:59,540 --> 00:34:04,030 Pode ficar confuso. 441 00:34:04,030 --> 00:34:07,380 Se só ollar para estas liñas directamente, pode pensar que se (i == 0), 442 00:34:07,380 --> 00:34:10,800 ok, entón eu dei un paso e agora estou en Dinky (i), 443 00:34:10,800 --> 00:34:14,120 pode pensar que debe significar i = 0 ou algo así. 444 00:34:14,120 --> 00:34:18,980 Non Significa só que el sabe que pode ir directamente ao Dinky liña (i). 445 00:34:18,980 --> 00:34:23,300 Porque eu non for 0, o seguinte paso non vai rematar no outro. 446 00:34:23,300 --> 00:34:26,239 Else non é unha liña que vai parar. 447 00:34:26,239 --> 00:34:31,570 É só pasar para ir á seguinte liña realmente pode facer, o que é atractivo (i). 448 00:34:31,570 --> 00:34:36,090 Entrando Dinky (i), imos ver se (i == 1). 449 00:34:36,090 --> 00:34:42,670 Sabemos i = 1, entón cando paso, sabemos que imos terminar en oh_no 450 00:34:42,670 --> 00:34:46,489 porque i = 1 chámase o oh_no función, que pode entrar, 451 00:34:46,489 --> 00:34:52,969 que vai definir char ** s = a NULL e inmediatamente "boom". 452 00:34:54,270 --> 00:34:59,690 E entón, en realidade, ollando para a implementación de buggy2, 453 00:34:59,690 --> 00:35:04,590 iso, eu só está obtendo un número aleatorio - 0, 1 ou 2 - chamado binky, 454 00:35:04,590 --> 00:35:10,610 que se eu for 0 ela chama oh_no, senón el chama Dinky, que vén ata aquí. 455 00:35:10,610 --> 00:35:18,100 Se eu fose 1, chamada oh_no, senón chamar slinky, que chegando aquí, 456 00:35:18,100 --> 00:35:20,460 i é 2, chame oh_no. 457 00:35:20,460 --> 00:35:24,720 Eu nin creo que hai un camiño - 458 00:35:24,720 --> 00:35:30,030 Alguén ve unha forma de facelo dun programa que non vai segfault? 459 00:35:30,030 --> 00:35:37,530 Porque a menos que eu estou falta algo, se for 0, vostede inmediatamente segfault, 460 00:35:37,530 --> 00:35:41,250 outra cousa que ir a unha función que se i é un que segfault, 461 00:35:41,250 --> 00:35:44,540 outra cousa que ir a unha función onde se i é 2, segfault. 462 00:35:44,540 --> 00:35:46,810 Polo tanto, non importa o que fai, ten segfault. 463 00:35:46,810 --> 00:35:52,380 >> Eu creo que unha forma de resolve-lo sería en vez de facer char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 podería malloc espazo para esa cadea. 465 00:35:55,610 --> 00:36:04,230 Nós poderiamos facer malloc (sizeof) - sizeof o que? 466 00:36:09,910 --> 00:36:15,190 [Alumno] (char) * 5? >> Isto parece certo? 467 00:36:15,190 --> 00:36:21,060 Estou supoñendo que iso vai funcionar se eu realmente el foi, pero non é o que eu estou buscando. 468 00:36:24,400 --> 00:36:32,940 Olle para o tipo de s. Imos engadir * int, entón int * x. 469 00:36:32,940 --> 00:36:35,600 Eu faría malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Ou se eu quería un conxunto de cinco, eu faría (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 E se eu tivera un ** int? 472 00:36:46,260 --> 00:36:49,140 O que eu malloc? 473 00:36:49,140 --> 00:36:53,510 [Estudante] Tamaño do punteiro. Si >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 A mesma cousa aquí. 475 00:36:56,960 --> 00:37:01,280 Eu quero (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Isto vai reservar espacio para o punteiro que apunta a "boom". 477 00:37:12,840 --> 00:37:15,330 Eu non teño reservar espacio para "boom" en si 478 00:37:15,330 --> 00:37:17,210 porque este é basicamente equivalente ao que eu dixen antes 479 00:37:17,210 --> 00:37:20,870 de char * x = "boom". 480 00:37:20,870 --> 00:37:27,950 "Boom" xa existe. Acontece que hai na rexión de lectura de memoria. 481 00:37:27,950 --> 00:37:35,200 Pero xa existe, o que significa que esta liña de código, se s é un char **, 482 00:37:35,200 --> 00:37:43,900 entón * s é un char * e está definindo este char * para apuntar para "boom". 483 00:37:43,900 --> 00:37:50,040 Se eu quería copiar "boom" en s, entón eu tería que reservar espazo para s. 484 00:37:55,170 --> 00:38:03,900 Vou facer * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Por 5? 486 00:38:06,210 --> 00:38:10,860 Por que non catro? Parece que o "boom" é de 4 caracteres. >> [Alumno] O personaxe nulo. 487 00:38:10,860 --> 00:38:14,580 Si Todas as cordas van precisar o carácter nulo. 488 00:38:14,580 --> 00:38:23,590 Agora podo facer algo como strcat - Cal é a función para copiar a cadea? 489 00:38:23,590 --> 00:38:28,520 [Alumno] cpy? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 strcpy home. 491 00:38:36,120 --> 00:38:39,590 Entón strcpy ou strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy é un pouco máis seguro, pois pode especificar exactamente cantos caracteres 493 00:38:43,410 --> 00:38:46,190 pero aquí non importa, porque sabemos. 494 00:38:46,190 --> 00:38:50,340 Entón strcpy e ollar nos argumentos. 495 00:38:50,340 --> 00:38:53,100 O primeiro argumento é o noso destino. 496 00:38:53,100 --> 00:38:56,770 O segundo argumento é a nosa fonte. 497 00:38:56,770 --> 00:39:10,310 Imos copiar para o noso destino * é o punteiro "boom". 498 00:39:10,310 --> 00:39:19,820 Por que quere facelo cun strcpy en vez de só o que tiñamos antes 499 00:39:19,820 --> 00:39:22,800 de * s = "boom"? 500 00:39:22,800 --> 00:39:28,630 Hai unha razón para que pode querer facelo, pero o que é iso? 501 00:39:28,630 --> 00:39:31,940 [Estudante] Se quere cambiar algo en "boom". Si >>. 502 00:39:31,940 --> 00:39:37,950 Agora podo facer algo como s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 porque os puntos s para a pila e que o espazo na pila que está a apuntar cara s 504 00:39:48,190 --> 00:39:52,320 é un punteiro para máis espazo na pila, que está almacenando "boom". 505 00:39:52,320 --> 00:39:55,150 Polo tanto, este exemplar de "boom" está sendo almacenado na pila. 506 00:39:55,150 --> 00:39:58,780 Hai técnicamente dúas copias do "boom" no noso programa. 507 00:39:58,780 --> 00:40:03,500 Non é o primeiro que é só dada por esta constante cadea "boom", 508 00:40:03,500 --> 00:40:09,250 ea segunda copia de "boom", strcpy creou a copia de "boom". 509 00:40:09,250 --> 00:40:13,100 Pero a copia de "boom" está sendo almacenado na pila, eo heap está libre de cambiar. 510 00:40:13,100 --> 00:40:17,250 A pila non é só de lectura, o que significa que s [0] 511 00:40:17,250 --> 00:40:20,500 vai deixar que cambiar o valor de "boom". 512 00:40:20,500 --> 00:40:23,130 Vai deixar lo pasar eses personaxes. 513 00:40:23,130 --> 00:40:26,640 >> Preguntas? 514 00:40:27,740 --> 00:40:29,290 Okay. 515 00:40:29,290 --> 00:40:35,500 >> Pasando para buggy3, gdb imos buggy3. 516 00:40:35,500 --> 00:40:39,840 Nós só executa-lo e vemos temos un segfault. 517 00:40:39,840 --> 00:40:46,550 Se backtrace, hai só dúas funcións. 518 00:40:46,550 --> 00:40:52,970 Subir na nosa función principal, vemos que segfaulted nesta liña. 519 00:40:52,970 --> 00:41:00,180 Entón, só de ollar para esta liña, é (int liña = 0; fgets este material fai NULL non é igual; 520 00:41:00,180 --> 00:41:03,770 liña + +). 521 00:41:03,770 --> 00:41:08,010 O noso cadro anterior foi chamado _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Vai ver que unha morea de funcións built-in C, 523 00:41:10,720 --> 00:41:15,350 que cando comeza a segfault, haberá nomes de funcións realmente enigmáticas 524 00:41:15,350 --> 00:41:18,090 como este _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Pero que vai relacionarse con esta chamada fgets. 526 00:41:21,770 --> 00:41:25,850 En algún lugar aquí dentro, estamos segmento estándar. 527 00:41:25,850 --> 00:41:30,340 Se olharmos para os argumentos para fgets, podemos imprimir buffer. 528 00:41:30,340 --> 00:41:41,180 Imos imprimir como un - Oh, non. 529 00:41:48,980 --> 00:41:51,900 Impresión non vai funcionar exactamente como quero que el. 530 00:41:55,460 --> 00:41:58,000 Imos ollar para o programa real. 531 00:42:02,200 --> 00:42:09,640 Buffer é unha matriz de caracteres. É unha matriz de caracteres de 128 caracteres. 532 00:42:09,640 --> 00:42:14,980 Polo tanto, cando digo buffer de impresión, que vai imprimir os 128 caracteres, 533 00:42:14,980 --> 00:42:18,300 Eu creo que é o que se espera. 534 00:42:18,300 --> 00:42:21,390 O que eu estaba a buscar e imprimir o enderezo do buffer, 535 00:42:21,390 --> 00:42:23,680 pero que realmente non me di moito. 536 00:42:23,680 --> 00:42:30,770 Entón, cando ocorrer de eu dicir aquí tapón x, el me amosa 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 que, se lembrar de máis cedo ou nalgún punto, Oxbffff tende a ser unha rexión pila-ISH. 538 00:42:38,690 --> 00:42:46,020 A pila tende a comezar en algún lugar só baixo 0xC000. 539 00:42:46,020 --> 00:42:51,890 Só de ver ese enderezo, sei que o buffer está a suceder na pila. 540 00:42:51,890 --> 00:43:04,500 Reiniciar o meu programa, executado, para arriba, o buffer que vimos foi esa secuencia de caracteres 541 00:43:04,500 --> 00:43:06,530 que son moito sentido. 542 00:43:06,530 --> 00:43:12,270 A continuación, imprimir arquivos, o que arquivo se parece? 543 00:43:15,120 --> 00:43:17,310 [Alumno] nulo. Si >>. 544 00:43:17,310 --> 00:43:22,610 Arquivo é un tipo FILE *, por iso é un punteiro, 545 00:43:22,610 --> 00:43:26,610 e o valor punteiro que é nula. 546 00:43:26,610 --> 00:43:33,240 Entón fgets vai ler que o punteiro de forma indirecta, 547 00:43:33,240 --> 00:43:37,320 mais, para acceder a este punteiro, ten que dereference-lo. 548 00:43:37,320 --> 00:43:40,550 Ou, para acceder ao que debe estar apuntando para el dereferences el. 549 00:43:40,550 --> 00:43:43,810 Entón é dereferencing un punteiro nulo e segfaults. 550 00:43:46,600 --> 00:43:48,730 Eu podería ter reiniciar alí. 551 00:43:48,730 --> 00:43:52,170 Se romper o noso punto principal e executar, 552 00:43:52,170 --> 00:43:57,320 a primeira liña de código char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Isto debe dar unha información moi grande respecto a porque este programa falla. 554 00:44:00,870 --> 00:44:06,080 Escribindo próxima trae-me á seguinte liña, onde abrir este ficheiro, 555 00:44:06,080 --> 00:44:11,140 e entón eu inmediatamente entrar na nosa liña, onde unha vez eu bati seguinte, que vai segfault. 556 00:44:11,140 --> 00:44:16,880 Alguén quere tirar unha razón pola cal se pode segmento defecto? 557 00:44:16,880 --> 00:44:19,130 [Alumno] O ficheiro non existe. Si >>. 558 00:44:19,130 --> 00:44:22,250 Isto é suposta ser unha información 559 00:44:22,250 --> 00:44:29,570 que sempre que está abrindo un arquivo que precisa para comprobar se o ficheiro realmente existe. 560 00:44:29,570 --> 00:44:31,510 Entón, aquí, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Cando nome fopen para lectura, entón necesitamos dicir 562 00:44:34,700 --> 00:44:45,870 if (arquivo == NULL) e dicir printf ("O ficheiro non existe!" 563 00:44:45,870 --> 00:44:56,340 ou - mellor aínda - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Entón agora imos comprobar para ver se é NULL 565 00:45:00,300 --> 00:45:03,930 antes de realmente seguir e intentar ler a partir dese arquivo. 566 00:45:03,930 --> 00:45:08,800 Podemos refacelo lo só para ver o que funciona. 567 00:45:11,020 --> 00:45:14,970 Eu pretendía incluír unha nova liña. 568 00:45:21,090 --> 00:45:25,290 Entón agora nonexistent.txt non existe. 569 00:45:26,890 --> 00:45:30,040 Ten que sempre comprobar se hai este tipo de cousas. 570 00:45:30,040 --> 00:45:33,870 Ten que sempre comprobar fopen retorna NULL. 571 00:45:33,870 --> 00:45:38,170 Ten que sempre comprobar para asegurarse de que malloc non retorna NULL, 572 00:45:38,170 --> 00:45:41,410 ou ben segfault. 573 00:45:42,200 --> 00:45:45,930 >> Agora buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Execución. Estou descubrindo que está á espera para entrada ou looping posiblemente infinito. 575 00:45:58,440 --> 00:46:01,870 Si, é looping infinito. 576 00:46:01,870 --> 00:46:05,560 Entón buggy4. Parece que estamos en loop infinito. 577 00:46:05,560 --> 00:46:12,590 Podemos romper a principal, executar o noso programa. 578 00:46:12,590 --> 00:46:20,180 En gdb, mentres a abreviatura empregada é inequívoca 579 00:46:20,180 --> 00:46:23,420 ou abreviações especiais que fornecen para ti, 580 00:46:23,420 --> 00:46:29,020 entón podes usar n empregar esta en vez de ter que escribir lado todo o camiño. 581 00:46:29,020 --> 00:46:33,730 E agora que eu bati n unha vez, podo só prema Intro para continuar próximo 582 00:46:33,730 --> 00:46:36,640 en vez de ter que bater n Intro, n Intro, n Intro. 583 00:46:36,640 --> 00:46:44,630 Parece que eu estou en algún tipo de loop que está asentado matriz [i] a 0. 584 00:46:44,630 --> 00:46:50,510 Parece que eu non estou saír deste bucle. 585 00:46:50,510 --> 00:46:54,780 Se eu imprimir i, entón eu é 2, entón eu vou ir. 586 00:46:54,780 --> 00:46:59,250 Vou imprimir i, i é 3, entón eu vou ir. 587 00:46:59,250 --> 00:47:05,360 Vou imprimir i e i é 3. A continuación, imprimir i, i é 4. 588 00:47:05,360 --> 00:47:14,520 En realidade, a impresión sizeof (array), así o tamaño da matriz é 20. 589 00:47:16,310 --> 00:47:32,870 Pero parece que hai algún comando gdb especial para ir ata que algo acontece. 590 00:47:32,870 --> 00:47:37,620 É como definindo unha condición de que o valor da variable. Pero eu non me lembro o que é. 591 00:47:37,620 --> 00:47:44,100 Entón, se nós seguir - 592 00:47:44,100 --> 00:47:47,120 O que estaba dicindo? O que trae? 593 00:47:47,120 --> 00:47:50,500 [Alumno] non ver eu engadir - >> Yeah. Entón amosar podo axudar. 594 00:47:50,500 --> 00:47:54,530 Se só amosar i, que vai poñer-se aquí que o valor de i é 595 00:47:54,530 --> 00:47:56,470 entón eu non teño que imprimir lo cada vez. 596 00:47:56,470 --> 00:48:02,930 Se só vai manter próximo, vemos 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 Algo está terriblemente mal, e eu está a ser reposto a 0. 598 00:48:13,330 --> 00:48:22,220 Mirando buggy4.c vemos todo o que pasa é matriz int [5]; 599 00:48:22,220 --> 00:48:26,200 é (i = 0; i <= sizeof (array); i + +) 600 00:48:26,200 --> 00:48:28,550 array [i] = 0; 601 00:48:28,550 --> 00:48:31,390 O que vemos que está mal aquí? 602 00:48:31,390 --> 00:48:39,480 Como unha información, cando estaba facendo o gdb buggy4 - imos romper principal, run - 603 00:48:39,480 --> 00:48:45,980 Eu tiña impresión sizeof (array) só para ver o que a condición é onde eu debería finalmente saír. 604 00:48:47,690 --> 00:48:51,100 Onde estou? Será que eu corro? 605 00:48:51,100 --> 00:48:54,280 Eu non declarou aínda. 606 00:48:54,280 --> 00:48:58,680 Así imprimir sizeof (matriz) e que é 20, 607 00:48:58,680 --> 00:49:06,690 que é esperado dende a miña matriz é de tamaño 5 e é de 5 números enteiros, 608 00:49:06,690 --> 00:49:12,410 así que a cousa toda debe ser de 5 * sizeof (int) bytes, onde sizeof (int) tende a ser 4. 609 00:49:12,410 --> 00:49:14,780 Entón, sizeof (array) é 20. 610 00:49:14,780 --> 00:49:17,420 O que debe ser iso? 611 00:49:17,420 --> 00:49:21,720 [Alumno] dividido por sizeof (int). >> Si, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Parece que aínda hai un problema aquí. Eu creo que iso debe ser só < 613 00:49:30,630 --> 00:49:36,960 xa que é practicamente sempre 00:49:44,860 Agora imos pensar sobre por que isto foi realmente dobres. 615 00:49:44,860 --> 00:49:53,370 Alguén ten palpites por que eu axustar a 0 en cada iteração do loop? 616 00:50:01,300 --> 00:50:09,350 A única cousa aquí dentro que está a suceder é que a matriz [i] está definida como 0. 617 00:50:09,350 --> 00:50:15,350 Entón, dalgunha forma, esta liña de código está causando a nosa int i a ser definido para 0. 618 00:50:16,730 --> 00:50:23,130 [Alumno] Podería ser porque está substituíndo a memoria desa parte do i 619 00:50:23,130 --> 00:50:27,970 cando se pensa que é o seguinte elemento da matriz? >> [Bowden] Si 620 00:50:27,970 --> 00:50:33,880 Cando imos máis aló do final da nosa matriz, 621 00:50:33,880 --> 00:50:39,870 espazo que de algunha maneira que estamos substituíndo está substituíndo o valor de i. 622 00:50:39,870 --> 00:50:48,030 E así, se olharmos para buggy4, romper carreira, principal, 623 00:50:48,030 --> 00:50:53,120 imos imprimir o enderezo de i. 624 00:50:53,120 --> 00:50:57,280 Parece que é bffff124. 625 00:50:57,280 --> 00:51:03,930 Agora imos imprimir o enderezo do array [0]. 110. 626 00:51:03,930 --> 00:51:06,290 E sobre [1]? 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11c, 120. array [5] é bfff124. 629 00:51:14,530 --> 00:51:26,990 Entón matriz [5] ten o mesmo enderezo como eu, o que significa que a matriz [5] é i. 630 00:51:26,990 --> 00:51:30,720 Se eles teñen o mesmo enderezo, son a mesma cousa. 631 00:51:30,720 --> 00:51:38,410 Entón, cando imos definir matriz [5] a 0, estamos establecendo i a 0. 632 00:51:38,410 --> 00:51:46,070 E se pensar sobre iso en termos de pila, 633 00:51:46,070 --> 00:51:55,590 int i é declarada primeiro, o que significa que está un pouco de espazo na pila. 634 00:51:55,590 --> 00:52:04,730 Entón matriz [5] é asignado, polo que 20 bytes son alocados na pila. 635 00:52:04,730 --> 00:52:08,400 Entón eu é alocada en primeiro lugar, a continuación, eses 20 bytes estar asignado. 636 00:52:08,400 --> 00:52:11,400 Entón eu acontece antes de matriz, 637 00:52:11,400 --> 00:52:19,230 e por mor da forma como eu dixen a semana pasada, cando técnicamente a pila crece cara abaixo, 638 00:52:19,230 --> 00:52:28,520 cando o índice de ti nunha matriz, temos a garantía de que a posición 0 na matriz 639 00:52:28,520 --> 00:52:31,970 sempre acontece antes da primeira posición na matriz. 640 00:52:31,970 --> 00:52:35,900 Este é o tipo de como eu deseño a semana pasada. 641 00:52:35,900 --> 00:52:42,210 Teña en conta que no fondo temos o enderezo 0 e na parte superior temos Max enderezo. 642 00:52:42,210 --> 00:52:44,880 A pila está sempre crecendo cara a abaixo. 643 00:52:48,100 --> 00:52:53,500 Imos dicir que reservar i. 644 00:52:53,500 --> 00:52:59,680 Alocamos enteiro i, o que significa que imos só dicir que ata aquí enteiro i é alocada. 645 00:52:59,680 --> 00:53:06,420 A continuación, alocamos noso array de 5 enteiros, o que significa que, por baixo que, 646 00:53:06,420 --> 00:53:11,230 Visto que a pila está crecendo para abaixo, eses cinco enteiros quedan alocados. 647 00:53:11,230 --> 00:53:15,900 Pero por mor de como matrices funciona, está garantido que a primeira posición na matriz 648 00:53:15,900 --> 00:53:22,260 sempre ten un enderezo de menos que o segundo aspecto da matriz. 649 00:53:22,260 --> 00:53:28,270 Así posición 0 matriz sempre ten que ocorrer primeiro na memoria, 650 00:53:28,270 --> 00:53:30,700 Considerando que a posición matriz 1 ten que acontecer despois diso 651 00:53:30,700 --> 00:53:33,310 e posición da matriz 2 ten que acontecer despois diso, 652 00:53:33,310 --> 00:53:37,900 o que significa que a posición 0 matriz ía ocorrer en algún lugar aquí, 653 00:53:37,900 --> 00:53:40,690 posición matriz 1 que acontecería arriba que 654 00:53:40,690 --> 00:53:45,530 porque mover-se significa enderezos máis altos desde que a dirección máxima é aquí. 655 00:53:45,530 --> 00:53:50,490 Entón array [0] aquí, array [1] ata aquí, array [2] ata aquí, matriz [3] ata aquí. 656 00:53:50,490 --> 00:53:55,620 Observe como antes alocados enteiro i todo o camiño ata aquí, 657 00:53:55,620 --> 00:54:01,040 a medida que avanzamos cada vez máis na nosa matriz, estamos chegando máis preto e máis preto do noso enteiro i. 658 00:54:01,040 --> 00:54:07,640 O que pasa é que a matriz [5], que é unha posición máis alá da nosa matriz, 659 00:54:07,640 --> 00:54:13,010 é exactamente onde enteiro i pasou a ser alocado. 660 00:54:13,010 --> 00:54:16,920 Entón ese é o momento en que se celebrará a bater o espazo na pila 661 00:54:16,920 --> 00:54:21,680 que foi alocada para o enteiro i, e estamos definindo que a 0. 662 00:54:21,680 --> 00:54:26,160 >> É así que funciona. Preguntas? Si 663 00:54:26,160 --> 00:54:30,710 [Alumno] non importa. Okay. 664 00:54:30,710 --> 00:54:33,090 [Alumno] Como evitar este tipo de erros? 665 00:54:33,090 --> 00:54:41,190 Estes tipos de erros? Non use C como linguaxe de programación. 666 00:54:41,190 --> 00:54:45,840 Usar a linguaxe que ten límites de matriz de verificación. 667 00:54:45,840 --> 00:54:55,900 Mentres está atento, só precisa evitar ir alén dos límites da súa matriz. 668 00:54:55,900 --> 00:54:58,300 [Alumno] Entón aquí cando fomos pasado dos límites da súa matriz - 669 00:54:58,300 --> 00:55:01,840 [Bowden] É aí onde as cousas comezan a dar mal. >> [Alumno] Ah, ok. 670 00:55:01,840 --> 00:55:05,730 Mentres lle queda dentro da memoria alocada para a matriz, está ben. 671 00:55:05,730 --> 00:55:12,400 Pero C non fai comprobación de erros. Se eu fai matriz [1000], é de bo grado só modificar o que pasa - 672 00:55:12,400 --> 00:55:16,500 Vai para o inicio da matriz, entón vai posicións 1000 e despois defínese como 0. 673 00:55:16,500 --> 00:55:20,000 Non fai ningunha verificación de que ah, iso non ten realmente mil cousas nel. 674 00:55:20,000 --> 00:55:22,750 1000 é moito máis do que eu debería estar cambiando, 675 00:55:22,750 --> 00:55:26,940 mentres Java ou algo que vai ter matriz de índice límites 676 00:55:26,940 --> 00:55:29,820 ou índice de excepción límites. 677 00:55:29,820 --> 00:55:33,950 É por iso que unha morea de linguaxes de alto nivel ten esas cousas 678 00:55:33,950 --> 00:55:37,340 onde se ir alén dos límites da matriz, non 679 00:55:37,340 --> 00:55:40,070 para que non pode cambiar as cousas de baixo de ti 680 00:55:40,070 --> 00:55:42,590 e despois as cousas van moito peor do que só comezando unha excepción 681 00:55:42,590 --> 00:55:44,940 dicindo que foi alén do fin da matriz. 682 00:55:44,940 --> 00:55:50,970 [Alumno] E así teriamos só cambiou o <= só > [Bowden] Yeah. 683 00:55:50,970 --> 00:55:54,800 Debe ser 00:55:59,560 desde sizeof (array) é de 20, pero só queremos 5. >> [Alumno] Dereito. 685 00:55:59,560 --> 00:56:04,060 Máis preguntas? Okay. 686 00:56:04,060 --> 00:56:07,380 >> [Estudante] Eu teño unha pregunta. Si >>. 687 00:56:07,380 --> 00:56:16,440 [Alumno] Cal é a variable matriz real? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Como o que é matriz? 689 00:56:20,000 --> 00:56:24,930 Array en si é un símbolo. 690 00:56:24,930 --> 00:56:31,490 É só o enderezo do inicio dos 20 bytes que fan referencia. 691 00:56:31,490 --> 00:56:38,070 Podes pensar niso como un punteiro, pero é un punteiro constante. 692 00:56:38,070 --> 00:56:44,140 Así que as cousas son compilados, a matriz variable non existe máis. 693 00:56:44,140 --> 00:56:48,210 [Alumno] Entón como é que atopar o tamaño da matriz? 694 00:56:48,210 --> 00:56:54,130 Tamaño da matriz refírese ao tamaño do bloque, que se refire a ese símbolo. 695 00:56:54,130 --> 00:57:01,240 Cando fago algo así como printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 imos executalo. 697 00:57:12,960 --> 00:57:15,530 O que eu acaba de malo? 698 00:57:15,530 --> 00:57:19,220 'Matriz' matriz declarada aquí. 699 00:57:20,820 --> 00:57:23,200 Ah, aquí enriba. 700 00:57:23,200 --> 00:57:31,250 Clang é intelixente, e iso pasa a entender que eu declarei a matriz como 5 elementos 701 00:57:31,250 --> 00:57:34,540 pero eu estou a indexación na posición 1000. 702 00:57:34,540 --> 00:57:38,450 Pode facelo porque estes son só constantes. 703 00:57:38,450 --> 00:57:43,370 E só pode ir tan lonxe en conta que eu estou indo alén dos límites da matriz. 704 00:57:43,370 --> 00:57:46,880 Pero aviso antes, cando tivemos i ser incorrecta, 705 00:57:46,880 --> 00:57:51,040 ela non pode determinar cantos valores eu podería asumir, 706 00:57:51,040 --> 00:57:55,540 por iso non pode determinar que eu estaba indo para alén do fin da matriz. 707 00:57:55,540 --> 00:57:59,430 Isto é só Clang ser intelixente. 708 00:57:59,430 --> 00:58:03,340 >> Pero agora facer buggy4. Entón o que máis estou facendo de malo? 709 00:58:03,340 --> 00:58:05,970 Implicitamente declarando función de biblioteca 'printf ". 710 00:58:05,970 --> 00:58:14,960 Vou querer # include. 711 00:58:14,960 --> 00:58:18,710 Okay. Agora correndo buggy4. 712 00:58:18,710 --> 00:58:24,840 Imprimir o valor da matriz, como eu fixen aquí, imprimir lo como un punteiro 713 00:58:24,840 --> 00:58:30,060 impresións algo que se parece iso - bfb8805c - que é un enderezo 714 00:58:30,060 --> 00:58:33,450 que é na rexión pila-ISH. 715 00:58:33,450 --> 00:58:41,820 Matriz en si é como un punteiro, pero non é un indicador real, 716 00:58:41,820 --> 00:58:45,410 Unha vez que un punteiro normal podemos cambiar. 717 00:58:45,410 --> 00:58:54,700 Matriz é só unha constante. Os 20 bloques de memoria comezan en 0xbfb8805c enderezo. 718 00:58:54,700 --> 00:59:09,020 Entón bfb8805c través deste enderezo +20- ou eu creo -20 - 719 00:59:09,020 --> 00:59:17,400 é toda a memoria alocada para esa matriz. 720 00:59:17,400 --> 00:59:20,350 Matriz, a variable en si non é almacenada en calquera lugar. 721 00:59:20,350 --> 00:59:27,660 Cando está compilando, o compilador - aceno de man para el - 722 00:59:27,660 --> 00:59:33,060 pero o compilador só vai usar sabe onde arranxo a ser. 723 00:59:33,060 --> 00:59:36,090 El sabe onde comeza esta matriz, 724 00:59:36,090 --> 00:59:40,910 e así pode sempre facer as cousas en termos de compensacións que comezo. 725 00:59:40,910 --> 00:59:43,960 Ela non precisa dunha variable en si para representar matriz. 726 00:59:43,960 --> 00:59:53,730 Pero cando fago algo así como int * p = array; agora p é un punteiro que apunta a esta matriz, 727 00:59:53,730 --> 00:59:57,830 e agora p realmente existe na pila. 728 00:59:57,830 --> 01:00:01,950 Eu son libre para cambiar p. Eu podo facer p = malloc. 729 01:00:01,950 --> 01:00:06,500 Por iso, inicialmente vinculado matriz, agora apunta a un espazo na pila. 730 01:00:06,500 --> 01:00:09,620 Eu non podo facer malloc = array. 731 01:00:09,620 --> 01:00:13,710 Se Clang é intelixente, vai berrar comigo pronto de cara. 732 01:00:17,000 --> 01:00:21,430 En realidade, eu estou seguro que gcc faría iso tamén. 733 01:00:21,430 --> 01:00:25,010 Así, o tipo de matriz 'int [5]' non é transferible. 734 01:00:25,010 --> 01:00:28,040 Vostede non pode asignar algo a un tipo de matriz 735 01:00:28,040 --> 01:00:30,500 porque matriz é só unha constante. 736 01:00:30,500 --> 01:00:34,760 É un símbolo que fai referencia a eses 20 bytes. Eu non podo cambiar isto. 737 01:00:34,760 --> 01:00:37,690 >> [Alumno] E onde está o tamaño da matriz almacenada? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Non é almacenada en calquera lugar. É cando está compilando. 739 01:00:40,670 --> 01:00:46,310 Entón, onde está o tamaño da matriz almacenada? 740 01:00:46,310 --> 01:00:51,870 Só se pode usar sizeof (matriz) dentro da función que a matriz é declarada en si. 741 01:00:51,870 --> 01:01:03,150 Entón, se eu fai algunha función, foo, e fago (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 e aquí eu chamo de foo (matriz); 744 01:01:21,330 --> 01:01:24,840 dentro desta función - imos executalo. 745 01:01:34,200 --> 01:01:36,840 Este é Clang ser intelixente de novo. 746 01:01:36,840 --> 01:01:43,890 Está me dicindo que sizeof no parámetro función de matriz 747 01:01:43,890 --> 01:01:46,690 volverá tamaño de 'int *'. 748 01:01:46,690 --> 01:01:55,150 Iso sería un erro, se non é o que eu quería que acontecese. 749 01:01:55,150 --> 01:01:58,960 Imos realmente desactivar Werror. 750 01:02:14,950 --> 01:02:17,590 Aviso. Avisos están ben. 751 01:02:17,590 --> 01:02:19,960 É aínda compilará sempre que ten un aviso. 752 01:02:19,960 --> 01:02:22,910 . / A.out vai imprimir 4. 753 01:02:22,910 --> 01:02:28,650 O aviso que foi xerado é un indicador claro de que deu errado. 754 01:02:28,650 --> 01:02:34,120 Esta matriz int só vai imprimir sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Mesmo se eu poñer array [5] aquí, que aínda está indo só para imprimir sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Así, logo que pasar a unha función, a distinción entre matrices e punteiros 757 01:02:47,440 --> 01:02:49,670 é inexistente. 758 01:02:49,670 --> 01:02:52,640 Isto acontece por ser unha matriz que foi declarado na pila, 759 01:02:52,640 --> 01:02:58,300 pero así que pasar ese valor, que 0xbf bla, bla, bla para esta función, 760 01:02:58,300 --> 01:03:03,350 entón este punteiro apunta a que a matriz na pila. 761 01:03:03,350 --> 01:03:08,310 Entón iso significa que sizeof só se aplica en función de que a matriz foi declarada, 762 01:03:08,310 --> 01:03:11,230 o que significa que cando está compilando esta función, 763 01:03:11,230 --> 01:03:17,330 Clang cando pasa por esta función, el ve matriz é un array de int tamaño 5. 764 01:03:17,330 --> 01:03:20,640 Entón ve sizeof (array). Ben, iso é 20. 765 01:03:20,640 --> 01:03:26,440 Isto é realmente como sizeof funciona basicamente para case todos os casos. 766 01:03:26,440 --> 01:03:31,150 Sizeof non é unha función, é un operador. 767 01:03:31,150 --> 01:03:33,570 Non chama a función sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), o compilador só vai traducir isto para 4. 769 01:03:41,480 --> 01:03:43,700 Entendeu? Okay. 770 01:03:43,700 --> 01:03:47,520 >> [Alumno] Entón, cal é a diferenza entre sizeof (array) no inicio e en foo? 771 01:03:47,520 --> 01:03:52,840 Isto é porque nós estamos dicindo sizeof (array), que é do tipo int *, 772 01:03:52,840 --> 01:03:57,120 mentres que a matriz aquí abaixo non é do tipo int *, é unha matriz int. 773 01:03:57,120 --> 01:04:04,540 >> [Alumno] Entón se tivese o parámetro na matriz [] no canto de matriz int *, 774 01:04:04,540 --> 01:04:09,230 que iso significa que aínda pode cambiar matriz porque agora é un punteiro? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Gustoulle? >> [Estudante] Yeah. Pode cambiar matriz dentro da función agora? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Vostede podería cambiar matriz en ambos os casos. 777 01:04:18,420 --> 01:04:23,130 En ambos os casos, vostede é libre para dicir array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Alumno] Pero pode facer punto de matriz para algo máis? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh Si En ambos os casos - >> [estudante] Yeah. 780 01:04:30,230 --> 01:04:38,410 [Bowden] A distinción entre array [] e unha matriz int *, non hai ningunha. 781 01:04:38,410 --> 01:04:42,570 Tamén pode obter algúns matriz multidimensional aquí 782 01:04:42,570 --> 01:04:47,050 por algunha sintaxe cómodo, pero aínda é só un punteiro. 783 01:04:47,050 --> 01:04:56,400 Isto significa que eu son libre para facer o array = malloc (sizeof (int)), e agora apuntan a outro lugar. 784 01:04:56,400 --> 01:04:59,610 Pero, así como a forma en que funciona sempre e sempre, 785 01:04:59,610 --> 01:05:03,210 cambiar esa matriz, tornándose a apuntar cara algo máis 786 01:05:03,210 --> 01:05:07,570 non cambiar esa matriz aquí porque é unha copia do argumento, 787 01:05:07,570 --> 01:05:10,780 non é un punteiro para ese argumento. 788 01:05:10,780 --> 01:05:16,070 E, en realidade, só como unha indicación de que é exactamente o mesmo - 789 01:05:16,070 --> 01:05:21,100 xa vimos o que imprime matriz de impresión - 790 01:05:21,100 --> 01:05:31,410 o que se imprime o enderezo da matriz ou o enderezo do enderezo da matriz 791 01:05:31,410 --> 01:05:36,290 a un deses? 792 01:05:41,770 --> 01:05:45,220 Imos ignorar este. 793 01:05:48,140 --> 01:05:51,660 Okay. Isto é bo. É agora en execución. A.out /. 794 01:05:51,660 --> 01:06:00,220 Matriz de impresión, despois de imprimir o enderezo da matriz, son a mesma cousa. 795 01:06:00,220 --> 01:06:02,870 Matriz simplemente non existe. 796 01:06:02,870 --> 01:06:08,190 Sabe cando está imprimindo matriz, está imprimindo o símbolo que se refire a eses 20 bytes. 797 01:06:08,190 --> 01:06:11,940 Imprimir o enderezo da matriz, así, matriz non existe. 798 01:06:11,940 --> 01:06:17,200 El non ten un enderezo, por iso só amosa o enderezo deses 20 bytes. 799 01:06:20,820 --> 01:06:28,150 Así que compilar para abaixo, como no seu buggy4 compilado. / A.out, 800 01:06:28,150 --> 01:06:30,340 matriz é inexistente. 801 01:06:30,340 --> 01:06:33,640 Punteiros existe. Matrices non. 802 01:06:34,300 --> 01:06:38,060 Os bloques de memoria que representan a matriz aínda existen, 803 01:06:38,060 --> 01:06:43,270 pero a matriz variable e as variables deste tipo non existen. 804 01:06:46,260 --> 01:06:50,270 Aqueles son como as principais diferenzas entre matrices e punteiros 805 01:06:50,270 --> 01:06:55,590 son así que fan chamadas de funcións, non hai diferenza. 806 01:06:55,590 --> 01:07:00,460 Pero dentro da función que a propia matriz é declarada, sizeof funciona de forma diferente 807 01:07:00,460 --> 01:07:05,190 sempre que a impresión é o tamaño dos bloques, en vez de o tamaño do tipo, 808 01:07:05,190 --> 01:07:08,950 e non pode cambiar iso, porque é un símbolo. 809 01:07:08,950 --> 01:07:14,370 Impresión da cousa eo enderezo da cousa imprime a mesma cousa. 810 01:07:14,370 --> 01:07:18,480 E iso é moi bonito iso. 811 01:07:18,480 --> 01:07:20,820 [Alumno] Podería dicirse que unha vez máis? 812 01:07:21,170 --> 01:07:24,170 Eu podería perder algo. 813 01:07:24,170 --> 01:07:29,260 Matriz de impresión e enderezo da matriz imprime o mesmo, 814 01:07:29,260 --> 01:07:33,180 mentres que se imprimir un punteiro en relación ao enderezo do punteiro, 815 01:07:33,180 --> 01:07:36,010 a única cousa que imprime o enderezo do que está apuntando, 816 01:07:36,010 --> 01:07:40,360 o outro imprime o enderezo do punteiro para a pila. 817 01:07:40,360 --> 01:07:47,040 Pode cambiar un punteiro, non pode cambiar un símbolo da matriz. 818 01:07:47,740 --> 01:07:53,270 E punteiro sizeof vai imprimir o tamaño deste tipo de punteiro. 819 01:07:53,270 --> 01:07:57,470 Entón, int * p sizeof (p) vai imprimir 4, 820 01:07:57,470 --> 01:08:04,110 pero int array [5] print sizeof (array) vai imprimir 20. 821 01:08:04,110 --> 01:08:07,480 [Estudante] Entón int array [5] pode imprimir 20? Si >>. 822 01:08:07,480 --> 01:08:13,300 É por iso que dentro buggy4 cando adoitaba ser sizeof (array) 823 01:08:13,300 --> 01:08:16,660 este estaba facendo i <20, que non é o que quería. 824 01:08:16,660 --> 01:08:20,880 Queremos i <5. >> [Alumno] Okay. 825 01:08:20,880 --> 01:08:25,569 [Bowden] E entón, logo que comezar a pasar nas funcións, 826 01:08:25,569 --> 01:08:34,340 se fixemos int * p = array; 827 01:08:34,340 --> 01:08:39,779 dentro desta función, podemos basicamente usar p e matriz en exactamente do mesmo xeito, 828 01:08:39,779 --> 01:08:43,710 agás para o problema e sizeof o problema cambiando. 829 01:08:43,710 --> 01:08:49,810 Pero p [0] = 1; é o mesmo que dicir array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 E así como dicimos foo (matriz), ou foo (p); 831 01:08:55,600 --> 01:08:59,760 dentro da función foo, esta é a mesma chamada dúas veces. 832 01:08:59,760 --> 01:09:03,350 Non hai ningunha diferenza entre estas dúas chamadas. 833 01:09:07,029 --> 01:09:11,080 >> Todos boa sobre isto? Okay. 834 01:09:14,620 --> 01:09:17,950 Temos 10 minutos. 835 01:09:17,950 --> 01:09:28,319 >> Imos tentar obter a través deste programa Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 Nesta web, que saíu o ano pasado ou algo así. 837 01:09:34,149 --> 01:09:41,100 É só debería ser como escribe aleatoriamente e imprime - 838 01:09:41,100 --> 01:09:46,729 Calquera ficheiro que pasa de ter cargado é o que parece que está escribindo. 839 01:09:46,729 --> 01:09:52,069 Parece que algún tipo de código do sistema operativo. 840 01:09:53,760 --> 01:09:56,890 Isto é o que queremos aplicar. 841 01:10:08,560 --> 01:10:11,690 Ten que ter un binario executable chamado hacker_typer 842 01:10:11,690 --> 01:10:14,350 que leva un único argumento, o ficheiro para "tipo de hacker". 843 01:10:14,350 --> 01:10:16,480 Executando o executable que limpar a pantalla 844 01:10:16,480 --> 01:10:20,850 e despois imprimir un personaxe do arquivo pasado en cada vez que o usuario preme unha tecla. 845 01:10:20,850 --> 01:10:24,990 Entón, calquera tecla presionada, debe xogar fora e en vez imprimir un personaxe a partir do arquivo 846 01:10:24,990 --> 01:10:27,810 Que é o argumento. 847 01:10:29,880 --> 01:10:34,350 Vou moi ben dicir o que as cousas que imos ter saber son. 848 01:10:34,350 --> 01:10:36,440 Pero queremos comprobar a biblioteca termios. 849 01:10:36,440 --> 01:10:44,840 Eu nunca usei esta biblioteca en toda a miña vida, polo que ten propósitos moi mínimas. 850 01:10:44,840 --> 01:10:48,610 Pero iso vai ser a biblioteca que podemos usar para xogar fora o personaxe que bateu 851 01:10:48,610 --> 01:10:52,390 cando está escribindo en estándar dentro 852 01:10:56,970 --> 01:11:05,840 Entón hacker_typer.c, e imos querer # include. 853 01:11:05,840 --> 01:11:12,870 Mirando para a páxina man para termios - estou supondo que é terminal de OS ou algo - 854 01:11:12,870 --> 01:11:16,240 Eu non sei como le-lo. 855 01:11:16,240 --> 01:11:21,040 Mirando para iso, di para incluír estes dous arquivos, entón imos facelo. 856 01:11:37,620 --> 01:11:46,820 >> Primeiro de todo, queremos ter un único argumento, que é o ficheiro que debe abrir. 857 01:11:46,820 --> 01:11:52,420 Entón, o que quero facer? Como podo comprobar a ver que eu teño un único argumento? 858 01:11:52,420 --> 01:11:56,480 [Estudante] Se argc é igual a el. >> [Bowden] Yeah. 859 01:11:56,480 --> 01:12:21,250 Entón, se (argc = 2!) Printf ("Uso:% s [arquivo para abrir]"). 860 01:12:21,250 --> 01:12:32,750 Polo tanto, agora eu executar este sen proporcionar un segundo argumento - Oh, eu teño da nova liña - 861 01:12:32,750 --> 01:12:36,240 podes ver que di de uso:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 e, a continuación, o segundo argumento debe ser o ficheiro que quero abrir. 863 01:12:58,430 --> 01:13:01,260 Agora, o que fago? 864 01:13:01,260 --> 01:13:08,490 Eu quero ler a partir deste ficheiro. ¿Como ler un arquivo? 865 01:13:08,490 --> 01:13:11,920 [Alumno] abri-lo primeiro. Si >>. 866 01:13:11,920 --> 01:13:15,010 Entón fopen. O que fopen parece? 867 01:13:15,010 --> 01:13:22,980 [Alumno] Filename. >> [Bowden] Marabillosa vai ser argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Alumno] E entón o que quere facer con ela, entón a - >> [Bowden] Yeah. 869 01:13:26,110 --> 01:13:28,740 Entón, se non se lembra, só podería facerse fopen home, 870 01:13:28,740 --> 01:13:32,960 onde vai ser un camiño const char *, onde camiño é o nome do ficheiro, 871 01:13:32,960 --> 01:13:34,970 modo de const char *. 872 01:13:34,970 --> 01:13:38,660 Se ocorrer de non se lembrar do que forma, entón podes ollar para o modo. 873 01:13:38,660 --> 01:13:44,660 Dentro de páxinas de manual, o carácter de barra é o que pode usar para buscar as cousas. 874 01:13:44,660 --> 01:13:49,790 Entón eu escriba / para a comprobación xeito. 875 01:13:49,790 --> 01:13:57,130 n e N son o que pode usar para percorrer os xogos de busca. 876 01:13:57,130 --> 01:13:59,800 Aquí di que os puntos de modo argumento para unha cadea 877 01:13:59,800 --> 01:14:01,930 comezando con unha das seguintes secuencias. 878 01:14:01,930 --> 01:14:06,480 Entón R, arquivo de texto aberto para lectura. Isto é o que queremos facer. 879 01:14:08,930 --> 01:14:13,210 Para ler, e quero gardar iso. 880 01:14:13,210 --> 01:14:18,720 A cousa vai ser un ficheiro *. Agora o que quero facer? 881 01:14:18,720 --> 01:14:21,200 Déame un segundo. 882 01:14:28,140 --> 01:14:30,430 Okay. Agora o que quero facer? 883 01:14:30,430 --> 01:14:32,940 [Alumno] Comprobar se é NULL. >> [Bowden] Yeah. 884 01:14:32,940 --> 01:14:38,690 Cada vez que abrir un arquivo, asegúrese de que vostede é éxito capaz de abrilo. 885 01:14:58,930 --> 01:15:10,460 >> Agora quero facer isto termios onde quero primeiro ler as miñas opcións actuais 886 01:15:10,460 --> 01:15:14,050 e gardar os en algo, entón eu quero cambiar a miña configuración 887 01:15:14,050 --> 01:15:19,420 tirar calquera personaxe que eu escriba, 888 01:15:19,420 --> 01:15:22,520 e entón eu quero actualizar esas opcións. 889 01:15:22,520 --> 01:15:27,250 E despois, ao final do programa, quero cambiar de volta para as miñas opcións orixinais. 890 01:15:27,250 --> 01:15:32,080 Así, a estrutura vai ser de termios tipo, e eu vou querer dous deles. 891 01:15:32,080 --> 01:15:35,600 O primeiro vai ser o meu current_settings, 892 01:15:35,600 --> 01:15:42,010 e entón eles van ser os meus hacker_settings. 893 01:15:42,010 --> 01:15:48,070 En primeiro lugar, eu vou querer gardar as miñas opcións actuais, 894 01:15:48,070 --> 01:15:53,790 entón eu vou querer actualizar hacker_settings, 895 01:15:53,790 --> 01:16:01,570 e forma, a finais do meu programa, quero voltar a configuración actual. 896 01:16:01,570 --> 01:16:08,660 Entón gardar as configuracións actuais, de xeito que funciona, nós termios home. 897 01:16:08,660 --> 01:16:15,810 Vemos que temos ese tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Eu pasar un struct termios polo seu punteiro. 899 01:16:22,960 --> 01:16:30,640 A forma como iso vai mirar é - eu xa esqueceu o que a función foi chamada. 900 01:16:30,640 --> 01:16:34,930 Copia e pega-o. 901 01:16:39,150 --> 01:16:45,500 Entón tcgetattr, entón eu quero pasar na estrutura que eu estou salvando a información, 902 01:16:45,500 --> 01:16:49,650 que vai ser current_settings, 903 01:16:49,650 --> 01:16:59,120 eo primeiro argumento é o descriptor de ficheiro para a cousa que quero gardar os atributos de. 904 01:16:59,120 --> 01:17:04,360 O que o descriptor de ficheiro é como calquera vez que abrir un arquivo, el recibe un descritor de ficheiro. 905 01:17:04,360 --> 01:17:14,560 Cando fopen argv [1], faise un descritor de ficheiro que está facendo referencia 906 01:17:14,560 --> 01:17:16,730 sempre que quere ler ou escribir para el. 907 01:17:16,730 --> 01:17:19,220 Ese non é o descriptor de ficheiro que quero usar aquí. 908 01:17:19,220 --> 01:17:21,940 Hai tres descritores de ficheiros que ten por defecto, 909 01:17:21,940 --> 01:17:24,310 que son estándar, saída estándar e erro estándar. 910 01:17:24,310 --> 01:17:29,960 Por defecto, eu creo que é estándar en é 0, fóra estándar é 1, e do erro estándar é 2. 911 01:17:29,960 --> 01:17:33,980 Entón, o que quero cambiar a configuración do? 912 01:17:33,980 --> 01:17:37,370 Eu quero cambiar as opcións de cada vez que eu bati un personaxe, 913 01:17:37,370 --> 01:17:41,590 Eu quero que xogue o personaxe fóra en vez de imprimir lo na pantalla. 914 01:17:41,590 --> 01:17:45,960 O fluxo - estándar, saída estándar ou erro estándar - 915 01:17:45,960 --> 01:17:52,050 responde ás cousas cando escribir no teclado? >> [Estudante] Standard dentro >> Yeah. 916 01:17:52,050 --> 01:17:56,450 Entón eu pode facer 0 ou stdin que eu poida facer. 917 01:17:56,450 --> 01:17:59,380 Estou recibindo o current_settings de patrón dentro 918 01:17:59,380 --> 01:18:01,720 >> Agora quero actualizar esas opcións, 919 01:18:01,720 --> 01:18:07,200 Entón, primeiro eu vou copiar hacker_settings que os meus current_settings son. 920 01:18:07,200 --> 01:18:10,430 E como o traballo de estruturas que vai só copia. 921 01:18:10,430 --> 01:18:14,510 Isto copia todos os campos, como sería de esperar. 922 01:18:14,510 --> 01:18:17,410 >> Agora quero actualizar algúns dos campos. 923 01:18:17,410 --> 01:18:21,670 Mirando termios, ten que ler unha morea de presente 924 01:18:21,670 --> 01:18:24,110 só para ver o que quere buscar, 925 01:18:24,110 --> 01:18:28,210 pero as bandeiras que vai querer ollar para son eco, 926 01:18:28,210 --> 01:18:33,110 ECHO para caracteres de entrada de eco. 927 01:18:33,110 --> 01:18:37,710 Primeiro quero definir - eu xa esqueceu o que os campos son. 928 01:18:45,040 --> 01:18:47,900 Isto é o que a estrutura parece. 929 01:18:47,900 --> 01:18:51,060 Así, os modos de entrada penso que queremos cambiar. 930 01:18:51,060 --> 01:18:54,210 Nós imos ollar para a solución para asegurarse de que é o que queremos cambiar. 931 01:19:04,060 --> 01:19:12,610 Queremos cambiar lflag, a fin de evitar a necesidade de ollar a través de todos estes. 932 01:19:12,610 --> 01:19:14,670 Queremos cambiar os modos locais. 933 01:19:14,670 --> 01:19:17,710 Vostede tería que ler esa cousa toda para entender onde todo pertence 934 01:19:17,710 --> 01:19:19,320 que queremos cambiar. 935 01:19:19,320 --> 01:19:24,120 Pero é dentro modos locais onde estamos indo querer cambiar isto. 936 01:19:27,080 --> 01:19:33,110 Entón hacker_settings.cc_lmode é o que se chama. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Isto é onde nós entramos operadores bit a bit. 939 01:19:52,280 --> 01:19:54,860 Somos o tipo de fóra do tempo, pero imos pasar por iso rápido. 940 01:19:54,860 --> 01:19:56,600 Isto é onde nós entramos operadores bit a bit, 941 01:19:56,600 --> 01:19:59,950 onde eu creo que eu dixen un tempo atrás que cando comeza a tratar con bandeiras, 942 01:19:59,950 --> 01:20:03,370 vai estar usando operador bitwise moito. 943 01:20:03,370 --> 01:20:08,240 Cada bit na bandeira representa algún tipo de comportamento. 944 01:20:08,240 --> 01:20:14,090 Entón, aquí, esta bandeira ten unha morea de cousas distintas, onde todos eles significan algo diferente. 945 01:20:14,090 --> 01:20:18,690 Pero o que quero facer é simplemente apagar o pouco que corresponde ao ECHO. 946 01:20:18,690 --> 01:20:25,440 Así, para desactivar iso fago & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 En realidade, eu creo que é como Techo ou algo así. Eu só vou comprobar de novo. 948 01:20:30,110 --> 01:20:34,050 I pode termios lo. É só ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO vai ser un único bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO vai significar todos os bits son definidos a 1, o que significa que todas as bandeiras son definidas como true 951 01:20:44,230 --> 01:20:47,140 excepto para o pouco ECHO. 952 01:20:47,140 --> 01:20:53,830 Ao acabar coas miñas bandeiras locais, con iso, significa que todas as bandeiras que están actualmente establecidos para True 953 01:20:53,830 --> 01:20:56,520 aínda vai ser definido como verdadeiro. 954 01:20:56,520 --> 01:21:03,240 A miña bandeira ECHO é definido como verdadeiro, entón este é necesariamente definida como false na bandeira ECHO. 955 01:21:03,240 --> 01:21:07,170 Entón esta liña de código só desactiva a bandeira ECHO. 956 01:21:07,170 --> 01:21:16,270 As outras liñas de código, vou copialos no interese de tempo e despois explica-las. 957 01:21:27,810 --> 01:21:30,180 Na solución, dixo 0. 958 01:21:30,180 --> 01:21:33,880 Probablemente é mellor dicir explicitamente stdin. 959 01:21:33,880 --> 01:21:42,100 >> Repare que eu tamén estou facendo ECHO | ICANON aquí. 960 01:21:42,100 --> 01:21:46,650 ICANON se refire a algo separado, o que significa para canónico. 961 01:21:46,650 --> 01:21:50,280 O que significa para canónico é xeralmente cando está escribindo a liña de comandos, 962 01:21:50,280 --> 01:21:54,670 estándar en non demandar nada ata que bata nova liña. 963 01:21:54,670 --> 01:21:58,230 Entón, cando GetString, escribe unha morea de cousas, entón acadou nova liña. 964 01:21:58,230 --> 01:22:00,590 É cando el é enviado a norma dentro 965 01:22:00,590 --> 01:22:02,680 Ese é o estándar. 966 01:22:02,680 --> 01:22:05,830 Cando desactivar o modo canónico, agora todos os personaxes só premer 967 01:22:05,830 --> 01:22:10,910 é o que é procesado, que é xeralmente un pouco mal, porque é lento para procesar esas cousas, 968 01:22:10,910 --> 01:22:14,330 é por iso que é bo para o buffer-lo en liñas enteiras. 969 01:22:14,330 --> 01:22:16,810 Pero eu quero que cada personaxe a ser procesado 970 01:22:16,810 --> 01:22:18,810 dende que eu non quero iso para me esperar a bater de nova liña 971 01:22:18,810 --> 01:22:21,280 antes de procesar todos os personaxes que eu estiven escribindo. 972 01:22:21,280 --> 01:22:24,760 Isto transforma o modo canónico. 973 01:22:24,760 --> 01:22:31,320 Este material significa só cando realmente procesa caracteres. 974 01:22:31,320 --> 01:22:35,830 Isto significa proceso-los inmediatamente; así que eu estou escribindo eles, proceso-los. 975 01:22:35,830 --> 01:22:42,510 E esta é a función que está a actualizar as miñas opcións para estándar en, 976 01:22:42,510 --> 01:22:45,480 e medios TCSA facelo agora. 977 01:22:45,480 --> 01:22:50,310 As outras opcións son esperar ata todo o que está actualmente no fluxo é procesado. 978 01:22:50,310 --> 01:22:52,030 Isto realmente non importa. 979 01:22:52,030 --> 01:22:56,920 Só agora cambiar as opcións para ser o que está actualmente en hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Eu creo que o chamou hacker_settings, entón imos cambiar isto. 981 01:23:09,610 --> 01:23:13,500 Cambiar todo para hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Agora a finais do noso programa imos querer desfacer 983 01:23:16,870 --> 01:23:20,210 para o que existe actualmente no interior normal_settings, 984 01:23:20,210 --> 01:23:26,560 que vai só ollar como e normal_settings. 985 01:23:26,560 --> 01:23:30,650 Repare que eu non mudei ningún dos meus normal_settings xa que orixinalmente conseguir. 986 01:23:30,650 --> 01:23:34,520 A continuación, só para muda-los de volta, eu paso-los de volta no final. 987 01:23:34,520 --> 01:23:38,390 Esta foi a actualización. Okay. 988 01:23:38,390 --> 01:23:43,900 >> Agora aquí dentro eu vou explicar o código no interese de tempo. 989 01:23:43,900 --> 01:23:46,350 Non é que moito código. 990 01:23:50,770 --> 01:24:03,750 Vemos, lemos un personaxe a partir do ficheiro. Nós o chamamos f. 991 01:24:03,750 --> 01:24:07,850 Agora podes fgetc home, pero como fgetc vai funcionar 992 01:24:07,850 --> 01:24:11,910 é só que vai voltar o carácter que acaba de ler ou EOF, 993 01:24:11,910 --> 01:24:15,680 que corresponde ao final do ficheiro de algún acontecemento ou de erro. 994 01:24:15,680 --> 01:24:19,900 Estamos looping, continuando a ler un único carácter do ficheiro, 995 01:24:19,900 --> 01:24:22,420 ata que funcionamos fóra de caracteres para ler. 996 01:24:22,420 --> 01:24:26,650 E mentres nós estamos facendo isto, esperamos nun único carácter de estándar dentro 997 01:24:26,650 --> 01:24:29,090 Cada vez que escriba algo na liña de comandos, 998 01:24:29,090 --> 01:24:32,820 que está lendo un personaxe de nivel dentro 999 01:24:32,820 --> 01:24:38,330 Entón putchar só vai poñer o char lemos aquí enriba do ficheiro para a saída estándar. 1000 01:24:38,330 --> 01:24:42,890 Pode putchar home, pero é só poñer na saída estándar, é a impresión que o personaxe. 1001 01:24:42,890 --> 01:24:51,600 Tamén pode só facer printf ("% c", c); mesma idea. 1002 01:24:53,330 --> 01:24:56,670 Isto vai facer a maior parte do noso traballo. 1003 01:24:56,670 --> 01:25:00,300 >> A última cousa que vai querer facer é só fclose noso arquivo. 1004 01:25:00,300 --> 01:25:03,310 Se non fclose, que é un baleirado de memoria. 1005 01:25:03,310 --> 01:25:06,680 Queremos fclose o arquivo que orixinalmente aberto, e eu creo que é iso. 1006 01:25:06,680 --> 01:25:13,810 Se facemos iso, eu xa teño problemas. 1007 01:25:13,810 --> 01:25:17,260 Imos ver. 1008 01:25:17,260 --> 01:25:19,960 O que foi reclamar? 1009 01:25:19,960 --> 01:25:30,220 Esperado 'int' pero o argumento é do tipo 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Imos ver se isto funciona. 1011 01:25:45,210 --> 01:25:53,540 Só permitido C99. Augh. Ok, facer hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Agora temos descricións máis útiles. 1013 01:25:57,760 --> 01:25:59,900 Polo tanto, use de identificador non declarado "normal_settings '. 1014 01:25:59,900 --> 01:26:04,170 Eu non chamalo normal_settings. Chameino current_settings. 1015 01:26:04,170 --> 01:26:12,090 Entón, imos cambiar todo isto. 1016 01:26:17,920 --> 01:26:21,710 Agora pasando argumento. 1017 01:26:26,290 --> 01:26:29,500 Vou facelo 0 por agora. 1018 01:26:29,500 --> 01:26:36,720 Okay. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Eu tamén non limpar a pantalla ao comezo. 1020 01:26:39,590 --> 01:26:42,960 Pero pode ollar cara atrás para o conxunto de problemas última para ver como limpar a pantalla. 1021 01:26:42,960 --> 01:26:45,160 É só imprimir algúns caracteres 1022 01:26:45,160 --> 01:26:47,210 Mentres tanto está facendo o que quero facer. 1023 01:26:47,210 --> 01:26:48,900 Okay. 1024 01:26:48,900 --> 01:26:55,280 E pensar sobre por que isto precisaba ser 0 en vez de stdin, 1025 01:26:55,280 --> 01:27:00,560 que debe ser # define 0, 1026 01:27:00,560 --> 01:27:03,890 este se queixa de que - 1027 01:27:13,150 --> 01:27:19,360 Antes, cando dixo que non hai descritores de ficheiros, pero entón tamén ten o seu FILE *, 1028 01:27:19,360 --> 01:27:23,210 un descritor de ficheiro é só un único número enteiro, 1029 01:27:23,210 --> 01:27:26,970 mentres que un FILE * ten unha morea de cousas asociado a el. 1030 01:27:26,970 --> 01:27:30,380 A razón que necesitamos dicir 0 en vez de stdin 1031 01:27:30,380 --> 01:27:37,480 é que stdin é un FILE * que apunta a algo que é referencia descriptor de ficheiro 0. 1032 01:27:37,480 --> 01:27:45,070 Así, mesmo aquí, cando fago fopen (argv [1], eu estou quedando un * ficheiro de volta. 1033 01:27:45,070 --> 01:27:51,180 Pero en algún lugar que * FILE é unha cousa correspondente ao descritor de ficheiro para o ficheiro. 1034 01:27:51,180 --> 01:27:57,430 Se ollar para a páxina do manual para abrir, entón eu creo que vai ter que facer o home aberto 3 - nope - 1035 01:27:57,430 --> 01:27:59,380 home aberto 2 - Si. 1036 01:27:59,380 --> 01:28:06,250 Se ollar para a páxina para abrir aberto é como un fopen de nivel inferior, 1037 01:28:06,250 --> 01:28:09,350 e está retornando ao descritor de ficheiro real. 1038 01:28:09,350 --> 01:28:12,050 fopen fai unha morea de cousas enriba aberto, 1039 01:28:12,050 --> 01:28:17,640 que en vez de retornar só descriptor de ficheiro que retorna un ficheiro punteiro * 1040 01:28:17,640 --> 01:28:20,590 dentro do que é o noso descriptor de ficheiro pequeno. 1041 01:28:20,590 --> 01:28:25,020 Entón estándar en canto á cousa * file, 1042 01:28:25,020 --> 01:28:29,120 Considerando 0 refírese só un estándar descriptor do ficheiro en si. 1043 01:28:29,120 --> 01:28:32,160 >> Preguntas? 1044 01:28:32,160 --> 01:28:35,930 [Risas] Blew por iso. 1045 01:28:35,930 --> 01:28:39,140 Todo ben. Estamos a facer. [Risas] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]