1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Sección 5 - Más 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 es CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Como dije en mi e-mail, hay un montón de cosas que usted puede utilizar 5 00:00:14,250 --> 00:00:17,060 que no sea el aparato para hacer realidad los boletines de problemas. 6 00:00:17,060 --> 00:00:19,910 Te recomendamos que lo hagas en el aparato sólo porque entonces nos será más fácil ayudar 7 00:00:19,910 --> 00:00:22,070 y sabemos que todo va a funcionar. 8 00:00:22,070 --> 00:00:26,950 Pero como un ejemplo de que se pueden hacer cosas si, por ejemplo, no tienen acceso 9 00:00:26,950 --> 00:00:31,570 a un aparato o desea trabajar en el sótano del Centro de Ciencias - 10 00:00:31,570 --> 00:00:33,090 que en realidad tienen el aparato demasiado - 11 00:00:33,090 --> 00:00:35,150 si quieres trabajar en cualquier lugar. 12 00:00:35,150 --> 00:00:42,370 Un ejemplo se han visto / oído de SSH? 13 00:00:44,380 --> 00:00:47,780 SSH es básicamente igual que conectarse a algo. 14 00:00:47,780 --> 00:00:51,340 De hecho, ahora mismo estoy SSHed en el aparato. 15 00:00:51,340 --> 00:00:54,290 Nunca trabajar directamente en el aparato. 16 00:00:55,930 --> 00:01:01,060 Aquí está el aparato, y si miras aquí abajo se ve esta dirección IP. 17 00:01:01,060 --> 00:01:03,650 Nunca trabajo en el propio aparato; 18 00:01:03,650 --> 00:01:08,840 Siempre vengo a un iTerm2 ventana / ventana de terminal. 19 00:01:08,840 --> 00:01:15,910 Usted puede SSH a esa dirección IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Me acuerdo de ese número con mucha facilidad debido a que es un bonito patrón. 21 00:01:20,390 --> 00:01:24,920 Pero eso me va a pedir mi contraseña, y ahora estoy en el aparato. 22 00:01:24,920 --> 00:01:33,060 Básicamente, en este punto, si se abre un terminal en el interior del propio aparato, 23 00:01:33,060 --> 00:01:36,350 esta interfaz, sin embargo usted lo usa, es exactamente el mismo 24 00:01:36,350 --> 00:01:40,010 como la interfaz que estoy usando aquí, pero ahora estamos SSHed. 25 00:01:42,240 --> 00:01:44,920 Usted no tiene que SSH al dispositivo. 26 00:01:44,920 --> 00:01:52,360 Un ejemplo de otro lugar que podría SSH es que estoy bastante seguro de que tiene por defecto - 27 00:01:52,360 --> 00:01:55,020 Oh. Más grande. 28 00:01:55,020 --> 00:02:01,130 Todos ustedes deben tener en cuenta FAS por defecto en los servidores de FAS. 29 00:02:01,130 --> 00:02:06,840 Para mí, lo haría SSH a rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Va a pedirle que la primera vez, y usted dice que sí. 31 00:02:11,610 --> 00:02:15,840 Mi contraseña es sólo va a ser mi contraseña FAS. 32 00:02:15,840 --> 00:02:22,650 Y ahora, estoy SSHed a los servidores buenos, y puedo hacer lo que quiera aquí. 33 00:02:22,650 --> 00:02:28,560 Una gran cantidad de clases que se podrían adoptar, como 124, van a tener que subir cosas a aquí 34 00:02:28,560 --> 00:02:30,950 que presentar efectivamente sus boletines de problemas. 35 00:02:30,950 --> 00:02:34,100 Pero dice que no tiene acceso a su aparato. 36 00:02:34,100 --> 00:02:37,910 A continuación, puede hacer cosas, como aquí se dirá - 37 00:02:37,910 --> 00:02:42,160 Esto es sólo nuestra sección de preguntas. 38 00:02:42,160 --> 00:02:45,070 Se le pide que lo hagamos en el aparato. 39 00:02:45,070 --> 00:02:47,790 En lugar de eso sólo lo hará en el servidor. 40 00:02:47,790 --> 00:02:50,560 Me voy a descomprimir eso. 41 00:02:50,560 --> 00:02:55,670 El problema va a ser que usted está acostumbrado a usar algo como gedit 42 00:02:55,670 --> 00:02:58,160 o lo que sea en el interior del aparato. 43 00:02:58,160 --> 00:03:01,830 No vas a tener que en el servidor de FAS. 44 00:03:01,830 --> 00:03:04,110 Todo esto es sólo va a ser esta interfaz textual. 45 00:03:04,110 --> 00:03:09,180 Así que usted podría cualquiera de ellos, tratar de aprender un editor de texto que se tiene. 46 00:03:09,180 --> 00:03:12,130 Tienen Nano. 47 00:03:12,130 --> 00:03:14,990 Nano es bastante fácil de usar. 48 00:03:14,990 --> 00:03:19,470 Usted puede utilizar sus flechas y escribe normalmente. 49 00:03:19,470 --> 00:03:21,250 Así que no es difícil. 50 00:03:21,250 --> 00:03:24,720 Si usted quiere conseguir realmente de lujo puede usar Emacs, 51 00:03:24,720 --> 00:03:29,850 que yo probablemente no debería haber abierto porque no sé ni cómo cerrar Emacs. 52 00:03:29,850 --> 00:03:32,760 X Control, Control C? Si. 53 00:03:32,760 --> 00:03:35,310 O puede usar Vim, que es lo que yo uso. 54 00:03:35,310 --> 00:03:37,800 Y esas son sus opciones. 55 00:03:37,800 --> 00:03:43,830 Si no quieres hacer eso, usted también puede, si nos fijamos en manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 En un PC, puede usar SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 que vas a tener que descargar por separado. 59 00:03:51,940 --> 00:03:55,460 En un Mac, puede simplemente usar predeterminado Terminal o puede descargar iTerm2, 60 00:03:55,460 --> 00:03:58,490 que es como un terminal bonito, lujoso. 61 00:03:58,490 --> 00:04:03,780 Si usted va a manual.cs50.net verás un enlace a Notepad + +, 62 00:04:03,780 --> 00:04:07,120 que es lo que se puede utilizar en un PC. 63 00:04:07,120 --> 00:04:13,340 Te permite SFTP de Notepad + +, que es básicamente SSH. 64 00:04:13,340 --> 00:04:17,750 Lo que esto le permitirá hacer es editar tus archivos de forma local, 65 00:04:17,750 --> 00:04:20,670 y luego cada vez que quieras salvar, salvará a nice.fas, 66 00:04:20,670 --> 00:04:23,670 donde usted puede entonces correr. 67 00:04:23,670 --> 00:04:26,880 Y el equivalente en Mac va a ser TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Por lo tanto, le permite hacer lo mismo. 69 00:04:28,760 --> 00:04:32,800 Te permite editar archivos de forma local y guardarlos en nice.fas, 70 00:04:32,800 --> 00:04:35,730 donde usted puede entonces correr. 71 00:04:35,730 --> 00:04:40,400 Así que si alguna vez atrapado sin un aparato, tiene las siguientes opciones 72 00:04:40,400 --> 00:04:44,230 que todavía hace sus boletines de problemas. 73 00:04:44,230 --> 00:04:48,250 El único problema va a ser que no vamos a tener la biblioteca CS50 74 00:04:48,250 --> 00:04:51,580 porque nice.fas por defecto no tienen eso. 75 00:04:51,580 --> 00:04:55,970 Puede descargar la biblioteca CS50 - 76 00:04:55,970 --> 00:04:58,470 Yo no creo que sea necesario que en este punto. 77 00:04:58,470 --> 00:05:03,270 Puede descargar la biblioteca CS50 y copiarlo a nice.fas, 78 00:05:03,270 --> 00:05:07,450 o creo que en este momento no usarlo nunca más de todos modos. 79 00:05:07,450 --> 00:05:12,720 O si lo hacemos, puede por el momento, sustituirlo por 80 00:05:12,720 --> 00:05:18,480 las implementaciones de las funciones en la biblioteca CS50 de todos modos. 81 00:05:18,480 --> 00:05:21,370 Así que no debería ser parte de una restricción. 82 00:05:21,370 --> 00:05:23,710 Y eso es todo. 83 00:05:26,460 --> 00:05:29,820 >> Voy a volver a la aplicación ahora, vamos a hacer todo lo posible en el aparato. 84 00:05:29,820 --> 00:05:37,510 En cuanto a nuestra sección de preguntas, al principio, como dije en mi e-mail, 85 00:05:37,510 --> 00:05:43,620 tenemos que hablar de la corta se suponía que ver. 86 00:05:43,620 --> 00:05:51,980 Tenemos la reorientación y Tubos y estas tres preguntas. 87 00:05:51,980 --> 00:05:56,070 >> ¿A qué corriente no funciona como printf escribir de forma predeterminada? 88 00:05:56,070 --> 00:05:59,130 Así corriente. ¿Qué es un río? 89 00:06:06,520 --> 00:06:15,100 Una corriente es básicamente como si fuera sólo un poco - 90 00:06:15,100 --> 00:06:21,450 Ni siquiera es una fuente de 1s y 0s. 91 00:06:21,450 --> 00:06:24,920 La corriente está pidiendo aquí es la salida estándar. 92 00:06:24,920 --> 00:06:27,250 Y fuera tan estándar es una corriente que cuando se escribe en él, 93 00:06:27,250 --> 00:06:30,940 que aparece en la pantalla. 94 00:06:30,940 --> 00:06:36,860 Fuera Standard, por flujo, esto significa que usted acaba de escribir 1s y 0s a la misma, 95 00:06:36,860 --> 00:06:40,220 y el otro extremo de salida estándar sólo lee de esa corriente. 96 00:06:40,220 --> 00:06:43,540 Es sólo una cadena de 1s y 0s. 97 00:06:43,540 --> 00:06:45,570 Usted puede escribir a los arroyos o puede leer de los arroyos 98 00:06:45,570 --> 00:06:47,950 dependiendo de lo que la corriente que realmente es. 99 00:06:47,950 --> 00:06:52,800 Las otras dos corrientes de defecto son estándar y de error estándar. 100 00:06:52,800 --> 00:06:57,540 Es estándar en cada vez que se GetString, está esperando para que usted pueda materia de entrada. 101 00:06:57,540 --> 00:07:01,570 Por lo que te espera, en realidad espera en la norma en, 102 00:07:01,570 --> 00:07:04,880 que en realidad es lo que pasa cuando se escribe en el teclado. 103 00:07:04,880 --> 00:07:07,530 Estás escribiendo en estándar pulg 104 00:07:07,530 --> 00:07:10,050 Error estándar es básicamente equivalente a la salida estándar, 105 00:07:10,050 --> 00:07:13,280 pero es especializada en la que al imprimir en error estándar, 106 00:07:13,280 --> 00:07:16,770 se supone que debes imprimir sólo mensajes de error para que 107 00:07:16,770 --> 00:07:20,200 para que pueda diferenciar entre los mensajes impresos regulares a la pantalla 108 00:07:20,200 --> 00:07:24,560 frente a los mensajes de error dependiendo de si fueron a la salida estándar o error estándar. 109 00:07:24,560 --> 00:07:28,660 Los archivos también. 110 00:07:28,660 --> 00:07:32,440 Fuera estándar, estándar en, y el error estándar son corrientes sólo especiales, 111 00:07:32,440 --> 00:07:36,810 pero en realidad cualquier archivo, cuando se abre un archivo, éste se convierte en un flujo de bytes 112 00:07:36,810 --> 00:07:40,740 donde sólo se puede leer de esa corriente. 113 00:07:40,740 --> 00:07:47,770 Usted, en su mayor parte, sólo puedo pensar en un archivo como una secuencia de bytes. 114 00:07:47,770 --> 00:07:51,190 Entonces, ¿qué es lo que las corrientes escribir de forma predeterminada? Por Norma. 115 00:07:51,190 --> 00:07:56,980 >> ¿Cuál es la diferencia entre> y >>? 116 00:07:58,140 --> 00:08:03,710 ¿Alguien ver el vídeo de antemano? Bien. 117 00:08:03,710 --> 00:08:10,960 > Va a ser cómo redirigir a los archivos, 118 00:08:10,960 --> 00:08:15,240 y >> también va a redirigir la salida en archivos, 119 00:08:15,240 --> 00:08:17,820 pero está vez va a anexar al expediente. 120 00:08:17,820 --> 00:08:23,430 Por ejemplo, los vamos a decir resulta que tengo dict aquí, 121 00:08:23,430 --> 00:08:27,020 y las cosas sólo en el interior de dict es gato, gato, perro, pez, perro. 122 00:08:27,020 --> 00:08:31,530 Un comando que usted tiene en la línea de comandos es gato, 123 00:08:31,530 --> 00:08:34,539 que sólo va a imprimir lo que hay en un archivo. 124 00:08:34,539 --> 00:08:40,679 Así que cuando digo dict gato, que va a imprimir gato, gato, perro, pez, perro. Eso es todo gato hace. 125 00:08:40,679 --> 00:08:46,280 Eso significa que se imprime en la salida estándar gato, gato, perro, pez, perro. 126 00:08:46,280 --> 00:08:53,240 Si en lugar que desee redirigir a un archivo, puede utilizar> y redireccionarlo a lo que el archivo es. 127 00:08:53,240 --> 00:08:56,460 Voy a llamar al archivo archivo. 128 00:08:56,460 --> 00:09:00,320 Así que ahora si ls, voy a ver que tengo un nuevo archivo llamado archivo. 129 00:09:00,320 --> 00:09:05,700 Y si lo abre, va a tener exactamente lo gatos, acondicionados en la línea de comandos. 130 00:09:05,700 --> 00:09:11,040 Así que ahora si lo hago de nuevo, entonces va a redirigir la salida en un archivo, 131 00:09:11,040 --> 00:09:13,930 y yo voy a tener exactamente la misma cosa. 132 00:09:13,930 --> 00:09:17,910 Así que, técnicamente, se anuló por completo lo que teníamos. 133 00:09:17,910 --> 00:09:22,970 Y vamos a ver si puedo cambiar dict, saqué perro. 134 00:09:22,970 --> 00:09:29,980 Ahora bien, si dict gato en el archivo de nuevo, vamos a tener la nueva versión con el perro eliminado. 135 00:09:29,980 --> 00:09:32,400 Por lo tanto, se anula completamente. 136 00:09:32,400 --> 00:09:36,640 En cambio, si usamos >>, que va a adjuntar el archivo. 137 00:09:36,640 --> 00:09:40,860 Ahora, al abrir el archivo, vemos que tenemos la misma cosa dos veces impreso 138 00:09:40,860 --> 00:09:44,920 porque era allí una vez, entonces adjunta a la original. 139 00:09:44,920 --> 00:09:48,130 Así que eso es lo que> y >> hacer. 140 00:09:48,130 --> 00:09:50,580 ¿La siguiente pregunta - No pregunte al respecto. 141 00:09:50,580 --> 00:09:59,050 >> El otro que tenemos es <, que si> redirecciona la salida estándar, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Vamos a ver si tenemos un ejemplo. 144 00:10:14,750 --> 00:10:16,930 Soy capaz de escribir un muy rápido. 145 00:10:17,870 --> 00:10:25,700 Tomemos cualquier archivo, hello.c. 146 00:10:56,060 --> 00:10:59,070 Archivo relativamente sencillo. 147 00:10:59,070 --> 00:11:03,570 Me estoy haciendo una cadena y luego imprimir "Hola" cualquiera que sea la cadena que acaba de entrar era. 148 00:11:03,570 --> 00:11:07,990 Así que hola y luego. / Hello. 149 00:11:07,990 --> 00:11:10,720 Ahora se me llevó a escribir algo, 150 00:11:10,720 --> 00:11:15,070 lo que significa que está esperando en las cosas que se introducirán en estándar pulg 151 00:11:15,070 --> 00:11:20,450 Así que lo que yo quiera entrar en estándar pulg Sólo vamos a decir Hola, Rob! 152 00:11:20,450 --> 00:11:23,310 Entonces está imprimiendo a la salida estándar Hola, Rob! 153 00:11:23,310 --> 00:11:28,860 Si lo hago. / Hola y luego redireccionar, 154 00:11:30,740 --> 00:11:34,310 por ahora sólo se puede redirigir a un archivo. 155 00:11:34,310 --> 00:11:41,720 Así que si me pongo en algún archivo, txt, y puse Rob, 156 00:11:41,720 --> 00:11:52,300 hola si me quedo y luego redirigir el archivo txt a. / hola, que va a decir Hola, Rob! inmediatamente. 157 00:11:52,300 --> 00:11:57,160 Cuando por primera vez llega a GetString y está esperando en la norma en, 158 00:11:57,160 --> 00:12:01,730 estándar ya no se espera en el teclado para los datos que se ingresan. 159 00:12:01,730 --> 00:12:05,980 En cambio, hemos redirigido estándar para leer el archivo txt. 160 00:12:05,980 --> 00:12:10,290 Y por lo que va a leer desde el archivo txt, que es sólo la línea de Rob, 161 00:12:10,290 --> 00:12:13,380 y entonces va a imprimir Hola, Rob! 162 00:12:13,380 --> 00:12:18,180 Y si yo quería, yo también podía hacer. / Hello 00:12:21,500 y entonces el estándar que el mismo de la impresión, que es Hola, Rob!, 164 00:12:21,500 --> 00:12:24,700 Puedo redireccionar que en su propio archivo. 165 00:12:24,700 --> 00:12:29,790 Voy a llamar al archivo hola - no, no lo haré, porque ese es el ejecutable - txt2. 166 00:12:29,790 --> 00:12:40,150 Ahora, txt2 va a tener la salida de. / Hello 00:12:43,520 >> ¿Preguntas? 168 00:12:45,900 --> 00:12:49,090 >> Bien. Así que aquí tenemos tubería. 169 00:12:49,090 --> 00:12:53,510 Los tubos son la última unidad de redirección. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Supongo que una unidad más de redirección es si en vez de> hacer 2>, 171 00:12:58,750 --> 00:13:01,070 que está redirigiendo error estándar. 172 00:13:01,070 --> 00:13:06,280 Así que si algo salía de error estándar, no se pone en txt2. 173 00:13:06,280 --> 00:13:12,480 Pero note si lo hago 2>, entonces es todavía la impresión Hola, Rob! a la línea de comandos 174 00:13:12,480 --> 00:13:18,600 porque estoy solo redirigir el error estándar, no estoy redirigiendo la salida estándar. 175 00:13:18,600 --> 00:13:22,210 Error estándar y la salida estándar son diferentes. 176 00:13:24,210 --> 00:13:27,080 Si querías escribir realmente el error estándar 177 00:13:27,080 --> 00:13:35,080 entonces yo podría cambiar esto sea fprintf a stderr. 178 00:13:35,080 --> 00:13:37,850 Así printf, por defecto, se imprime en la salida estándar. 179 00:13:37,850 --> 00:13:41,720 Si desea imprimir en el error estándar de forma manual, entonces tengo que usar fprintf 180 00:13:41,720 --> 00:13:45,010 y especificar lo que desea imprimir. 181 00:13:45,010 --> 00:13:49,720 Si en cambio lo hice stdout fprintf, entonces eso es básicamente equivalente a printf. 182 00:13:49,720 --> 00:13:55,530 Pero fprintf al error estándar. 183 00:13:57,790 --> 00:14:03,650 Así que ahora, si puedo redirigir esto en txt2, Hola, Rob! todavía se está impreso en la línea de comandos 184 00:14:03,650 --> 00:14:08,270 ya que se está haciendo visualiza como error estándar y sólo estoy redirigiendo la salida estándar. 185 00:14:08,270 --> 00:14:16,420 Si ahora redirigir el error estándar, ya que no se imprimen y txt2 va a ser ¡Hola, Rob! 186 00:14:16,420 --> 00:14:21,910 Así que ahora, usted puede imprimir sus errores reales en el error estándar 187 00:14:21,910 --> 00:14:24,720 e imprimir sus mensajes regulares a la salida estándar. 188 00:14:24,720 --> 00:14:31,420 Y así, cuando se ejecuta el programa, se puede ejecutar como. / Hola este tipo con el 2> 189 00:14:31,420 --> 00:14:33,800 para que el programa va a funcionar con normalidad, 190 00:14:33,800 --> 00:14:38,400 pero cualquier mensaje de error que usted recibe puede comprobar más adelante en su registro de errores, 191 00:14:38,400 --> 00:14:44,500 lo que los errores, y luego buscar el archivo más tarde y tendrá errores los errores que ocurrieron. 192 00:14:45,200 --> 00:14:47,540 >> ¿Preguntas? 193 00:14:47,540 --> 00:14:58,070 >> El último es pipa, que se puede pensar en como tomar la salida estándar de un comando 194 00:14:58,070 --> 00:15:01,210 y lo que es el estándar en el siguiente comando. 195 00:15:01,210 --> 00:15:05,570 Un ejemplo de ello es eco es algo línea de comandos 196 00:15:05,570 --> 00:15:11,840 que sólo va a hacerse eco de lo que me pone como argumento. No voy a poner comillas. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, bla, sólo va a imprimir, bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Antes, cuando me dijo que tenía que poner Rob en un archivo txt 199 00:15:20,600 --> 00:15:28,830 porque sólo puedo redirigir los archivos txt, en cambio, / si me hago eco de Rob 200 00:15:28,830 --> 00:15:35,520 y luego canalizarla en. / hola, que también hará el mismo tipo de cosas. 201 00:15:35,520 --> 00:15:39,160 Esto es tomar la salida de este comando, el eco Rob, 202 00:15:39,160 --> 00:15:43,610 y que sirva como insumo para el. / hello. 203 00:15:44,790 --> 00:15:49,560 Usted puede pensar en él como el primer eco Rob redirigir a un archivo 204 00:15:49,560 --> 00:15:54,160 y luego ingrese en. / hola ese archivo que se emiten justo. 205 00:15:54,160 --> 00:15:57,850 Pero se necesita el archivo temporal de la imagen. 206 00:16:01,890 --> 00:16:04,460 >> Las preguntas sobre eso? 207 00:16:04,460 --> 00:16:07,150 >> La pregunta que viene va a implicar esto. 208 00:16:07,150 --> 00:16:15,310 ¿Qué gasoducto podría usar para encontrar el número de nombres únicos en un archivo llamado nombres.txt? 209 00:16:15,310 --> 00:16:24,160 Los comandos que vamos a querer utilizar aquí son únicos, por lo uniq, a continuación, wc. 210 00:16:24,160 --> 00:16:28,840 Usted puede hacer uniq hombre a mirar realmente lo que hace, 211 00:16:28,840 --> 00:16:34,840 y que sólo va a filtrar las líneas que coincidan adyacentes de la entrada. 212 00:16:34,840 --> 00:16:40,690 Y el hombre wc va a imprimir la palabra nueva línea, y el recuento de bytes para cada archivo. 213 00:16:40,690 --> 00:16:43,760 Y el último que vamos a querer usar es una especie, 214 00:16:43,760 --> 00:16:47,410 que se va a ordenar sólo las líneas de archivo txt. 215 00:16:47,410 --> 00:16:58,080 Si hago algún archivo txt, nombres.txt, y es Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 lo que quiero hacer aquí es encontrar el número de nombres únicos en este archivo. 217 00:17:03,910 --> 00:17:08,750 Entonces, ¿qué debería ser la respuesta? >> [Estudiante] 4. Sí >>. 218 00:17:08,750 --> 00:17:13,780 Debería ser 4, ya que Rob, Tommy, Joseph, RJ son los únicos nombres únicos en este archivo. 219 00:17:13,780 --> 00:17:20,180 El primer paso, si acabo de hacer recuento de palabras en nombres.txt, 220 00:17:20,180 --> 00:17:24,290 esto es en realidad me está diciendo todo. 221 00:17:24,290 --> 00:17:32,560 Esto es en realidad la impresión - A ver, hombre wc - nuevas líneas, palabras, y el recuento de bytes. 222 00:17:32,560 --> 00:17:38,270 Si sólo se preocupan por las líneas, entonces sólo puede hacer wc-l nombres.txt. 223 00:17:41,730 --> 00:17:44,300 Así que ese es el paso 1. 224 00:17:44,300 --> 00:17:50,510 Pero yo no quiero wc-l nombres.txt nombres.txt porque sólo contiene todos los nombres, 225 00:17:50,510 --> 00:17:54,170 y quiero filtrar los seres no únicos. 226 00:17:54,170 --> 00:18:01,200 Así que si lo hago nombres.txt uniq, que no acaba de darme lo que quiero 227 00:18:01,200 --> 00:18:03,760 porque los nombres duplicados todavía están allí. 228 00:18:03,760 --> 00:18:07,690 ¿Por qué es eso? ¿Por qué no uniq hacer lo que quiero? 229 00:18:07,690 --> 00:18:10,500 [Estudiante] Los duplicados no son [inaudible] >> Si. 230 00:18:10,500 --> 00:18:16,370 Recuerde que la página de manual para uniq dice filtro de líneas coincidentes adyacentes. 231 00:18:16,370 --> 00:18:19,680 No son adyacentes, por lo que no los filtra. 232 00:18:19,680 --> 00:18:31,100 Si ordenarlos en primer lugar, nombres.txt tipo va a poner todas las líneas duplicadas entre sí. 233 00:18:31,100 --> 00:18:34,450 Así que ahora nombres.txt especie es eso. 234 00:18:34,450 --> 00:18:40,550 Voy a querer usar eso como la entrada a uniq, que es | uniq. 235 00:18:40,550 --> 00:18:43,390 Eso me da Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 y quiero usar eso como la entrada a wc-l, 237 00:18:49,260 --> 00:18:52,740 que me va a dar 4. 238 00:18:52,740 --> 00:18:56,930 Como dice aquí, lo gasoducto podría utilizar? 239 00:18:56,930 --> 00:19:01,390 Usted puede hacer un montón de cosas como el uso de una serie de comandos 240 00:19:01,390 --> 00:19:05,130 donde se utiliza la salida de un comando como entrada para el comando siguiente. 241 00:19:05,130 --> 00:19:08,780 Usted puede hacer un montón de cosas, un montón de cosas inteligentes. 242 00:19:08,780 --> 00:19:11,440 >> ¿Preguntas? 243 00:19:12,910 --> 00:19:14,600 Bien. 244 00:19:14,600 --> 00:19:17,880 Eso es para las tuberías y la redirección. 245 00:19:18,370 --> 00:19:24,090 >> Ahora vamos a las cosas reales, las cosas codificación. 246 00:19:24,090 --> 00:19:29,100 Dentro de este PDF, podrás ver este comando, 247 00:19:29,100 --> 00:19:32,950 y usted desea ejecutar este comando en el aparato. 248 00:19:36,240 --> 00:19:42,250 wget es el comando para sólo conseguir algo de Internet, en el fondo, 249 00:19:42,250 --> 00:19:45,180 así wget URL y esto. 250 00:19:45,180 --> 00:19:49,110 Si usted fue a la siguiente dirección URL en el navegador, se descarga el archivo. 251 00:19:49,110 --> 00:19:52,510 Me acaba de hacer clic en él, por lo que el archivo descargado para mí. 252 00:19:52,510 --> 00:19:55,650 Pero escribir wget de esa cosa dentro de la terminal 253 00:19:55,650 --> 00:19:58,620 sólo va a descargar en su terminal. 254 00:19:58,620 --> 00:20:02,750 Tengo section5.zip, y usted desea descomprimir section5.zip, 255 00:20:02,750 --> 00:20:06,520 que te va a dar una carpeta llamada Sección 5, 256 00:20:06,520 --> 00:20:11,550 que va a tener todos los archivos que vamos a utilizar hoy en día dentro de ella. 257 00:20:33,380 --> 00:20:37,710 Como los nombres de estos programas sugieren archivos, son un poco buggy, 258 00:20:37,710 --> 00:20:40,990 por lo que su misión es averiguar por qué usar gdb. 259 00:20:40,990 --> 00:20:44,560 ¿Todo el mundo los ha descargado / saber cómo los ha descargado 260 00:20:44,560 --> 00:20:47,480 en su electrodoméstico? Bien. 261 00:20:47,480 --> 00:20:56,400 >> Ejecución de ./buggy1, dirá Segmentation fault (core dumped), 262 00:20:56,400 --> 00:21:00,500 que cada vez que recibe un error de segmentación, es una mala cosa. 263 00:21:00,500 --> 00:21:03,810 ¿Bajo qué circunstancias se puede conseguir una violación de segmento? 264 00:21:03,810 --> 00:21:08,210 [Estudiante] desreferenciación un puntero nulo. Sí >>. Así que es un ejemplo. 265 00:21:08,210 --> 00:21:11,580 Desreferenciación un puntero nulo vas a conseguir una violación de segmento. 266 00:21:11,580 --> 00:21:16,720 Lo que significa es una violación de segmento que está tocando de memoria que no se debe tocar. 267 00:21:16,720 --> 00:21:21,350 Así desreferencia un puntero nulo está tocando la dirección 0, 268 00:21:21,350 --> 00:21:28,060 y, básicamente, todos los ordenadores hoy en día dicen que el 0 es la dirección de memoria que no se debe tocar. 269 00:21:28,060 --> 00:21:31,920 Así que por eso se produce una eliminación de referencias a punteros nulos en una violación de segmento. 270 00:21:31,920 --> 00:21:37,210 Cuando te quedas a no inicializar un puntero, entonces tiene un valor basura, 271 00:21:37,210 --> 00:21:41,520 y así, cuando se intenta eliminar la referencia que, con toda probabilidad, usted está tocando memoria 272 00:21:41,520 --> 00:21:43,540 que está en el medio de la nada. 273 00:21:43,540 --> 00:21:45,650 Si le sucede a tener suerte y el valor de la basura 274 00:21:45,650 --> 00:21:48,440 paso para que apunte a algún lugar en la pila o algo, 275 00:21:48,440 --> 00:21:50,820 luego cuando desreferencia puntero que los que no ha inicializado, 276 00:21:50,820 --> 00:21:52,730 nada va a salir mal. 277 00:21:52,730 --> 00:21:55,480 Pero si se está señalando, por ejemplo, en algún lugar entre la pila y el heap, 278 00:21:55,480 --> 00:21:59,850 o es simplemente apuntando a algún lugar que no ha sido utilizado por el programa, sin embargo, 279 00:21:59,850 --> 00:22:02,240 entonces usted está tocando de memoria que no se debe tocar y segfault ti. 280 00:22:02,240 --> 00:22:06,370 Al escribir una función recursiva y recursivamente demasiadas veces 281 00:22:06,370 --> 00:22:08,720 y su pila es demasiado grande y choca con las cosas de la pila 282 00:22:08,720 --> 00:22:12,270 que no debe chocar con, estás tocando de memoria que no se debe tocar, 283 00:22:12,270 --> 00:22:14,810 por lo que violación de segmento. 284 00:22:14,810 --> 00:22:17,010 Eso es lo que es una violación de segmento. 285 00:22:17,010 --> 00:22:21,810 >> También es la misma razón que si usted tiene una cadena como - 286 00:22:21,810 --> 00:22:23,930 vamos a volver al programa anterior. 287 00:22:23,930 --> 00:22:28,530 En hello.c--soy sólo va a hacer otra cosa. 288 00:22:28,530 --> 00:22:33,770 char * s = "hola mundo"; 289 00:22:33,770 --> 00:22:42,310 Si utilizo * s = algo o s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 así que hola. / hola, ¿por qué esa violación de segmento? 291 00:22:48,410 --> 00:22:51,250 ¿Por qué esta violación de segmento? 292 00:22:55,660 --> 00:22:57,890 ¿Qué espera que suceda? 293 00:22:57,890 --> 00:23:06,640 Si lo hiciera printf ("% s \ n", s), lo que se puede esperar para ser impreso? 294 00:23:06,640 --> 00:23:09,930 [Estudiante] X hello. Sí >>. 295 00:23:09,930 --> 00:23:15,140 El problema es que cuando se declara una cadena como esta, 296 00:23:15,140 --> 00:23:18,190 s es un puntero que va a ir a la pila, 297 00:23:18,190 --> 00:23:25,880 y lo que s está señalando es esta cadena que está contenido en memoria de sólo lectura. 298 00:23:25,880 --> 00:23:30,560 Así que sólo por el nombre, la memoria de sólo lectura, usted debe conseguir la idea 299 00:23:30,560 --> 00:23:33,010 que si intenta cambiar lo que hay en memoria de sólo lectura, 300 00:23:33,010 --> 00:23:36,670 usted está haciendo algo que no debería estar haciendo con la memoria y la violación de segmento ti. 301 00:23:36,670 --> 00:23:45,360 Esto es realmente una gran diferencia entre char * s y char s []. 302 00:23:45,360 --> 00:23:48,790 Así char s [], ahora esta cadena se va a poner en la pila, 303 00:23:48,790 --> 00:23:53,960 y la pila no es de sólo lectura, lo que significa que esto debería funcionar perfectamente bien. 304 00:23:55,500 --> 00:23:57,370 Y lo hace. 305 00:23:57,370 --> 00:24:06,250 Recuerde que cuando hago char * s = "hola mundo", s es en sí mismo en la pila 306 00:24:06,250 --> 00:24:10,390 pero señala sa en otro lugar, y que en otro lugar pasa a ser de sólo lectura. 307 00:24:10,390 --> 00:24:15,640 Pero char s [] es sólo algo en la pila. 308 00:24:17,560 --> 00:24:21,760 Así que ese es otro ejemplo de una violación de segmento sucediendo. 309 00:24:21,760 --> 00:24:27,820 >> Vimos que ./buggy1 dio lugar a una violación de segmento. 310 00:24:27,820 --> 00:24:31,810 En teoría, no debería mirar buggy1.c inmediatamente. 311 00:24:31,810 --> 00:24:35,170 En su lugar, vamos a mirar a través de gdb. 312 00:24:35,170 --> 00:24:37,750 Tenga en cuenta que cuando usted consigue Segmentation fault (core dumped), 313 00:24:37,750 --> 00:24:40,850 recibe este archivo a través de aquí se llama núcleo. 314 00:24:40,850 --> 00:24:45,200 Si ls-l, veremos que el núcleo es normalmente un archivo bastante grande. 315 00:24:45,200 --> 00:24:51,580 Este es el número de bytes del archivo, por lo que parece que es algo de 250 kilobytes. 316 00:24:51,580 --> 00:24:56,120 La razón de esto es que lo que el volcado del núcleo es realmente 317 00:24:56,120 --> 00:25:01,410 Se presenta cuando el programa se bloquea, el estado de la memoria de su programa 318 00:25:01,410 --> 00:25:05,230 sólo se copia y se pega en este archivo. 319 00:25:05,230 --> 00:25:07,270 Esto se vierten en ese archivo. 320 00:25:07,270 --> 00:25:13,060 Este programa, al tiempo que corría, pasó a tener un uso de memoria de alrededor de 250 kilobytes, 321 00:25:13,060 --> 00:25:17,040 y eso es lo que he vertido en este archivo. 322 00:25:17,040 --> 00:25:23,630 Ahora se puede ver en el archivo si lo hacemos gdb núcleo buggy1. 323 00:25:23,630 --> 00:25:30,130 Sólo podemos hacer gdb buggy1, y que sólo se pondrá en marcha gdb con regularidad, 324 00:25:30,130 --> 00:25:33,800 utilizando buggy1 como su archivo de entrada. 325 00:25:33,800 --> 00:25:38,260 Pero si lo hace gdb núcleo buggy1, entonces está específicamente va a poner en marcha gdb 326 00:25:38,260 --> 00:25:40,330 al ver que el archivo principal. 327 00:25:40,330 --> 00:25:45,560 Y diciendo buggy1 gdb medio sabe que ese archivo central proviene del programa buggy1. 328 00:25:45,560 --> 00:25:49,580 Así gdb buggy1 núcleo va a llevarnos inmediatamente 329 00:25:49,580 --> 00:25:52,060 a los que el programa pasó a terminar. 330 00:25:57,720 --> 00:26:02,340 Vemos aquí el Programa terminó con señal 11, fallo de segmentación. 331 00:26:02,340 --> 00:26:10,110 Nos pasó a ver una línea de montaje, lo que probablemente no es muy útil. 332 00:26:10,110 --> 00:26:15,360 Pero si escribe bt o backtrace, eso va a ser la función 333 00:26:15,360 --> 00:26:19,430 que nos da la lista de nuestros marcos de pila actual. 334 00:26:19,430 --> 00:26:23,150 Así backtrace. Parece que sólo tenemos dos marcos de pila. 335 00:26:23,150 --> 00:26:26,310 El primero es nuestro marco de pila principal, 336 00:26:26,310 --> 00:26:29,810 y el segundo es el marco de pila para esta función que nos ha tocado estar, 337 00:26:29,810 --> 00:26:34,440 que parece que sólo tenemos el código ensamblador para. 338 00:26:34,440 --> 00:26:38,050 Así que vamos a volver a nuestra función principal, 339 00:26:38,050 --> 00:26:42,300 y para ello podemos hacer un marco, y creo que también podemos hacer hacia abajo, 340 00:26:42,300 --> 00:26:45,160 pero casi nunca lo hacen hacia abajo - arriba o abajo. Si. 341 00:26:45,160 --> 00:26:50,710 Arriba y abajo. Hasta que nos lleva a un marco de pila, abajo te trae abajo un marco de pila. 342 00:26:50,710 --> 00:26:53,240 Tiendo a no usarla. 343 00:26:53,240 --> 00:26:59,120 Acabo de decir específicamente el cuadro 1, que se vaya al fotograma con la etiqueta 1. 344 00:26:59,120 --> 00:27:01,750 Cuadro 1 nos va a poner en marco de pila principal, 345 00:27:01,750 --> 00:27:05,570 y dice que aquí la línea de código que nos encontremos en. 346 00:27:05,570 --> 00:27:07,950 Si queríamos un par de líneas de código, se puede afirmar lista, 347 00:27:07,950 --> 00:27:11,280 y que nos va a dar todas las líneas de código que lo rodean. 348 00:27:11,280 --> 00:27:13,360 La línea que estaba en segfaulted 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 rocas", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Si no está claro, sin embargo, usted puede ir directamente desde aquí sólo pensar por qué segfaulted. 351 00:27:24,130 --> 00:27:28,800 Pero podemos dar un paso más y decir: "¿Por qué argv [1] violación de segmento?" 352 00:27:28,800 --> 00:27:38,830 Vamos a imprimir argv [1], y parece que es 0x0, que es el puntero nulo. 353 00:27:38,830 --> 00:27:44,750 Estamos strcmping CS50 rocas y nulos, por lo que va a violación de segmento. 354 00:27:44,750 --> 00:27:48,280 ¿Y por qué es argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Estudiante] Debido a que no le dio ningún argumento de línea de comandos. 356 00:27:51,280 --> 00:27:53,390 Si. Nosotros no le dio ningún argumento de línea de comandos. 357 00:27:53,390 --> 00:27:58,460 Así ./buggy1 sólo va a tener argv [0] sea ./buggy1. 358 00:27:58,460 --> 00:28:02,100 No va a tener un argv [1], por lo que va a violación de segmento. 359 00:28:02,100 --> 00:28:07,450 Pero si, en cambio, lo hago sólo CS50, va a decir que te dan un D 360 00:28:07,450 --> 00:28:09,950 porque eso es lo que se supone que debe hacer. 361 00:28:09,950 --> 00:28:15,240 En cuanto a buggy1.c, se supone que debe imprimir "Se obtiene una D" - 362 00:28:15,240 --> 00:28:20,820 Si argv [1] no es "CS50 rocas", "Usted obtiene una D", de lo "Se obtiene una A!" 363 00:28:20,820 --> 00:28:25,660 Así que si queremos una A, necesitamos esto para comparar como verdadero, 364 00:28:25,660 --> 00:28:28,710 lo que significa que se compara con 0. 365 00:28:28,710 --> 00:28:31,100 Así que argv [1] tiene que ser "piedras" CS50. 366 00:28:31,100 --> 00:28:35,660 Si quieres hacer eso en la línea de comandos, debe utilizar \ para escapar al espacio. 367 00:28:35,660 --> 00:28:41,690 Así CS50 \ rocas y se obtiene una A! 368 00:28:41,690 --> 00:28:44,060 Si usted no hace la barra invertida, ¿por qué no funciona? 369 00:28:44,060 --> 00:28:47,190 [Estudiante] Se trata de dos argumentos diferentes. Sí >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] va a ser CS50, y argv [2] va a ser rocas. Bien. 371 00:28:52,540 --> 00:28:56,470 >> Ahora ./buggy2 va a violación de segmento nuevo. 372 00:28:56,470 --> 00:29:01,880 En lugar de abrir el archivo con su núcleo, sólo tendremos que abrir buggy2 directamente, 373 00:29:01,880 --> 00:29:05,000 así gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Ahora bien, si acaba de ejecutar el programa, entonces va a decir el Programa recibió SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 que es el error de segmentación de la señal, y aquí es donde sucedió a suceder. 376 00:29:15,530 --> 00:29:21,250 En cuanto a nuestro backtrace, vemos que estábamos en el oh_no función, 377 00:29:21,250 --> 00:29:23,900 que fue llamado por el dinky función, que fue llamado por el binky función, 378 00:29:23,900 --> 00:29:26,460 que fue convocada por principal. 379 00:29:26,460 --> 00:29:31,680 También podemos ver los argumentos para estas funciones. 380 00:29:31,680 --> 00:29:34,680 El argumento de mala muerte y binky fue de 1. 381 00:29:34,680 --> 00:29:44,390 Si tenemos lista la función oh_no, vemos que sólo está haciendo oh_no char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 ¿Por que no? 384 00:29:54,330 --> 00:29:58,380 [Estudiante] No se puede eliminar la referencia al puntero nulo? Sí >>. 385 00:29:58,380 --> 00:30:06,090 Esto es sólo decir s es NULL, independientemente de si que pasa a ser un char **, 386 00:30:06,090 --> 00:30:12,070 que, dependiendo de cómo se interprete, podría ser un puntero a un puntero a una cadena 387 00:30:12,070 --> 00:30:15,550 o una matriz de cadenas. 388 00:30:15,550 --> 00:30:21,430 Es s es NULL, por lo que * s se desreferencia un puntero nulo, 389 00:30:21,430 --> 00:30:24,800 por lo que este se va a estrellar. 390 00:30:24,800 --> 00:30:27,540 Esta es una de las maneras más rápidas le sea posible violación de segmento. 391 00:30:27,540 --> 00:30:31,300 Es simplemente declarar un puntero nulo y segfaulting inmediatamente. 392 00:30:31,300 --> 00:30:34,570 Eso es lo que oh_no está haciendo. 393 00:30:34,570 --> 00:30:43,400 Si subimos un marco, entonces vamos a entrar en la función que llamó oh_no. 394 00:30:43,400 --> 00:30:44,830 Tengo que hacer eso. 395 00:30:44,830 --> 00:30:48,610 Si no se introduce un comando y simplemente pulse Enter de nuevo, 396 00:30:48,610 --> 00:30:52,350 se acaba de repetir el comando anterior que se ejecutó. 397 00:30:52,350 --> 00:30:56,610 Estamos en el cuadro 1. 398 00:30:56,610 --> 00:31:04,650 Añadir este marco, vemos aquí es nuestra función. 399 00:31:04,650 --> 00:31:08,520 Usted puede golpear lista de nuevo, o puedes hacer la lista 20 y una lista de más. 400 00:31:08,520 --> 00:31:13,640 La función dinky dice que si i es 1, entonces vaya a la función oh_no, 401 00:31:13,640 --> 00:31:15,960 sino va a la función furtivo. 402 00:31:15,960 --> 00:31:18,700 Y sé que es 1 porque nos ha tocado ver aquí 403 00:31:18,700 --> 00:31:22,560 dinky que se ha llamado con el argumento 1. 404 00:31:22,560 --> 00:31:27,560 O puede simplemente puedo imprimir y dirá i es 1. 405 00:31:27,560 --> 00:31:33,770 Actualmente estamos en mala muerte, y si nos vamos a otro marco, sabemos que va a terminar en binky. 406 00:31:33,770 --> 00:31:36,600 Arriba. Ahora estamos en binky. 407 00:31:36,600 --> 00:31:41,340 Añadir esta función - la lista de antes del descanso me interrumpió - 408 00:31:41,340 --> 00:31:52,670 lo que comenzó como si i es 0, entonces vamos a llamarlo oh_no, que llame mala muerte. 409 00:31:52,670 --> 00:31:57,000 Sabemos que era 1, por lo que llamó de mala muerte. 410 00:31:57,000 --> 00:32:05,030 Y ahora que estamos de vuelta en main, y principal es sólo va a ser int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Eso sólo va a darle un número aleatorio que es 0, 1 ó 2. 412 00:32:08,790 --> 00:32:12,780 Se va a llamar binky con ese número, y lo devolverá 0. 413 00:32:12,780 --> 00:32:16,700 En cuanto a esto, 414 00:32:16,700 --> 00:32:19,880 caminando a través del programa de forma manual sin ejecutarlo inmediatamente, 415 00:32:19,880 --> 00:32:25,400 debería establecer un punto de quiebre en la principal, lo que significa que cuando se corre el programa 416 00:32:25,400 --> 00:32:31,020 su programa se ejecuta hasta que se llega a un punto de quiebre. 417 00:32:31,020 --> 00:32:35,450 Entonces, ejecutar el programa, se ejecutará y luego llegará a la función principal y dejar de correr. 418 00:32:35,450 --> 00:32:44,700 Ahora estamos dentro de la principal, y el paso siguiente o nos va a llevar a la siguiente línea de código. 419 00:32:44,700 --> 00:32:47,050 Usted puede realizar el paso o la siguiente. 420 00:32:47,050 --> 00:32:51,800 Golpear siguiente, ahora me ha sido ajustado a rand ()% 3, por lo que podemos imprimir el valor de i, 421 00:32:51,800 --> 00:32:55,280 y lo voy a decir que es 1. 422 00:32:55,280 --> 00:32:58,110 Ahora bien, no importa si usamos o siguiente paso. 423 00:32:58,110 --> 00:33:01,000 Supongo que importaba en la anterior, pero nos gustaría usar a continuación. 424 00:33:01,000 --> 00:33:06,000 Si usamos paso, entramos en la función, lo que significa ver la cosa real 425 00:33:06,000 --> 00:33:07,940 que está sucediendo dentro de Binky. 426 00:33:07,940 --> 00:33:10,510 Si usamos siguiente, entonces significa ir sobre la función 427 00:33:10,510 --> 00:33:14,070 y sólo tiene que ir a la siguiente línea de código en nuestra función principal. 428 00:33:14,070 --> 00:33:17,900 Aquí mismo, en esta línea, yo estaba en donde decía rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 si lo hice paso, entraría en la ejecución de rand 430 00:33:21,320 --> 00:33:25,110 y ver lo que está ocurriendo allí, y podría pasar por la función rand. 431 00:33:25,110 --> 00:33:26,920 Pero no se preocupan por la función rand. 432 00:33:26,920 --> 00:33:30,190 Sólo quiero ir a la siguiente línea de código en el principal, por lo que utilizará a continuación. 433 00:33:30,190 --> 00:33:35,800 Pero ahora sí me importa acerca de la función binky, así que quiero entrar en eso. 434 00:33:35,800 --> 00:33:37,730 Ahora estoy en binky. 435 00:33:37,730 --> 00:33:42,040 La primera línea de código que va a decir if (i == 0), doy un paso, 436 00:33:42,040 --> 00:33:44,930 vemos que terminamos en mala muerte. 437 00:33:44,930 --> 00:33:51,620 Si nosotros, las cosas de la lista, vemos que lo revise i es = 0. 438 00:33:51,620 --> 00:33:55,470 i no es igual a 0, por lo que se fue a la condición más, 439 00:33:55,470 --> 00:33:59,540 que se va a llamar dinky (i). 440 00:33:59,540 --> 00:34:04,030 Es posible que se confunda. 441 00:34:04,030 --> 00:34:07,380 Si sólo se observa en estas líneas directamente, se podría pensar if (i == 0), 442 00:34:07,380 --> 00:34:10,800 bien, entonces di un paso y ahora estoy en dinky (i), 443 00:34:10,800 --> 00:34:14,120 se podría pensar que debe significar i = 0 o algo así. 444 00:34:14,120 --> 00:34:18,980 No. Sólo significa que sabe que puede pegarse directamente a la línea dinky (i). 445 00:34:18,980 --> 00:34:23,300 Porque no es 0, el siguiente paso no se va a acabar en el otro. 446 00:34:23,300 --> 00:34:26,239 Más no es una línea que va a parar en el. 447 00:34:26,239 --> 00:34:31,570 Es sólo va a ir a la siguiente línea en realidad puede ejecutar, que es dinky (i). 448 00:34:31,570 --> 00:34:36,090 Al entrar en dinky (i), vemos if (i == 1). 449 00:34:36,090 --> 00:34:42,670 Lo que sí sé = 1, así que cuando damos un paso, sabemos que vamos a terminar en oh_no 450 00:34:42,670 --> 00:34:46,489 i = 1, porque llama a la función oh_no, que se puede caminar en, 451 00:34:46,489 --> 00:34:52,969 que se va a establecer char ** s = NULL e inmediatamente "BOOM". 452 00:34:54,270 --> 00:34:59,690 Y luego mirando realmente la aplicación de buggy2, 453 00:34:59,690 --> 00:35:04,590 esto, me acaba de obtener un número aleatorio - 0, 1, o 2 - llamado Binky, 454 00:35:04,590 --> 00:35:10,610 que si i es 0 lo llama oh_no, de lo que llama dinky, que llega hasta aquí. 455 00:35:10,610 --> 00:35:18,100 Si i es 1, llamada oh_no, que llame slinky, que viene aquí, 456 00:35:18,100 --> 00:35:20,460 si i es 2, llamar oh_no. 457 00:35:20,460 --> 00:35:24,720 Ni siquiera creo que haya una manera - 458 00:35:24,720 --> 00:35:30,030 ¿Alguien ve una manera de hacer de éste un programa que no violación de segmento? 459 00:35:30,030 --> 00:35:37,530 Porque a menos que me falta algo, si i es 0, usted inmediatamente violación de segmento, 460 00:35:37,530 --> 00:35:41,250 otra cosa que ir a una función que si i es usted un error de segmentación, 461 00:35:41,250 --> 00:35:44,540 otra cosa que ir a una función en la que si i es 2 que violación de segmento. 462 00:35:44,540 --> 00:35:46,810 Así que no importa lo que hagas, violación de segmento. 463 00:35:46,810 --> 00:35:52,380 >> Creo que una manera de arreglarlo sería en lugar de hacer char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 usted podría malloc espacio para esa cadena. 465 00:35:55,610 --> 00:36:04,230 Podríamos hacer malloc (sizeof) - sizeof qué? 466 00:36:09,910 --> 00:36:15,190 [Estudiante] (char) * 5? >> ¿Esto parece correcto? 467 00:36:15,190 --> 00:36:21,060 Asumo que esto va a funcionar si realmente funcionó, pero no es lo que estoy buscando. 468 00:36:24,400 --> 00:36:32,940 Mira el tipo de s. Vamos a añadir * int, int modo * x. 469 00:36:32,940 --> 00:36:35,600 Me gustaría hacer malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 O si yo quería una matriz de 5, lo haría (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 ¿Qué pasa si tengo un int **? 472 00:36:46,260 --> 00:36:49,140 Lo que yo haría malloc? 473 00:36:49,140 --> 00:36:53,510 [Estudiante] Tamaño del puntero. Sí >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Lo mismo aquí. 475 00:36:56,960 --> 00:37:01,280 Quiero (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Esto va a asignar espacio para el puntero que apunta a "BOOM". 477 00:37:12,840 --> 00:37:15,330 No es necesario reservar espacio para "BOOM" en sí 478 00:37:15,330 --> 00:37:17,210 porque esto es básicamente equivalente a lo que dije antes 479 00:37:17,210 --> 00:37:20,870 de char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" ya existe. Sucede que existen en la región de sólo lectura de la memoria. 481 00:37:27,950 --> 00:37:35,200 Pero lo que ya existe, lo que significa que esta línea de código, si s es un char **, 482 00:37:35,200 --> 00:37:43,900 entonces s * es un char * y que está configurando este char * para indicar "BOOM". 483 00:37:43,900 --> 00:37:50,040 Si quisiera copiar "BOOM" en s, entonces yo tendría que asignar espacio para el s. 484 00:37:55,170 --> 00:38:03,900 Haré * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 ¿Por qué cinco? 486 00:38:06,210 --> 00:38:10,860 4 ¿Por qué no? Parece que "BOOM" es de 4 caracteres. >> [Estudiante] El carácter nulo. 487 00:38:10,860 --> 00:38:14,580 Si. Todas las cadenas van a necesitar el carácter nulo. 488 00:38:14,580 --> 00:38:23,590 Ahora puedo hacer algo como strcat - ¿Cuál es la función para copiar una cadena? 489 00:38:23,590 --> 00:38:28,520 [Estudiante] cpy? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 hombre strcpy. 491 00:38:36,120 --> 00:38:39,590 Así strcpy o strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy es un poco más seguro ya que se puede especificar con exactitud el número de caracteres, 493 00:38:43,410 --> 00:38:46,190 pero en este caso no importa porque lo que sabemos. 494 00:38:46,190 --> 00:38:50,340 Así strcpy y mirar en los argumentos. 495 00:38:50,340 --> 00:38:53,100 El primer argumento es nuestro destino. 496 00:38:53,100 --> 00:38:56,770 El segundo argumento es nuestra fuente. 497 00:38:56,770 --> 00:39:10,310 Vamos a copiar en nuestro destino * s el puntero "BOOM". 498 00:39:10,310 --> 00:39:19,820 ¿Por qué querría hacer esto con un strcpy en lugar de lo que teníamos antes 499 00:39:19,820 --> 00:39:22,800 de * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Hay una razón es posible que desee hacer esto, pero ¿qué es eso? 501 00:39:28,630 --> 00:39:31,940 [Estudiante] Si desea cambiar algo en el "BOOM". Sí >>. 502 00:39:31,940 --> 00:39:37,950 Ahora puedo hacer algo como s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 porque los puntos s al montón y espacio que en el montón que s está apuntando a 504 00:39:48,190 --> 00:39:52,320 es un puntero a más espacio en el montón, que es el almacenamiento de "BOOM". 505 00:39:52,320 --> 00:39:55,150 Así que esta copia de "BOOM" se almacena en el montón. 506 00:39:55,150 --> 00:39:58,780 Hay técnicamente dos copias del "boom" de nuestro programa. 507 00:39:58,780 --> 00:40:03,500 No es el primero que se acaba de dar por esta constante cadena "BOOM", 508 00:40:03,500 --> 00:40:09,250 y la segunda copia del "boom", strcpy creó la copia de "BOOM". 509 00:40:09,250 --> 00:40:13,100 Sin embargo, la copia de "BOOM" se almacena en el montón, y el montón eres libre de cambiar. 510 00:40:13,100 --> 00:40:17,250 La pila no es de sólo lectura, lo que significa que s [0] 511 00:40:17,250 --> 00:40:20,500 va a permitir que usted cambie el valor de "BOOM". 512 00:40:20,500 --> 00:40:23,130 Esto va a permitir cambiar esos caracteres. 513 00:40:23,130 --> 00:40:26,640 >> ¿Preguntas? 514 00:40:27,740 --> 00:40:29,290 Bien. 515 00:40:29,290 --> 00:40:35,500 >> Pasando a buggy3, gdb vamos buggy3. 516 00:40:35,500 --> 00:40:39,840 Acabamos de correr y vemos que obtenemos una violación de segmento. 517 00:40:39,840 --> 00:40:46,550 Si backtrace, sólo hay dos funciones. 518 00:40:46,550 --> 00:40:52,970 Si subimos a nuestra función principal, vemos que segfaulted en esta línea. 519 00:40:52,970 --> 00:41:00,180 Así que sólo mirar a esta línea, for (int fila = 0; fgets esto hace NULL no es igual; 520 00:41:00,180 --> 00:41:03,770 línea + +). 521 00:41:03,770 --> 00:41:08,010 Nuestro cuadro anterior se llamaba _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Usted verá que una gran cantidad de funciones integradas C, 523 00:41:10,720 --> 00:41:15,350 que cuando llegue la violación de segmento, habrá nombres de las funciones realmente críptico 524 00:41:15,350 --> 00:41:18,090 como éste _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Pero eso va a relacionar con la presente convocatoria fgets. 526 00:41:21,770 --> 00:41:25,850 En algún lugar dentro de aquí, estamos segfaulting. 527 00:41:25,850 --> 00:41:30,340 Si nos fijamos en los argumentos a fgets, podemos imprimir buffer. 528 00:41:30,340 --> 00:41:41,180 Vamos a imprimir como - Oh, no. 529 00:41:48,980 --> 00:41:51,900 Imprimir no va a funcionar exactamente como yo quiero que haga. 530 00:41:55,460 --> 00:41:58,000 Vamos a ver el programa actual. 531 00:42:02,200 --> 00:42:09,640 Buffer es un array de caracteres. Se trata de una matriz de caracteres de 128 caracteres. 532 00:42:09,640 --> 00:42:14,980 Así que cuando digo búfer de impresión, va a imprimir esos 128 caracteres, 533 00:42:14,980 --> 00:42:18,300 que supongo que es lo que se espera. 534 00:42:18,300 --> 00:42:21,390 Lo que se busca es imprimir la dirección de buffer, 535 00:42:21,390 --> 00:42:23,680 pero que en realidad no me dice mucho. 536 00:42:23,680 --> 00:42:30,770 Así que cuando se me ocurre decir aquí amortiguador x, que me muestra 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 que, si te acuerdas de antes o punto alguno, Oxbffff tiende a ser una región de pila-ish. 538 00:42:38,690 --> 00:42:46,020 La pila tiende a comenzar en algún lugar un poco menos de 0xc000. 539 00:42:46,020 --> 00:42:51,890 Sólo por ver esta dirección, ya sé que el buffer está ocurriendo en la pila. 540 00:42:51,890 --> 00:43:04,500 Reinicio de mi programa, ejecutar, arriba, amortiguar lo que vimos fue esta secuencia de caracteres 541 00:43:04,500 --> 00:43:06,530 que son más o menos sentido. 542 00:43:06,530 --> 00:43:12,270 Después de imprimir el archivo, ¿qué archivo parece? 543 00:43:15,120 --> 00:43:17,310 [Estudiante] Null. Sí >>. 544 00:43:17,310 --> 00:43:22,610 El archivo es un de tipo * FILE, por lo que es un puntero, 545 00:43:22,610 --> 00:43:26,610 y el valor de dicho puntero es nulo. 546 00:43:26,610 --> 00:43:33,240 Así fgets se va a tratar de leer ese puntero en forma indirecta, 547 00:43:33,240 --> 00:43:37,320 pero con el fin de acceder a ese puntero, que tiene que dejar de hacer referencia. 548 00:43:37,320 --> 00:43:40,550 O bien, con el fin de acceder a lo que debe apuntar a, It desreferencia. 549 00:43:40,550 --> 00:43:43,810 Así que es eliminar la referencia a un puntero nulo y segfaults ella. 550 00:43:46,600 --> 00:43:48,730 Podría haberlo reiniciado allí. 551 00:43:48,730 --> 00:43:52,170 Si rompemos a nuestro punto principal y correr, 552 00:43:52,170 --> 00:43:57,320 la primera línea de código es char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Esto debería dar una pista bastante grande de por qué este programa falla. 554 00:44:00,870 --> 00:44:06,080 Escribiendo siguiente me lleva a la siguiente línea, en el que abrir este archivo, 555 00:44:06,080 --> 00:44:11,140 y entonces inmediatamente entrar en nuestra línea, donde una vez me golpeó próximo, va a violación de segmento. 556 00:44:11,140 --> 00:44:16,880 ¿Alguien quiere echar una razón por la que podría ser segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Estudiante] El archivo no existe. Sí >>. 558 00:44:19,130 --> 00:44:22,250 Esto se supone que es un indicio 559 00:44:22,250 --> 00:44:29,570 que cada vez que va a abrir un archivo que usted necesita para comprobar que el archivo existe en realidad. 560 00:44:29,570 --> 00:44:31,510 Así que aquí, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Al nombre de archivo fopen para la lectura, entonces necesito decir 562 00:44:34,700 --> 00:44:45,870 if (archivo == NULL) y decir printf ("El archivo no existe!" 563 00:44:45,870 --> 00:44:56,340 o - mejor aún - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Así que ahora comprobamos si es NULL 565 00:45:00,300 --> 00:45:03,930 antes de realmente continuar y tratar de leer ese archivo. 566 00:45:03,930 --> 00:45:08,800 Podemos rehacer sólo para ver que funciona. 567 00:45:11,020 --> 00:45:14,970 Tenía la intención de incluir una nueva línea. 568 00:45:21,090 --> 00:45:25,290 Así que ahora nonexistent.txt no existe. 569 00:45:26,890 --> 00:45:30,040 Siempre se debe comprobar si este tipo de cosas. 570 00:45:30,040 --> 00:45:33,870 Siempre se debe comprobar para ver si fopen devuelve NULL. 571 00:45:33,870 --> 00:45:38,170 Siempre se debe comprobar para asegurarse de que malloc no devuelve NULL, 572 00:45:38,170 --> 00:45:41,410 o de lo contrario violación de segmento. 573 00:45:42,200 --> 00:45:45,930 >> Ahora buggy4.c. 574 00:45:49,190 --> 00:45:58,440 En ejecución. Supongo que esto está a la espera de la entrada o posiblemente bucle infinito. 575 00:45:58,440 --> 00:46:01,870 Sí, es un bucle infinito. 576 00:46:01,870 --> 00:46:05,560 Así buggy4. Parece que estamos en bucle infinito. 577 00:46:05,560 --> 00:46:12,590 Podemos dividir a principal, ejecute el programa. 578 00:46:12,590 --> 00:46:20,180 En gdb, siempre y cuando la abreviatura que se utiliza es ambigua 579 00:46:20,180 --> 00:46:23,420 o abreviaturas especiales que ofrecen para usted, 580 00:46:23,420 --> 00:46:29,020 entonces usted puede utilizar n para usar a continuación en lugar de tener que escribir al lado todo el camino. 581 00:46:29,020 --> 00:46:33,730 Y ahora que me he golpeado n una vez, sólo puede pulsar Enter para continuar al lado 582 00:46:33,730 --> 00:46:36,640 en lugar de tener que pulsar Enter n, n Intro, n Intro. 583 00:46:36,640 --> 00:46:44,630 Parece como si estuviera en una especie de bucle para que se ajuste array [i] a 0. 584 00:46:44,630 --> 00:46:50,510 Parece que nunca estoy saliendo de este bucle for. 585 00:46:50,510 --> 00:46:54,780 Si yo puedo imprimir, así que es 2, entonces voy a ir después. 586 00:46:54,780 --> 00:46:59,250 Voy a imprimir i, i es 3, entonces voy a ir después. 587 00:46:59,250 --> 00:47:05,360 Voy a imprimir i e i es 3. A continuación, imprima i, i es 4. 588 00:47:05,360 --> 00:47:14,520 En realidad, la impresión sizeof (array), lo que el tamaño de la matriz es de 20. 589 00:47:16,310 --> 00:47:32,870 Pero parece que hay algún comando gdb especial para ir hasta que algo sucede. 590 00:47:32,870 --> 00:47:37,620 Es como fijar una condición sobre el valor de la variable. Pero yo no me acuerdo de lo que es. 591 00:47:37,620 --> 00:47:44,100 Así que si sigue adelante - 592 00:47:44,100 --> 00:47:47,120 ¿Qué estaba diciendo? ¿Qué has traído para arriba? 593 00:47:47,120 --> 00:47:50,500 [Estudiante] No mostrar añado - >> Yeah. Así que mostrar lo que puedo ayudar. 594 00:47:50,500 --> 00:47:54,530 Si nos limitamos a mostrar i, se puso aquí cuál es el valor de i es 595 00:47:54,530 --> 00:47:56,470 así que no tienes que imprimir cada vez. 596 00:47:56,470 --> 00:48:02,930 Si seguimos adelante siguiente, 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 va mal, muy mal, y yo se pone a 0. 598 00:48:13,330 --> 00:48:22,220 En cuanto a buggy4.c, vemos todo lo que sucede es array int [5]; 599 00:48:22,220 --> 00:48:26,200 for (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 ¿Qué es lo que vemos que está mal aquí? 602 00:48:31,390 --> 00:48:39,480 Como una pista, cuando estaba haciendo el gdb buggy4 - vamos a romper la marcha principal, - 603 00:48:39,480 --> 00:48:45,980 Yo tenía la impresión sizeof (array) sólo para ver lo que la condición es donde finalmente estallara. 604 00:48:47,690 --> 00:48:51,100 ¿Dónde estoy? ¿He correr? 605 00:48:51,100 --> 00:48:54,280 Yo no declaró todavía. 606 00:48:54,280 --> 00:48:58,680 Así imprimir sizeof (array) y eso es 20, 607 00:48:58,680 --> 00:49:06,690 que se espera ya que mi matriz es de tamaño 5 y es de 5 enteros, 608 00:49:06,690 --> 00:49:12,410 por lo que la cosa entera debe ser de 5 * sizeof (int) bytes, donde sizeof (int) tiende a ser 4. 609 00:49:12,410 --> 00:49:14,780 Así sizeof (array) es 20. 610 00:49:14,780 --> 00:49:17,420 ¿Qué debería ser? 611 00:49:17,420 --> 00:49:21,720 [Estudiante] Divididos por sizeof (int). >> Sí, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Parece que todavía hay un problema aquí. Creo que esto sólo debería ser < 613 00:49:30,630 --> 00:49:36,960 ya que es casi siempre 00:49:44,860 Ahora vamos a pensar en por qué esto fue roto en realidad. 615 00:49:44,860 --> 00:49:53,370 ¿Alguien se adivina por qué se me pone a 0 a través de cada iteración del bucle? 616 00:50:01,300 --> 00:50:09,350 La única cosa dentro de lo que está sucediendo aquí es que array [i] se establece en 0. 617 00:50:09,350 --> 00:50:15,350 De alguna manera, esta línea de código que está causando nuestro int i que se establece en 0. 618 00:50:16,730 --> 00:50:23,130 [Estudiante] ¿Podría ser porque está reemplazando la memoria de esta parte de i 619 00:50:23,130 --> 00:50:27,970 cuando se piensa que es el siguiente elemento de la matriz? >> [Bowden] Sí. 620 00:50:27,970 --> 00:50:33,880 Cuando vamos más allá del final de nuestra matriz, 621 00:50:33,880 --> 00:50:39,870 de alguna manera que el espacio que estamos anulando está ignorando el valor de i. 622 00:50:39,870 --> 00:50:48,030 Y si nos fijamos en buggy4, romper marcha principal, 623 00:50:48,030 --> 00:50:53,120 vamos a imprimir la dirección de i. 624 00:50:53,120 --> 00:50:57,280 Parece como si fuera bffff124. 625 00:50:57,280 --> 00:51:03,930 Ahora vamos a imprimir la dirección de la matriz [0]. 110. 626 00:51:03,930 --> 00:51:06,290 ¿Qué pasa con [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] es bfff124. 629 00:51:14,530 --> 00:51:26,990 Así array [5] tiene la misma dirección que yo, lo que significa que la matriz [5] es i. 630 00:51:26,990 --> 00:51:30,720 Si tienen la misma dirección, son la misma cosa. 631 00:51:30,720 --> 00:51:38,410 Así que cuando nos pusimos array [5] a 0, estamos i en 0. 632 00:51:38,410 --> 00:51:46,070 Y si usted piensa acerca de esto en términos de la pila, 633 00:51:46,070 --> 00:51:55,590 int i se declara en primer lugar, lo que significa que tiene un poco de espacio en la pila. 634 00:51:55,590 --> 00:52:04,730 Entonces matriz [5] se asigna, por lo que luego de 20 bytes se asignan en la pila. 635 00:52:04,730 --> 00:52:08,400 Así que se asignarán en primer lugar, a continuación, estos 20 bytes se asignan. 636 00:52:08,400 --> 00:52:11,400 Así que pasa justo antes de la matriz, 637 00:52:11,400 --> 00:52:19,230 y por el camino, como dije la semana pasada, cuando sea técnicamente la pila crece hacia abajo, 638 00:52:19,230 --> 00:52:28,520 Cuando se indexa en una matriz, se nos garantiza que la posición de 0 ª de la matriz 639 00:52:28,520 --> 00:52:31,970 siempre ocurre antes de la primera posición en la matriz. 640 00:52:31,970 --> 00:52:35,900 Esto es un poco como lo hizo la semana pasada. 641 00:52:35,900 --> 00:52:42,210 Observe que en la parte inferior tenemos la dirección 0 y en la parte superior tenemos Max dirección. 642 00:52:42,210 --> 00:52:44,880 La pila siempre está creciendo hacia abajo. 643 00:52:48,100 --> 00:52:53,500 Digamos que me asignen. 644 00:52:53,500 --> 00:52:59,680 Asignamos entero i, lo que significa que vamos a decir aquí entero i se asignan. 645 00:52:59,680 --> 00:53:06,420 Entonces asignamos nuestra matriz de 5 enteros, lo que significa que debajo de eso, 646 00:53:06,420 --> 00:53:11,230 desde que la pila crece hacia abajo, esos 5 números enteros se asignan. 647 00:53:11,230 --> 00:53:15,900 Sin embargo, debido a cómo funcionan las matrices, se tiene la garantía de que la primera posición en la matriz 648 00:53:15,900 --> 00:53:22,260 siempre tiene una dirección inferior a la segunda cosa en la matriz. 649 00:53:22,260 --> 00:53:28,270 Así posición 0 array siempre tiene que ocurrir primero en la memoria, 650 00:53:28,270 --> 00:53:30,700 mientras que la posición de la matriz 1 tiene que suceder después de que 651 00:53:30,700 --> 00:53:33,310 y posición de matriz 2 tiene que suceder después de eso, 652 00:53:33,310 --> 00:53:37,900 lo que significa que la posición 0 array que sucedería en algún lugar por aquí, 653 00:53:37,900 --> 00:53:40,690 posición de matriz 1 pasaría por encima de ese 654 00:53:40,690 --> 00:53:45,530 porque mueve hacia arriba significa mayores direcciones desde la dirección máxima es de aquí. 655 00:53:45,530 --> 00:53:50,490 Así array [0] hasta aquí, array [1] aquí, array [2] hasta aquí, array [3] hasta aquí. 656 00:53:50,490 --> 00:53:55,620 Note como antes hemos destinado entero i todo el camino hasta aquí, 657 00:53:55,620 --> 00:54:01,040 a medida que avanzamos más y más en nuestro arsenal, estamos cada vez más cerca y más cerca de nuestro entero i. 658 00:54:01,040 --> 00:54:07,640 Lo que pasa es que array [5], que es una posición más allá de nuestra matriz, 659 00:54:07,640 --> 00:54:13,010 es exactamente donde entero i pasó a ser asignado. 660 00:54:13,010 --> 00:54:16,920 Así que ese es el punto en el que nos ha tocado estar golpeando el espacio en la pila 661 00:54:16,920 --> 00:54:21,680 que se asignaron entero i, y estamos estableciendo que a 0. 662 00:54:21,680 --> 00:54:26,160 >> Eso es lo que funciona. ¿Preguntas? Si. 663 00:54:26,160 --> 00:54:30,710 [Estudiante] No importa. Bien. 664 00:54:30,710 --> 00:54:33,090 [Estudiante] ¿Cómo evitar este tipo de errores? 665 00:54:33,090 --> 00:54:41,190 Esta clase de errores? No utilice C como lenguaje de programación. 666 00:54:41,190 --> 00:54:45,840 Use un lenguaje que tiene límites de la matriz de comprobación. 667 00:54:45,840 --> 00:54:55,900 Siempre y cuando usted tiene cuidado, usted sólo tiene que evitar ir más allá de los límites de la matriz. 668 00:54:55,900 --> 00:54:58,300 [Estudiante] Así que aquí cuando fuimos más allá de los límites de la matriz - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Ahí es donde las cosas empiezan a ir mal. >> [Estudiante] Oh, está bien. 670 00:55:01,840 --> 00:55:05,730 Siempre y cuando se mantenga dentro de la memoria asignada para la matriz, estás bien. 671 00:55:05,730 --> 00:55:12,400 Sin embargo, C no realiza comprobaciones de error. Si lo hago matriz [1000], que con mucho gusto basta con modificar pase lo que pase - 672 00:55:12,400 --> 00:55:16,500 Se va al principio de la matriz, entonces se va después de 1000 posiciones y lo establece en 0. 673 00:55:16,500 --> 00:55:20,000 No hace ninguna comprobación de que oh, esto en realidad no tiene 1000 cosas en él. 674 00:55:20,000 --> 00:55:22,750 1000 es mucho más de lo que debería estar cambiando, 675 00:55:22,750 --> 00:55:26,940 mientras que Java o algo que usted obtendrá la matriz fuera de límites índice 676 00:55:26,940 --> 00:55:29,820 o el índice de excepción límites. 677 00:55:29,820 --> 00:55:33,950 Es por eso que una gran cantidad de lenguajes de alto nivel tiene estas cosas 678 00:55:33,950 --> 00:55:37,340 donde si usted va más allá de los límites de la matriz, que no vaya 679 00:55:37,340 --> 00:55:40,070 de modo que usted no puede cambiar las cosas desde abajo que 680 00:55:40,070 --> 00:55:42,590 y entonces las cosas van mucho peor de lo que acaba de conseguir una excepción 681 00:55:42,590 --> 00:55:44,940 diciendo que iba más allá del final de la matriz. 682 00:55:44,940 --> 00:55:50,970 [Estudiante] Y así lo hemos cambiado el <= a sólo > [Bowden] Yeah. 683 00:55:50,970 --> 00:55:54,800 Debe ser 00:55:59,560 desde sizeof (array) es de 20, pero solo queremos 5. >> [Estudiante] Derecho. 685 00:55:59,560 --> 00:56:04,060 Más preguntas? Bien. 686 00:56:04,060 --> 00:56:07,380 >> [Estudiante] Tengo una pregunta. Sí >>. 687 00:56:07,380 --> 00:56:16,440 [Estudiante] ¿Cuál es la variable de matriz real? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Al igual que lo que es matriz? 689 00:56:20,000 --> 00:56:24,930 Matriz en sí es un símbolo. 690 00:56:24,930 --> 00:56:31,490 Es sólo la dirección de comienzo de los 20 bytes que se hace referencia. 691 00:56:31,490 --> 00:56:38,070 Usted puede pensar en él como un puntero, pero es un puntero constante. 692 00:56:38,070 --> 00:56:44,140 Tan pronto como las cosas se compila, la matriz de la variable ya no existe. 693 00:56:44,140 --> 00:56:48,210 [Estudiante] Entonces, ¿cómo encontrar el tamaño de la matriz? 694 00:56:48,210 --> 00:56:54,130 Tamaño de matriz se refiere al tamaño de ese bloque que hace referencia a ese símbolo. 695 00:56:54,130 --> 00:57:01,240 Cuando hago algo como printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 vamos a correr. 697 00:57:12,960 --> 00:57:15,530 ¿Qué acabo de hacer el mal? 698 00:57:15,530 --> 00:57:19,220 'Array' Matriz declarado aquí. 699 00:57:20,820 --> 00:57:23,200 Oh, aquí arriba. 700 00:57:23,200 --> 00:57:31,250 Clang es inteligente, y sucede a notar que yo declaré la matriz como 5 elementos 701 00:57:31,250 --> 00:57:34,540 pero estoy en posición de indexación 1000. 702 00:57:34,540 --> 00:57:38,450 Se puede hacer eso porque estos son sólo constantes. 703 00:57:38,450 --> 00:57:43,370 Sólo se puede llegar a darse cuenta de que yo voy más allá de los límites de la matriz. 704 00:57:43,370 --> 00:57:46,880 Pero note antes, cuando teníamos que ser incorrecta, 705 00:57:46,880 --> 00:57:51,040 no es posible que determinar cuántos valores que podría asumir, 706 00:57:51,040 --> 00:57:55,540 por lo que no puede determinar que i iba más allá del final de la matriz. 707 00:57:55,540 --> 00:57:59,430 Eso es sólo Clang ser inteligente. 708 00:57:59,430 --> 00:58:03,340 >> Pero ahora hacer buggy4. Entonces, ¿qué estoy haciendo mal? 709 00:58:03,340 --> 00:58:05,970 Implícitamente se declara función de biblioteca 'printf'. 710 00:58:05,970 --> 00:58:14,960 Voy a querer incluir # . 711 00:58:14,960 --> 00:58:18,710 Bien. Ahora ejecuta buggy4. 712 00:58:18,710 --> 00:58:24,840 Impresión del valor de la matriz como lo hice aquí, imprimirlo como un puntero 713 00:58:24,840 --> 00:58:30,060 imprime algo que se parece a esto - bfb8805c - que es un poco de dirección 714 00:58:30,060 --> 00:58:33,450 que está en la región de pila-ish. 715 00:58:33,450 --> 00:58:41,820 Matriz en sí es como un puntero, pero no es un puntero real, 716 00:58:41,820 --> 00:58:45,410 desde un puntero normal que podemos cambiar. 717 00:58:45,410 --> 00:58:54,700 Array es sólo una constante. Los 20 bloques de memoria comenzará a las 0xbfb8805c dirección. 718 00:58:54,700 --> 00:59:09,020 Así bfb8805c través de esta dirección +20--o supongo -20 - 719 00:59:09,020 --> 00:59:17,400 es toda la memoria asignada a esta matriz. 720 00:59:17,400 --> 00:59:20,350 Array, la propia variable no se almacena en cualquier lugar. 721 00:59:20,350 --> 00:59:27,660 Cuando está compilando el compilador - ola mano en ella - 722 00:59:27,660 --> 00:59:33,060 pero el compilador sólo se utilizan donde conoce matriz a ser. 723 00:59:33,060 --> 00:59:36,090 Se sabe que la matriz se inicia, 724 00:59:36,090 --> 00:59:40,910 y por lo que siempre puede hacer las cosas en términos de compensaciones de ese principio. 725 00:59:40,910 --> 00:59:43,960 No se necesita una variable en sí para representar matriz. 726 00:59:43,960 --> 00:59:53,730 Pero cuando hago algo como int * p = array, ahora que p es un puntero que apunta a la matriz, 727 00:59:53,730 --> 00:59:57,830 y ahora p en realidad no existe en la pila. 728 00:59:57,830 --> 01:00:01,950 Soy libre para cambiar p. Que puedo hacer p = malloc. 729 01:00:01,950 --> 01:00:06,500 Por lo tanto, inicialmente señaló a la matriz, y ahora apunta a un cierto espacio en el montón. 730 01:00:06,500 --> 01:00:09,620 No puedo hacer array = malloc. 731 01:00:09,620 --> 01:00:13,710 Si Clang es inteligente, se me grites la derecha del palo. 732 01:00:17,000 --> 01:00:21,430 De hecho, estoy bastante seguro de gcc lo haría también. 733 01:00:21,430 --> 01:00:25,010 Así que tipo de matriz 'int [5]' no es asignable. 734 01:00:25,010 --> 01:00:28,040 No se puede asignar algo a un tipo de matriz 735 01:00:28,040 --> 01:00:30,500 porque la matriz es simplemente una constante. 736 01:00:30,500 --> 01:00:34,760 Es un símbolo que hace referencia a esos 20 bytes. No lo puedo cambiar. 737 01:00:34,760 --> 01:00:37,690 >> [Estudiante] ¿Y dónde está el tamaño de la matriz almacenada? 738 01:00:37,690 --> 01:00:40,670 [Bowden] No se almacena en cualquier lugar. Es cuando está compilando. 739 01:00:40,670 --> 01:00:46,310 Entonces, ¿dónde está el tamaño de la matriz almacenada? 740 01:00:46,310 --> 01:00:51,870 Sólo se puede utilizar sizeof (array) dentro de la función que la matriz se haya declarado. 741 01:00:51,870 --> 01:01:03,150 Así que si hago alguna función, foo, y lo hago (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 y luego por aquí me llaman foo (array); 744 01:01:21,330 --> 01:01:24,840 dentro de esta función - vamos a ejecutarlo. 745 01:01:34,200 --> 01:01:36,840 Se trata de ser inteligente Clang nuevo. 746 01:01:36,840 --> 01:01:43,890 Me está diciendo que sizeof parámetro de matriz en función 747 01:01:43,890 --> 01:01:46,690 volverá tamaño de 'int'. 748 01:01:46,690 --> 01:01:55,150 Esto sería un error si no es lo que yo quería que sucediera. 749 01:01:55,150 --> 01:01:58,960 Vamos realmente apagar Werror. 750 01:02:14,950 --> 01:02:17,590 Advertencia. Las advertencias están bien. 751 01:02:17,590 --> 01:02:19,960 Todavía se compilará el tiempo que tiene una advertencia. 752 01:02:19,960 --> 01:02:22,910 . / A.out va a imprimir 4. 753 01:02:22,910 --> 01:02:28,650 La advertencia que se ha generado es un indicador claro de lo que salió mal. 754 01:02:28,650 --> 01:02:34,120 Esta matriz int es sólo va a imprimir sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Incluso si pongo matriz [5] aquí, sigue siendo sólo va a imprimir sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Así que tan pronto como usted lo pasa a una función, la distinción entre matrices y punteros 757 01:02:47,440 --> 01:02:49,670 es inexistente. 758 01:02:49,670 --> 01:02:52,640 Esto pasa a ser una matriz que se declaró en la pila, 759 01:02:52,640 --> 01:02:58,300 pero tan pronto como se pasa ese valor, que 0xbf bla, bla, bla, en esta función, 760 01:02:58,300 --> 01:03:03,350 a continuación, este puntero apunta a la matriz en la pila. 761 01:03:03,350 --> 01:03:08,310 Así que eso significa que sizeof sólo se aplica en la función que el conjunto fue declarado, 762 01:03:08,310 --> 01:03:11,230 lo que significa que cuando se está compilando esta función, 763 01:03:11,230 --> 01:03:17,330 Clang cuando pasa a través de esta función, ve matriz es una matriz de int tamaño 5. 764 01:03:17,330 --> 01:03:20,640 Así lo ve sizeof (array). Bueno, eso es 20. 765 01:03:20,640 --> 01:03:26,440 Eso es en realidad cómo sizeof básicamente funciona para casi todos los casos. 766 01:03:26,440 --> 01:03:31,150 Sizeof no es una función, es un operador. 767 01:03:31,150 --> 01:03:33,570 No llame a la función sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), el compilador sólo la va a traducir a 4. 769 01:03:41,480 --> 01:03:43,700 ¿Lo tienes? Bien. 770 01:03:43,700 --> 01:03:47,520 >> [Estudiante] ¿Cuál es la diferencia entre sizeof (array) de principal y en foo? 771 01:03:47,520 --> 01:03:52,840 Esto se debe a que estamos diciendo sizeof (array), que es de tipo int *, 772 01:03:52,840 --> 01:03:57,120 mientras que la matriz de aquí abajo no es de tipo int *, es una matriz int. 773 01:03:57,120 --> 01:04:04,540 >> [Estudiante] Así que si usted tenía el parámetro de matriz [] en lugar de la matriz * int, 774 01:04:04,540 --> 01:04:09,230 ¿significa que todavía podría cambiar matriz porque ahora es un puntero? 775 01:04:09,230 --> 01:04:14,250 [Bowden] De esta manera? >> [Estudiante] Yeah. ¿Se puede cambiar array dentro de la función ahora? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Usted podría cambiar la matriz en ambos casos. 777 01:04:18,420 --> 01:04:23,130 En ambos casos, usted es libre de decir array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Estudiante] ¿Pero puede usted hacer punto matriz a otra cosa? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Si. En cualquiera de los casos - >> [estudiante] Yeah. 780 01:04:30,230 --> 01:04:38,410 [Bowden] La distinción entre array [] y una matriz int *, no hay ninguno. 781 01:04:38,410 --> 01:04:42,570 También puede obtener algunos matriz multidimensional aquí 782 01:04:42,570 --> 01:04:47,050 por alguna sintaxis conveniente, pero todavía es sólo un indicador. 783 01:04:47,050 --> 01:04:56,400 Esto quiere decir que soy libre de hacer array = malloc (sizeof (int)), y ahora apuntan a otro lugar. 784 01:04:56,400 --> 01:04:59,610 Pero al igual que cómo esto funciona siempre y siempre, 785 01:04:59,610 --> 01:05:03,210 cambiar esta matriz haciendo que apunte a otra cosa 786 01:05:03,210 --> 01:05:07,570 no cambia esta matriz por aquí porque es una copia del argumento, 787 01:05:07,570 --> 01:05:10,780 no es un puntero a ese argumento. 788 01:05:10,780 --> 01:05:16,070 Y de hecho, así como la indicación más de que es exactamente lo mismo - 789 01:05:16,070 --> 01:05:21,100 ya hemos visto lo que se imprime la matriz de impresión - 790 01:05:21,100 --> 01:05:31,410 lo que si imprimimos la dirección de la matriz o la dirección de la dirección de la matriz 791 01:05:31,410 --> 01:05:36,290 a cualquiera de esos? 792 01:05:41,770 --> 01:05:45,220 Vamos a pasar por alto esto. 793 01:05:48,140 --> 01:05:51,660 Bien. Esto está bien. Ahora está en marcha. / A.out. 794 01:05:51,660 --> 01:06:00,220 Matriz de impresión, y luego imprimir la dirección de la matriz, son la misma cosa. 795 01:06:00,220 --> 01:06:02,870 Matriz simplemente no existe. 796 01:06:02,870 --> 01:06:08,190 Se sabe cuando va a imprimir array, que está imprimiendo el símbolo que se refiere a esos 20 bytes. 797 01:06:08,190 --> 01:06:11,940 Impresión de la dirección de la matriz, así, la matriz no existe. 798 01:06:11,940 --> 01:06:17,200 No tiene una dirección, por lo que sólo imprime la dirección de esos 20 bytes. 799 01:06:20,820 --> 01:06:28,150 Tan pronto como se compila hacia abajo, como en su buggy4 compilado. / A.out, 800 01:06:28,150 --> 01:06:30,340 matriz es inexistente. 801 01:06:30,340 --> 01:06:33,640 Punteros existe. Las matrices no. 802 01:06:34,300 --> 01:06:38,060 Los bloques de memoria que representa el conjunto todavía existe, 803 01:06:38,060 --> 01:06:43,270 pero la matriz de variables y variables de ese tipo no existen. 804 01:06:46,260 --> 01:06:50,270 Esos son como las principales diferencias entre las matrices y punteros 805 01:06:50,270 --> 01:06:55,590 están tan pronto como usted haga llamadas a funciones, no hay ninguna diferencia. 806 01:06:55,590 --> 01:07:00,460 Pero dentro de la función que la propia matriz se declara, sizeof funciona de forma diferente 807 01:07:00,460 --> 01:07:05,190 ya que va a imprimir el tamaño de los bloques en lugar de el tamaño del tipo, 808 01:07:05,190 --> 01:07:08,950 y no se puede cambiar porque es un símbolo. 809 01:07:08,950 --> 01:07:14,370 Impresión de la cosa y la dirección de la cosa imprime la misma cosa. 810 01:07:14,370 --> 01:07:18,480 Y eso es más o menos la misma. 811 01:07:18,480 --> 01:07:20,820 [Estudiante] ¿Podría usted decir que una vez más? 812 01:07:21,170 --> 01:07:24,170 Me podría haber pasado algo por alto. 813 01:07:24,170 --> 01:07:29,260 Matriz de impresión y la dirección de la matriz imprime la misma cosa, 814 01:07:29,260 --> 01:07:33,180 mientras que si se imprime un puntero frente a la dirección del puntero, 815 01:07:33,180 --> 01:07:36,010 la única cosa que imprime la dirección de lo que estás señalando, 816 01:07:36,010 --> 01:07:40,360 el otro imprime la dirección del puntero en la pila. 817 01:07:40,360 --> 01:07:47,040 Puede cambiar un puntero, no se puede cambiar un símbolo de matriz. 818 01:07:47,740 --> 01:07:53,270 Y puntero sizeof se va a imprimir el tamaño de ese tipo de puntero. 819 01:07:53,270 --> 01:07:57,470 Así int * p sizeof (p) va a imprimir 4, 820 01:07:57,470 --> 01:08:04,110 pero int array [5] impresión sizeof (array) se va a imprimir 20. 821 01:08:04,110 --> 01:08:07,480 [Estudiante] Así int array [5] se imprimirán 20? Sí >>. 822 01:08:07,480 --> 01:08:13,300 Es por eso que dentro de buggy4 cuando lo que solía ser sizeof (array) 823 01:08:13,300 --> 01:08:16,660 esto hacía yo <20, que no es lo que queríamos. 824 01:08:16,660 --> 01:08:20,880 Queremos i <5. >> [Estudiante] Bueno. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Y luego, tan pronto como usted comience a pasar en las funciones, 826 01:08:25,569 --> 01:08:34,340 si lo hiciéramos int * p = array; 827 01:08:34,340 --> 01:08:39,779 dentro de esta función, que básicamente puede utilizar p y matriz en exactamente las mismas formas, 828 01:08:39,779 --> 01:08:43,710 excepto por el problema sizeof y el problema cambiando. 829 01:08:43,710 --> 01:08:49,810 Pero p [0] = 1; es lo mismo que decir array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Y tan pronto como decimos foo (array), o foo (p); 831 01:08:55,600 --> 01:08:59,760 dentro de la función foo, esta es la misma llamada dos veces. 832 01:08:59,760 --> 01:09:03,350 No hay ninguna diferencia entre estas dos llamadas. 833 01:09:07,029 --> 01:09:11,080 >> Todo el mundo bueno en eso? Bien. 834 01:09:14,620 --> 01:09:17,950 Tenemos 10 minutos. 835 01:09:17,950 --> 01:09:28,319 >> Vamos a tratar de conseguir a través de este programa Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 Este sitio web, que salió el año pasado o algo así. 837 01:09:34,149 --> 01:09:41,100 Es sólo supone que es como se escribe al azar y se imprime - 838 01:09:41,100 --> 01:09:46,729 Cualquiera que sea el archivo que resulta haber cargado es lo que parece que está escribiendo. 839 01:09:46,729 --> 01:09:52,069 Parece una especie de código del sistema operativo. 840 01:09:53,760 --> 01:09:56,890 Eso es lo que queremos llevar a cabo. 841 01:10:08,560 --> 01:10:11,690 Usted debe tener un binario ejecutable llamado hacker_typer 842 01:10:11,690 --> 01:10:14,350 que lleva en un solo argumento, el archivo de "tipo hacker." 843 01:10:14,350 --> 01:10:16,480 Ejecutar el ejecutable debe borrar la pantalla 844 01:10:16,480 --> 01:10:20,850 y luego imprimir un carácter del fichero pasado como cada vez que el usuario pulsa una tecla. 845 01:10:20,850 --> 01:10:24,990 Asi que cualquier tecla que pulse, se debe desechar y en su lugar muestra un personaje del archivo 846 01:10:24,990 --> 01:10:27,810 que es el argumento. 847 01:10:29,880 --> 01:10:34,350 Yo casi le dirá cuáles son las cosas que vamos a necesitar saber lo son. 848 01:10:34,350 --> 01:10:36,440 Pero queremos revisar la biblioteca termios. 849 01:10:36,440 --> 01:10:44,840 Nunca he utilizado esta biblioteca en toda mi vida, lo que tiene efectos muy mínimos. 850 01:10:44,840 --> 01:10:48,610 Pero esto va a ser la biblioteca se puede utilizar para desechar el carácter que golpeó 851 01:10:48,610 --> 01:10:52,390 cuando se está escribiendo en estándar pulg 852 01:10:56,970 --> 01:11:05,840 Así hacker_typer.c, y vamos a querer incluir # . 853 01:11:05,840 --> 01:11:12,870 En cuanto a la página del manual de termios - estoy adivinando que la terminal OS o algo así - 854 01:11:12,870 --> 01:11:16,240 No sé cómo leerlo. 855 01:11:16,240 --> 01:11:21,040 En cuanto a esto, se dice para incluir estos dos archivos, por lo que vamos a hacer eso. 856 01:11:37,620 --> 01:11:46,820 >> Primero lo primero, queremos tomar en un solo argumento, que es el archivo que debe abrirse. 857 01:11:46,820 --> 01:11:52,420 Entonces, ¿qué es lo que quiero hacer? ¿Cómo puedo comprobar que tengo un solo argumento? 858 01:11:52,420 --> 01:11:56,480 [Estudiante] Si argc es igual. >> [Bowden] Yeah. 859 01:11:56,480 --> 01:12:21,250 Así que si (argc = 2!) Printf ("Uso:% s [archivo para abrir]"). 860 01:12:21,250 --> 01:12:32,750 Así que ahora si me quedo, sin aportar un segundo argumento - oh, necesito la nueva línea - 861 01:12:32,750 --> 01:12:36,240 verás que dice uso:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 y luego el segundo argumento debe ser el archivo que desea abrir. 863 01:12:58,430 --> 01:13:01,260 ¿Y ahora qué hago? 864 01:13:01,260 --> 01:13:08,490 Quiero leer de este archivo. ¿Cómo puedo leer un archivo? 865 01:13:08,490 --> 01:13:11,920 [Estudiante] Usted abrirlo primero. Sí >>. 866 01:13:11,920 --> 01:13:15,010 Así fopen. ¿Qué fopen parece? 867 01:13:15,010 --> 01:13:22,980 [Estudiante] Nombre de archivo. >> [Bowden] Nombre del archivo que va a ser argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Estudiante] Y entonces, ¿qué quieres hacer con él, así que el - >> [Bowden] Yeah. 869 01:13:26,110 --> 01:13:28,740 Así que si no se acordaba, se podía hacer fopen hombre, 870 01:13:28,740 --> 01:13:32,960 donde va a ser un camino const char * donde ruta es nombre de archivo, 871 01:13:32,960 --> 01:13:34,970 modo const char *. 872 01:13:34,970 --> 01:13:38,660 Si por casualidad usted no recuerda qué modo es así, entonces usted puede buscar el modo. 873 01:13:38,660 --> 01:13:44,660 En el interior de las páginas de manual, el carácter de barra es lo que puede utilizar para buscar las cosas. 874 01:13:44,660 --> 01:13:49,790 Así que escribir / mode para buscar el modo. 875 01:13:49,790 --> 01:13:57,130 ny N son lo que usted puede utilizar para desplazarse por las coincidencias de búsqueda. 876 01:13:57,130 --> 01:13:59,800 Aquí se dice que los argumento modo apunta a una cadena 877 01:13:59,800 --> 01:14:01,930 comenzando con una de las secuencias siguientes. 878 01:14:01,930 --> 01:14:06,480 Así que r, archivo de texto abierto para la lectura. Eso es lo que quiero hacer. 879 01:14:08,930 --> 01:14:13,210 Para leer, y quiero guardar eso. 880 01:14:13,210 --> 01:14:18,720 La cosa va a ser un archivo *. Ahora, ¿qué es lo que quiero hacer? 881 01:14:18,720 --> 01:14:21,200 Dame un segundo. 882 01:14:28,140 --> 01:14:30,430 Bien. Ahora, ¿qué es lo que quiero hacer? 883 01:14:30,430 --> 01:14:32,940 [Estudiante] Compruebe si es NULL. >> [Bowden] Yeah. 884 01:14:32,940 --> 01:14:38,690 Cada vez que se abre un archivo, asegúrese de que usted es capaz con éxito para abrirlo. 885 01:14:58,930 --> 01:15:10,460 >> Ahora quiero hacer esas cosas termios donde quiero leer primero la configuración actual 886 01:15:10,460 --> 01:15:14,050 y salvar a aquellos en algo, entonces quiero cambiar mi configuración 887 01:15:14,050 --> 01:15:19,420 tirar a la basura cualquier personaje que me escriba, 888 01:15:19,420 --> 01:15:22,520 y luego quiero actualizar esos valores. 889 01:15:22,520 --> 01:15:27,250 Y luego, al final del programa, quiero volver a mi configuración original. 890 01:15:27,250 --> 01:15:32,080 Así que la estructura va a ser de termios tipo, y lo voy a querer a dos de ellos. 891 01:15:32,080 --> 01:15:35,600 La primera de ellas va a ser mi current_settings, 892 01:15:35,600 --> 01:15:42,010 y luego van a ser mis hacker_settings. 893 01:15:42,010 --> 01:15:48,070 En primer lugar, voy a querer guardar la configuración actual, 894 01:15:48,070 --> 01:15:53,790 entonces voy a querer actualizar hacker_settings, 895 01:15:53,790 --> 01:16:01,570 y después camino al final de mi programa, quiero volver a la configuración actual. 896 01:16:01,570 --> 01:16:08,660 Así que guardar la configuración actual, la forma en que funciona, termios hombre. 897 01:16:08,660 --> 01:16:15,810 Vemos que tenemos este tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Paso en una estructura termios por su puntero. 899 01:16:22,960 --> 01:16:30,640 La forma en que se verá es - HE olvidado ya lo que la función fue llamada. 900 01:16:30,640 --> 01:16:34,930 Copiar y pegar. 901 01:16:39,150 --> 01:16:45,500 Así tcgetattr, entonces quiero pasar en la estructura que estoy ahorrando la información, 902 01:16:45,500 --> 01:16:49,650 que va a ser current_settings, 903 01:16:49,650 --> 01:16:59,120 y el primer argumento es el descriptor de archivo para lo que quiero para guardar los atributos de. 904 01:16:59,120 --> 01:17:04,360 ¿Qué es el descriptor de archivo es como cada vez que abra un archivo, se obtiene un descriptor de archivo. 905 01:17:04,360 --> 01:17:14,560 Cuando fopen argv [1], se obtiene un descriptor de fichero que se hace referencia 906 01:17:14,560 --> 01:17:16,730 cada vez que se desea leer o escribir en él. 907 01:17:16,730 --> 01:17:19,220 Ese no es el descriptor de archivo que desea utilizar aquí. 908 01:17:19,220 --> 01:17:21,940 Hay tres descriptores de archivo que tiene por defecto, 909 01:17:21,940 --> 01:17:24,310 que son estándar, salida de estándar y el error estándar. 910 01:17:24,310 --> 01:17:29,960 Por defecto, creo que es estándar en es 0, la salida estándar es 1, y el error estándar es de 2. 911 01:17:29,960 --> 01:17:33,980 Entonces, ¿qué es lo que quiero cambiar la configuración de? 912 01:17:33,980 --> 01:17:37,370 Quiero cambiar la configuración de cada vez que me tocó un personaje, 913 01:17:37,370 --> 01:17:41,590 Quiero que tirar ese carácter inmediato en lugar de imprimirlo en la pantalla. 914 01:17:41,590 --> 01:17:45,960 ¿Qué corriente - standard in, out estándar o error estándar - 915 01:17:45,960 --> 01:17:52,050 responde a las cosas cuando escribo en el teclado? >> [Estudiante] Standard pulg >> Yeah. 916 01:17:52,050 --> 01:17:56,450 Así que puede hacer de 0 o yo podamos hacer stdin. 917 01:17:56,450 --> 01:17:59,380 Me estoy poniendo el estándar de current_settings pulg 918 01:17:59,380 --> 01:18:01,720 >> Ahora quiero actualizar esos valores, 919 01:18:01,720 --> 01:18:07,200 lo primero que voy a copiar en hacker_settings lo que mis current_settings son. 920 01:18:07,200 --> 01:18:10,430 ¿Y cómo es el trabajo structs se acaba de copiar. 921 01:18:10,430 --> 01:18:14,510 Esto copia todos los campos, como era de esperar. 922 01:18:14,510 --> 01:18:17,410 >> Ahora quiero actualizar algunos de los campos. 923 01:18:17,410 --> 01:18:21,670 En cuanto a termios, usted tendría que leer a través de una gran cantidad de este 924 01:18:21,670 --> 01:18:24,110 sólo para ver lo que usted quiere buscar, 925 01:18:24,110 --> 01:18:28,210 pero las banderas que usted va a querer tener en cuenta son eco, 926 01:18:28,210 --> 01:18:33,110 así ECHO Echo caracteres de entrada. 927 01:18:33,110 --> 01:18:37,710 En primer lugar quiero dejar - HE olvidado ya lo que los campos son. 928 01:18:45,040 --> 01:18:47,900 Esto es lo que la estructura se parece. 929 01:18:47,900 --> 01:18:51,060 Así modos de entrada Creo que desee cambiar. 930 01:18:51,060 --> 01:18:54,210 Veremos la solución para asegurarse de que es lo que queremos cambiar. 931 01:19:04,060 --> 01:19:12,610 Queremos cambiar lflag con el fin de evitar tener que buscar a través de todos estos. 932 01:19:12,610 --> 01:19:14,670 Queremos cambiar los modos locales. 933 01:19:14,670 --> 01:19:17,710 Usted tendría que leer toda esta cosa a entender que todo pertenece 934 01:19:17,710 --> 01:19:19,320 que queremos cambiar. 935 01:19:19,320 --> 01:19:24,120 Pero es en el interior de los modos locales donde vamos a querer cambiar eso. 936 01:19:27,080 --> 01:19:33,110 Así hacker_settings.cc_lmode es lo que se llama. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Aquí es donde nos metemos en los operadores bit a bit. 939 01:19:52,280 --> 01:19:54,860 Estamos un poco fuera de tiempo, pero vamos a ir a través de él muy rápido. 940 01:19:54,860 --> 01:19:56,600 Aquí es donde nos metemos en los operadores bit a bit, 941 01:19:56,600 --> 01:19:59,950 donde creo que dije una vez hace mucho tiempo que cada vez que empezar a tratar con banderas, 942 01:19:59,950 --> 01:20:03,370 usted va a estar utilizando el operador bit a bit mucho. 943 01:20:03,370 --> 01:20:08,240 Cada bit de la bandera corresponde a algún tipo de comportamiento. 944 01:20:08,240 --> 01:20:14,090 Así que aquí, este indicador tiene un montón de cosas diferentes, donde todos ellos significan algo diferente. 945 01:20:14,090 --> 01:20:18,690 Pero lo que quiero hacer es apagar el bit que corresponde a ECHO. 946 01:20:18,690 --> 01:20:25,440 Así que para apagar eso que hago y = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 En realidad, creo que es como techo o algo así. Voy a comprobar de nuevo. 948 01:20:30,110 --> 01:20:34,050 Puedo termios. Es sólo ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO va a ser un solo bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO va a significar que todos los bits están puestos a 1, lo que significa que todos los indicadores se establecen en true 951 01:20:44,230 --> 01:20:47,140 excepto para el bit de ECHO. 952 01:20:47,140 --> 01:20:53,830 Al poner fin a mis banderas cercanas con esto, significa todas las banderas que están establecidas actualmente en true 953 01:20:53,830 --> 01:20:56,520 Todavía se establece en true. 954 01:20:56,520 --> 01:21:03,240 Si mi bandera ECHO se establece en true, entonces este es necesariamente establece en false en la bandera ECHO. 955 01:21:03,240 --> 01:21:07,170 Así que esta línea de código sólo se apaga el indicador de ECHO. 956 01:21:07,170 --> 01:21:16,270 Las otras líneas de código, sólo voy a copiarlos en el interés de tiempo y luego explicarlos. 957 01:21:27,810 --> 01:21:30,180 En la solución, dice 0. 958 01:21:30,180 --> 01:21:33,880 Es probable que sea mejor decir explícitamente stdin. 959 01:21:33,880 --> 01:21:42,100 >> Tenga en cuenta que también estoy haciendo ECHO | ICANON aquí. 960 01:21:42,100 --> 01:21:46,650 ICANON se refiere a algo distinto, es decir, el modo canónico. 961 01:21:46,650 --> 01:21:50,280 ¿Qué significa el modo canónico es por lo general cuando se está escribiendo la línea de comandos, 962 01:21:50,280 --> 01:21:54,670 estándar no procesa nada hasta que llegues nueva línea. 963 01:21:54,670 --> 01:21:58,230 Así que cuando usted GetString, escribe un montón de cosas, entonces usted golpea nueva línea. 964 01:21:58,230 --> 01:22:00,590 Fue entonces cuando se envía al estándar pulg 965 01:22:00,590 --> 01:22:02,680 Ese es el valor predeterminado. 966 01:22:02,680 --> 01:22:05,830 Cuando desactive el modo canónico, ahora cada personaje pulsa 967 01:22:05,830 --> 01:22:10,910 es lo que se procesa, que suele ser un poco mal porque es lento para procesar estas cosas, 968 01:22:10,910 --> 01:22:14,330 por lo que es bueno para amortiguar en líneas enteras. 969 01:22:14,330 --> 01:22:16,810 Pero quiero que cada personaje para ser procesado 970 01:22:16,810 --> 01:22:18,810 ya que no quiero que me esperes para golpear de nueva línea 971 01:22:18,810 --> 01:22:21,280 antes de procesar todos los personajes que he estado escribiendo. 972 01:22:21,280 --> 01:22:24,760 Esto desactiva el modo canónico. 973 01:22:24,760 --> 01:22:31,320 Estas cosas sólo quiere decir cuando en realidad procesa caracteres. 974 01:22:31,320 --> 01:22:35,830 Esto significa procesar de inmediato, tan pronto como les estoy escribiendo, procesarlos. 975 01:22:35,830 --> 01:22:42,510 Y esta es la función que está actualizando mi configuración estándar para adentro, 976 01:22:42,510 --> 01:22:45,480 y medios TCSA hacerlo ahora mismo. 977 01:22:45,480 --> 01:22:50,310 Las otras opciones son esperar a que todo lo que se encuentra actualmente en la corriente se procesa. 978 01:22:50,310 --> 01:22:52,030 Eso realmente no importa. 979 01:22:52,030 --> 01:22:56,920 Justo en este momento puede cambiar mi configuración para ser lo que actualmente se encuentra en hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Supongo que lo llamó hacker_settings, así que vamos a cambiar eso. 981 01:23:09,610 --> 01:23:13,500 Cambiar todo para hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Ahora, al final de nuestro programa vamos a querer volver 983 01:23:16,870 --> 01:23:20,210 a lo que es en la actualidad dentro de normal_settings, 984 01:23:20,210 --> 01:23:26,560 que se va a ver igual y normal_settings. 985 01:23:26,560 --> 01:23:30,650 Tenga en cuenta que no he cambiado ninguna de mis normal_settings ya que originalmente consiguiendo. 986 01:23:30,650 --> 01:23:34,520 Entonces para simplemente cambiar de nuevo, les pasa de nuevo al final. 987 01:23:34,520 --> 01:23:38,390 Esta fue la actualización. Bien. 988 01:23:38,390 --> 01:23:43,900 >> Ahora dentro de aquí sólo voy a explicar el código en aras del tiempo. 989 01:23:43,900 --> 01:23:46,350 No es que mucho código. 990 01:23:50,770 --> 01:24:03,750 Vemos, leemos un carácter del archivo. Lo llamamos f. 991 01:24:03,750 --> 01:24:07,850 Ahora usted puede el hombre fgetc, pero ¿cómo fgetc va a funcionar 992 01:24:07,850 --> 01:24:11,910 sólo se va a devolver el carácter que usted acaba de leer o EOF, 993 01:24:11,910 --> 01:24:15,680 que se corresponde con el final del archivo o algún suceso de error. 994 01:24:15,680 --> 01:24:19,900 Estamos bucle, sin dejar de leer un solo carácter de los autos, 995 01:24:19,900 --> 01:24:22,420 hasta que nos hemos quedado sin caracteres a leer. 996 01:24:22,420 --> 01:24:26,650 Y ya que estamos haciendo eso, esperamos en un solo carácter de norma pulg 997 01:24:26,650 --> 01:24:29,090 Cada vez que escriba algo en la línea de comandos, 998 01:24:29,090 --> 01:24:32,820 que está leyendo en un personaje de nivel pulg 999 01:24:32,820 --> 01:24:38,330 Entonces putchar es sólo va a poner el carbón leemos aquí arriba desde el archivo de salida estándar. 1000 01:24:38,330 --> 01:24:42,890 Puede putchar hombre, pero es sólo poner en la salida estándar, se imprime ese carácter. 1001 01:24:42,890 --> 01:24:51,600 También puede simplemente hacer printf ("% c", c); La misma idea. 1002 01:24:53,330 --> 01:24:56,670 Eso va a hacer la mayor parte de nuestro trabajo. 1003 01:24:56,670 --> 01:25:00,300 >> Lo último que vas a querer hacer es fclose nuestro archivo. 1004 01:25:00,300 --> 01:25:03,310 Si no fclose, eso es una pérdida de memoria. 1005 01:25:03,310 --> 01:25:06,680 Queremos fclose el archivo que se abrió originalmente, y creo que eso es todo. 1006 01:25:06,680 --> 01:25:13,810 Si hacemos eso, yo ya tengo problemas. 1007 01:25:13,810 --> 01:25:17,260 Vamos a ver. 1008 01:25:17,260 --> 01:25:19,960 ¿Qué es lo que quejarse? 1009 01:25:19,960 --> 01:25:30,220 Se esperaba 'int' pero el argumento es de tipo 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Vamos a ver si eso funciona. 1011 01:25:45,210 --> 01:25:53,540 Sólo permitido en C99. Augh. Está bien, hacer hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Ahora tenemos descripciones más útiles. 1013 01:25:57,760 --> 01:25:59,900 Por lo tanto el uso de identificador no declarado "normal_settings '. 1014 01:25:59,900 --> 01:26:04,170 Yo no lo llamó normal_settings. Lo llamé current_settings. 1015 01:26:04,170 --> 01:26:12,090 Así que vamos a cambiar todo eso. 1016 01:26:17,920 --> 01:26:21,710 Ahora pasa argumento. 1017 01:26:26,290 --> 01:26:29,500 Voy a hacer esto 0 por ahora. 1018 01:26:29,500 --> 01:26:36,720 Bien. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Yo también no borrar la pantalla al principio. 1020 01:26:39,590 --> 01:26:42,960 Pero usted puede mirar hacia atrás al conjunto último problema para ver cómo limpiar la pantalla. 1021 01:26:42,960 --> 01:26:45,160 Es simplemente imprimir algunos caracteres 1022 01:26:45,160 --> 01:26:47,210 mientras que esto está haciendo lo que quiero hacer. 1023 01:26:47,210 --> 01:26:48,900 Bien. 1024 01:26:48,900 --> 01:26:55,280 Y pensando en por qué esto tenía que ser 0 en lugar de la entrada estándar, 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 queja de que - 1027 01:27:13,150 --> 01:27:19,360 Antes, cuando he dicho que no hay descriptores de archivo, pero luego también tienes tu * FILE, 1028 01:27:19,360 --> 01:27:23,210 un descriptor de archivo es sólo un único número entero, 1029 01:27:23,210 --> 01:27:26,970 mientras que un FILE * tiene un montón de cosas asociada a ella. 1030 01:27:26,970 --> 01:27:30,380 La razón por la que tenemos que decir 0 en lugar de la entrada estándar 1031 01:27:30,380 --> 01:27:37,480 es que stdin es un FILE * que apunta a lo que hace referencia descriptor de archivo 0. 1032 01:27:37,480 --> 01:27:45,070 Así que hasta aquí cuando hago fopen (argv [1], me estoy poniendo un * archivo de nuevo. 1033 01:27:45,070 --> 01:27:51,180 Pero en algún lugar en que * FILE es una cosa que corresponde al descriptor de archivo para el archivo. 1034 01:27:51,180 --> 01:27:57,430 Si nos fijamos en la página del manual de abierto, así que creo que tendré que hacer man 3 abierto - No. - 1035 01:27:57,430 --> 01:27:59,380 man 2 abierto - sí. 1036 01:27:59,380 --> 01:28:06,250 Si nos fijamos en la página de abierto, abierto es como un fopen de nivel inferior, 1037 01:28:06,250 --> 01:28:09,350 y se devuelve el descriptor de archivo real. 1038 01:28:09,350 --> 01:28:12,050 fopen hace un montón de cosas sobre abierto, 1039 01:28:12,050 --> 01:28:17,640 que en lugar de devolver sólo el descriptor de fichero devuelve un archivo completo puntero * 1040 01:28:17,640 --> 01:28:20,590 dentro de los cuales es nuestro descriptor de archivo pequeño. 1041 01:28:20,590 --> 01:28:25,020 Así estándar se refiere a la cosa * FILE, 1042 01:28:25,020 --> 01:28:29,120 mientras que 0 se refiere sólo a la norma descriptor de fichero en sí mismo. 1043 01:28:29,120 --> 01:28:32,160 >> ¿Preguntas? 1044 01:28:32,160 --> 01:28:35,930 [Risas] sopló a través de eso. 1045 01:28:35,930 --> 01:28:39,140 Está bien. Hemos terminado. [Risas] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]