DAVID MALAN: Muy bien, bienvenida de nuevo. Este es CS50. Este es el comienzo de la séptima semana. Así que ha sido un tiempo, así que pensamos que sería mejor tomar un viaje relámpago de dónde estamos dejamos y donde ahora vamos. Así que esta cosa aquí podría tener causado cierta angustia al principio. Pero es de esperar, que está empezando a aclimatarse a lo que esto denota aquí - estrella que representa un puntero, que es justo lo que, en términos más sencillos? Así que es una dirección. Así que es la dirección de algo en la memoria. Y empezamos a pelar las capas Hace un par de semanas, las cosas como GetString y otras funciones similares todo este tiempo han estado volviendo direcciones de las cosas en la memoria, como el dirección del primer carácter en alguna secuencia. Así también introdujimos valgrind, que usted comenzará a utilizar para este problema establecer, en particular para la próxima problema configurado así. Y valgrind hace lo que para nosotros? Comprueba si hay fugas de memoria, y También comprueba que hay abuso de la memoria. Se puede, con cierta probabilidad, detectar si su código va a tocar de memoria que simplemente no debería. Así que no es necesariamente una fuga, pero si ir más allá de las fronteras de algunos matriz, y en realidad se ejecuta valgrind e inducir a que el comportamiento, mientras que valgrind se está ejecutando en su programa es se ejecuta dentro de la misma, obtendrá mensajes como este - "escritura no válido de tamaño 4 ", el cual, recordar un par de Hace semanas significaba que tenía accidentalmente como en un int demasiado más allá de los límites de una matriz. Y lo que el tamaño 4 significa que aquí el tamaño de que int en particular. Así que toma consuelo en el hecho de que de salida de valgrind, el formato de la misma, es simplemente atroz. Es muy difícil ver a través del desorden para la información interesante. Así que lo que hemos hecho aquí es sólo extracto algunos de la pareja de más líneas interesantes. Pero darse cuenta de que el 80% de los de valgrind salida va a ser un poco de un distracción. Sólo tienes que buscar patrones como estos - derecho válido, no válido de lectura, 40 bytes y un número de bloques son definitivamente perdidos, palabras clave así. ¿Y qué te esperamos ver algo de tipo de rastro de lo que funcionará el error es en realidad pulg En este caso aquí, en qué línea de mi código fue el error aparentemente? 26 en un archivo llamado memory.c, que era el ejemplo que estábamos jugando con en el momento. Así que probablemente no está en malloc. Probablemente fue en mi código en su lugar. Así que vamos a ver esto de nuevo y de nuevo en poco tiempo. Así scanf, esto ocurrió en un par de formas hasta ahora. Vimos brevemente sscanf. Fue algo un número de que se zambulló en en su los preparativos para el concurso. Y scanf es en realidad lo que el CS50 biblioteca ha estado usando por debajo de la campana desde hace bastante tiempo con el fin para obtener la entrada del usuario. Por ejemplo, si me mudo a la CS50 Appliance aquí, déjame abrir una ejemplo hoy que se llama scanf-0.C Y es super simple. Son sólo unas pocas líneas de código. Pero demuestra realmente cómo getInt ha estado trabajando todo este tiempo. En este programa aquí, en la línea 16 , Noto que me declaro un int. Así que no hay punteros, nada mágico allí, sólo un int. Luego, en la línea 17, que incitan la usuario un número, por favor. Luego a finales de 18, yo uso scanf aquí. Y he especificado, algo así como printf, que estoy esperando la cita ciento unquote i. Así ciento i, por supuesto, denota un int. Pero note lo que el segundo argumento para scanf es. ¿Cómo describiría el segundo argumento después de la coma? ¿Qué es eso? Es la dirección de x. Así que esto es útil porque al proporcionar scanf con la dirección de x, lo que hace que permiten a esa función a hacer? No sólo tiene que ir allí, sino también hacer que? Realizar un cambio en él. Debido a que usted puede ir allí, es una especie de como un mapa a una ubicación en la memoria. Y así, siempre y cuando proporcione scanf, o cualquier función con dicho mapa, que función puede ir allí, y no sólo mirar el valor, sino que también puede cambiar ese valor, lo cual es útil si el propósito en la vida de scanf es escanear la entrada del usuario, en concreto desde el teclado. Y el f denota formato, al igual que printf, el f denota una formateada cadena que desea imprimir. Así que en resumen, esta línea 18 simplemente dice: tratar de leer un int del usuario teclado y guardarlo dentro de x, en cualquiera que sea la dirección x pasa a vivir en. Y luego, por último, la línea 19 se limita a decir, gracias por el int, en este caso. Así que permítanme seguir adelante y hacer esto. Así que scanf 0. Déjame ir adelante y agrandar Voy a correr con este puntos slash scanf 0. Número, por favor? 50. Gracias por el 50. Así que es bastante simple. Ahora ¿qué es lo que no hace? No está haciendo un montón de comprobación de errores. Por ejemplo, si yo no coopero, y yo no escribo en un número, pero vez que escribo algo así como "hola" eso es sólo un poco extraño. Y lo que una de las cosas que el CS50 biblioteca ha estado haciendo por nosotros durante algún tiempo es que reprompting y reprompting. La frase recordatorio reintento estaba en cs50.c, y esa es la razón por la que en getInt la biblioteca CS50 es en realidad un conjunto montón de líneas largas, porque estamos la comprobación de cosas estúpidas como esta. ¿El usuario no da nosotros, de hecho, un int? ¿Él o ella nos da algo como una letra del alfabeto? Si es así, queremos detectar eso y les gritan. Pero las cosas se ponen más interesantes en el siguiente ejemplo. Si voy a scanf-1.c, lo que es un Lo que ha cambiado fundamentalmente en el siguiente ejemplo? Estoy utilizando char *, por supuesto, en lugar de int. Así que esto es interesante, porque char *, recuerdo, en realidad es sólo la lo mismo que la cadena. Así que se siente como tal vez este es un super implementación simple de GetString. Pero he desprendió la capa de la biblioteca CS50, así que estoy llamar a este char * ahora. Así que vamos a ver a dónde, si en cualquier lugar, nos equivocamos. Línea 17 - Otra vez digo, por favor, dame algo, en este caso, una cadena. Y luego, en la línea siguiente, que yo llamo scanf, de nuevo, dándole un código de formato, pero esta vez por ciento s. Y después de este tiempo, yo soy dándole a amortiguar. Ahora noto, no estoy usando la y comercial. Pero ¿por qué es que probablemente está bien aquí? Porque lo que la barrera es ya? Ya es un puntero. Ya es una dirección. Y vamos a esta palabra "confundir", hágamelo simplemente llame que s, por ejemplo, para simplicidad. Pero yo he llamado a amortiguar porque en en general, en la programación, si usted tiene un trozo de memoria, que una cadena realmente justo es decir, que se podría llamar un buffer. Es un lugar para almacenar información. Al igual que en cosas como YouTube, cuando que están amortiguando, por así decirlo, que simplemente significa que es la descarga de los bits de Internet y guardarlos en un matriz local, una parte local de la memoria, de modo que se puede ver más adelante sin que saltar o colgar en que durante la reproducción. Así que hay un problema aquí, sin embargo, porque yo lo digo scanf, le espera una cadena del usuario. Aquí está la dirección de un trozo de memoria. Ponga esa cadena allí. ¿Por qué es que dan cota nos problemas, sin embargo? ¿Qué es eso? ¿Se me permite el acceso que parte de la memoria? Usted sabe, yo no lo sé. Debido a que se ha inicializado búfer a algo? En realidad no. Y lo que es lo que hemos estado llamando un valor basura, que no es una palabra formal. Simplemente significa que no tenemos idea de lo que los bits se encuentran dentro de los cuatro bytes que He asignado como tampón. No he llamado a malloc. Definitivamente no he llamado GetString. Entonces, ¿quién sabe lo que es en realidad dentro de tampón? Y sin embargo, diciendo scanf ciegamente, ir allí y poner lo que el usuario escribe. Entonces, ¿qué es probable que la causa en nuestro código si lo ejecutamos? Probablemente una violación de segmento. Tal vez no, pero probablemente un error de segmentación. Y digo tal vez no, porque a veces usted lo hace, a veces usted no recibe una violación de segmento. A veces sólo tener suerte, pero que es, sin embargo, va a ser un error en nuestro programa. Así que permítanme seguir adelante y compilar esto. Voy a hacerlo de la manera de la vieja escuela. Tablero Así clang 0, scanf-1, scanf-1.c, Intro. Vaya, demasiado vieja escuela. Vamos a ver. ¿Qué hice? Oh, char * buffer. Oh, gracias - Guardar, OK - muy vieja escuela. Muy bien, ha pasado un tiempo. Así que he acabo de salvar el archivo después de haciendo que temporal cambiar hace un momento. Y ahora que he compilado manualmente con Clang. Y ahora me voy a ir por delante y ejecutar scanf-1, Enter. Cadena por favor. Voy a escribir "hola." Y ahora, aquí es donde, francamente, printf CAN es un poco molesto. No es en realidad va a segfault en este caso. Printf es un poco especial porque se usa de manera muy comúnmente que esencialmente printf está haciendo Haznos un favor y hacer realidad, eso no es un puntero válido. Permítanme tomar sobre mí sólo de impresión en paréntesis nulo, incluso aunque no es necesariamente lo que nosotros mismos nos esperábamos. Así que no podemos inducir muy fácilmente un segfault con esto, pero está claro que no es el comportamiento que yo quería. ¿Y cuál es la solución simple? Pues bien, en scanf-2, permítanme proponer que en lugar de en realidad sólo la asignación de una char *, quiero ser un poco más inteligente sobre esto, y déjame asignar el búfer como una secuencia de 16 caracteres. Así que puedo hacer esto en un par de maneras. Absolutamente me vendría malloc. Pero yo puedo volver a la semana dos, cuando Sólo necesitaba un montón de personajes. Eso es sólo una matriz. Así que déjame en lugar redefino búfer a ser una matriz de 16 caracteres. Y ahora, cuando paso de búfer en - y esto es algo que no hicimos hablar en la segunda semana - pero se puede tratar a un array como aunque es una dirección. Técnicamente, como hemos visto, son un poco diferente. Pero scanf no le importará si se le pasa el nombre de un arreglo, ya que lo que Clang hará por nosotros es esencialmente tratar el nombre de esa matriz como la dirección de la porción de 16 bytes. Así que esto es mejor. Esto significa que ahora que puedo espero haga lo siguiente. Permítanme Alejar por un momento y no hacer scanf-2, compilado en Aceptar. Ahora déjame hacer conseguí slash scanf-2. Cadena por favor. "Hola." Y parecía funcionar esta vez. Pero alguien puede proponer un escenario en el que todavía no podría funcionar? ¿Sí? Algo más de 16 caracteres. Y, de hecho, podemos estar un poco más precisa. Algo más largo que 15 caracteres, porque realmente tenemos que tener en cuenta que necesitamos que el cero barra invertida implícitamente en el extremo de la cadena, que es un aparte scanf típicamente cuidar para nosotros. Así que déjame hacer algo así - A veces podemos simplemente dejarlo así. OK, así que ahora hemos inducidos nuestro fallo de segmentación. ¿Por qué? Debido a que he escrito más de 15 personajes, y por lo que hemos hecho memoria tocado que en realidad No debería haberlo hecho. Entonces, ¿qué es realmente la solución aquí? Bueno, ¿y si necesitamos una cadena más larga? Bueno, tal vez lo dejamos 32 bytes. Bueno, ¿y si eso no es suficiente? ¿Qué hay de 64 bytes? ¿Y si eso no es suficiente? ¿Qué hay de 128 o 200 bytes? Lo que realmente es la solución a este problema en el caso general, si no sabemos en avanzar en lo que el usuario va a escribir? Es sólo una especie de gran dolor en el culo, para ser honesto, que es la razón por la Biblioteca CS50 tiene unas pocas docenas de líneas de código que colectivamente implementar GetString cadena de una manera que no lo hacemos tiene que saber de antemano lo que el usuario va a escribir. En particular, si uno mira hacia atrás en cs50.c desde hace dos semanas, usted verá que GetString hace realidad No utilice scanf de esta manera. Más bien, se lee un carácter a la vez. Porque la única cosa buena acerca de la lectura de un personaje es lo que podemos garantizar nosotros mismos para siempre tener al menos un carbón de leña. Yo sólo puedo declarar un char y, a continuación, tomar estos pasos verdaderamente bebé a poco leer un carácter en a una tiempo desde el teclado. Y entonces, lo que verás GetString hace es cada vez que se queda sin, por ejemplo, 16 bytes de memoria, se utiliza malloc, o un primo de la misma, asignar más memoria, copia de la vieja memoria en la nueva, y luego arrastrándose junto, consiguiendo un carácter a la vez, y cuando se queda sin que trozo de memoria, lo tira, agarra un pedazo más grande de la memoria, copias de edad en nuevas y repeticiones. Y es realmente un dolor de realidad aplicar algo tan simple como obtener información de un usuario. Así que usted puede usar scanf. Puede utilizar otras funciones similares. Y un montón de libros de texto y en línea ejemplos hacen, pero son todos vulnerables a problemas como éste. Y en última instancia, conseguir un error de segmentación es un poco molesto. No es bueno para el usuario. Pero en el peor de los casos, lo que hace es fundamental poner su código en riesgo de? Algún tipo de ataque, potencialmente. Hablamos de uno de estos ataques - Desbordamiento de la pila. Pero en general, si se le permite desbordar un buffer, como lo hicimos una par de semanas atrás, con sólo escribir más que "hola" en la pila, tampoco puede asumir el control, potencialmente, un computadora, o por lo menos llegar a los datos que no pertenece a usted. Así que en resumen, es por eso que tenemos esas ruedas de entrenamiento. Pero ahora, empezamos a quitárselos, como nuestros programas ya no necesitan, necesariamente, la entrada del usuario. Pero en el caso del problema planteado seis, su aporte provendrá de una enorme archivo de diccionario con 150 algunos impares mil palabras. Así que usted no tendrá que preocuparse por entrada arbitraria del usuario. Le daremos algunos supuestos sobre ese archivo. ¿Tiene preguntas sobre punteros o scanf o la entrada del usuario en general? Muy bien, por lo que un rápido vistazo a continuación, en un arrastrando tema desde hace dos semanas. Y esa fue la idea de una estructura. No es que - esta noción de un estructura, que era lo que? Lo que sí struct hacer por nosotros? Definir - ¿Cómo? Definir un tipo variable. Así que en cierto modo. De hecho, estamos combinando dos temas. Así que con typedef, recordar que podemos declarar un tipo de los nuestros, como un sinónimo, como cadena para char *. Pero el uso de typedef struct y, podemos crear verdaderamente nuestras propias estructuras de datos. Por ejemplo, si voy de nuevo en gedit aquí sólo por un momento, y sigo adelante y hacer algo como, permítanme guardar esto como, digamos, STRUCTS.C temporalmente, sólo voy seguir adelante e incluir standardio.h, void main int. Y luego aquí, supongo que quiero para escribir un programa que almacena varios estudiantes de múltiples casas, por ejemplo. Así que es como un registrarial base de datos de algún tipo. Así que si necesito el nombre de un estudiante, podría hacer algo como carbón nombre *, y voy a hacer algo así - En realidad, vamos a usar la biblioteca CS50 por sólo un momento para hacer de esto una poco más simple, por lo que podemos pedir prestado esas decenas de líneas de código. Y vamos a hacerlo simple. Lo mantendremos en cadena, y ahora GetString. Así que yo pretendo ahora que he almacenado el nombre de algún estudiante, y la casa de algún estudiante, el simple uso de las variables como lo hicimos y en la primera semana. Pero supongo que ahora quiero apoyar varios estudiantes. Muy bien, así que mis instintos son hacer nombre2 cadena, se pone GetString, string house2 consigue GetString. Y entonces nuestro tercer estudiante, hagámoslo GetString nombre3. Muy bien, así que esto es de esperar sorprendente usted como un poco estúpido, porque este proceso es realmente nunca va a terminar, y que sólo va a hace que mi código se vea peor y peor y peor. Pero resolvimos esto también en la segunda semana. ¿Cuál era nuestra solución relativamente limpio cuando tuvimos múltiples variables de la mismo tipo de datos que están relacionados, pero que no queríamos este lío atroz de llamada de manera similar las variables? ¿Qué hemos hecho en su lugar? Así que creo que he oído un par de lugares. Tuvimos una matriz. Si desea varias copias de algo, ¿por qué no limpiamos todo esto y simplemente decir, dame array llamado nombres? Y por ahora, vamos a codificar 3. Y luego me dan otra matriz llamado casas, y me dejó para ahora codificar 3. Y yo he limpiado masivamente la desastre que acabo de crear. Ahora, he todavía no modificable 3, pero aún el 3 podría venir de la dinámica usuario, o argv, o similares. Así que esto ya es más limpio. Pero lo que es molesto sobre esto es que Ahora, a pesar de que el nombre es de alguna manera fundamentalmente vinculados a la casa de un estudiante - es un estudiante que realmente quiere representar - Ahora tengo dos matrices que son paralelas en el sentido de que son la soporte de mismo tamaño y nombre 0 presumiblemente mapas para casas soporte 0, y los nombres de Soporte 1 mapas a las casas de soporte 1. En otras palabras, el estudiante vive en esa casa, y que otro estudiante vive en la otra casa. Pero seguro que esto podría ser hecho aún más limpiamente. Bueno, es posible, de hecho. Y déjame seguir adelante y abrir hasta structs.h, y usted ver esta idea aquí. Fíjate que he usado typedef, a medida que aludido hace un momento para declarar nuestra propio tipo de datos. Pero también estoy usando esta otra palabra clave llamada struct que me da una nueva estructura de datos. Y esta estructura de datos Reclamo va tener dos cosas en el interior de - una cadena llamado nombre, y una cadena llama casa. Y el nombre que voy a dar a esta estructura de datos se va para ser llamado de los estudiantes. Yo podría llamarlo lo que quiera, pero esto semánticamente hacer sentido para mí en mi mente. Así que ahora, si abro una versión mejor del programa que empecé a escribir allí, déjame Desplácese hasta la parte superior. Y hay algunos más líneas de código aquí, pero permítanme centrarme para el momento en uno. He declarado una constante llamada a los estudiantes y no modificable 3 por ahora. Pero ahora, observe lo limpio mi código comienza a conseguir. En la línea 22, declaro gama de estudiantes. Y note que el estudiante es aparentemente ahora un tipo de datos. Debido a que en la parte superior de este archivo, notificación He incluido el archivo de cabecera que llegué hace un momento. Y ese archivo de cabecera simplemente tenía esta definición de un estudiante. Así que ahora, he creado mi propia datos personalizados escribe que los autores de C año Hace no pensar de antemano. Pero no hay problema. Puedo hacerlo yo mismo. Así que esto es un arreglo llamado estudiantes, cada uno de cuyos miembros es una estructura estudiantil. Y quiero tres de los en la matriz. Y ahora, ¿qué hace el resto de este programa hacer? Yo necesitaba algo un poco arbitraria. Así que desde línea 24 en adelante, Iterar de 0 a 3. Entonces le pido al usuario para el nombre del estudiante. Y entonces yo uso GetString como antes. Entonces me pregunto por la casa del estudiante, y utilizo GetString como antes. Pero note - Ligeramente nueva pedazo de sintaxis - Todavía puede indexar para el estudiante i, pero ¿cómo puedo conseguir a los datos específicos campo dentro de la estructura? Bueno, lo que es aparentemente el nueva pieza de la sintaxis? Es sólo el operador punto. No hemos realmente visto esto antes. Usted lo ha visto en el conjunto de procesadores cinco si usted tiene buceado en ya con los archivos de mapa de bits. Pero el punto sólo significa dentro de este campos de struct o múltiples, dan puntos nombre, o me da la casa de puntos. Eso significa que van dentro de la estructura y obtener los campos particulares. ¿Qué hace el resto de este programa haga? No todo es tan sexy. Nótese que iterar 0-3 otra vez, y simplemente creo una Inglés frase como fulano de tal está en tal o tal casa, pasando el nombre del punto de el estudiante y el i-ésimo su casa también. Y luego, por último, ahora vamos a empezar a obtener anal sobre esto, ahora que estamos familiarizado con lo que malloc y otras funciones han sido haciendo todo este tiempo. ¿Por qué tengo que liberar tanto el nombre y de la casa, a pesar de que no llamar a malloc? GetString hizo. Y ese fue el pequeño y sucio secreto de varias semanas, pero GetString tiene estado filtrando la memoria de todo el colocar todo el semestre hasta el momento. Y Valgrand finalmente revelar esto a nosotros. Pero no es un gran problema, porque sé que simplemente puedo liberar el nombre y la casa, aunque técnicamente, a ser súper, súper seguro, yo debería ser haciendo un poco de comprobación de errores aquí. ¿Cuáles son tus instintos te dicen? ¿Qué debería ser la comprobación de antes de que yo ¿Qué es un cadena, también conocido como el que un char *? Realmente debe comprobar si los estudiantes soporte i DOT Nombre no igual nulo. Entonces va a estar bien para seguir adelante y libre ese puntero, y el mismo u otro uno así. Si los estudiantes ménsula de punteo casa no es igual a null, esto ahora va a proteger contra la caja de esquina en la que GetString vuelve algo así como nulo. Y vimos hace un momento, la voluntad printf protegernos aquí con sólo decir null, lo que se va a parecer raro. Pero por lo menos no va a segfault, como hemos visto. Bueno, déjame hacer una cosa aquí. estructuras-0 es una especie de un programa estúpido porque entro todos estos datos, y luego se pierde una vez que termine el programa. Pero déjame ir adelante y hacer esto. Quiero dejar el terminal ventana un poco más grande. Permítanme hacer estructuras-1, que es una nueva versión de éste. Voy a acercar un un poco. Y ahora déjame correr dot slash estructuras-1. Nombre del estudiante - David Mather, hagámoslo Rob Kirkland, hagámoslo Lauren Leverett. Lo interesante ahora es aviso - y sólo yo sé porque Yo escribí el programa - hay un archivo de ahora mi actual directorio llamado students.csv. Algunos de ustedes se han visto éstos en el mundo real. ¿Qué es un archivo CSV? Valores separados por comas. Es algo así como la de un hombre pobre versión de un archivo de Excel. Es una tabla de filas y columnas que puede abrir en un programa como Excel, o números en un MAC. Y si abro el archivo aquí en gedit, aviso - y los números no están allí. Eso es sólo contar gedit me Números de líneas. Note que en la primera línea de esta archivo es David y Mather. La siguiente línea es Rob coma Kirkland. Y la tercera línea es Lauren coma Leverett. Así que lo que he creado? Ahora que he escrito un programa en C que efectivamente puede generar hojas de cálculo que se puede abrir en un programa como Excel. No todo lo que obligar a un conjunto de datos, pero si tiene trozos mucho más grandes de datos que en realidad quieres manipular y hacer gráficas de y como, esto es quizás una manera de crear esos datos. Por otra parte, CSV son en realidad muy común sólo para el almacenamiento de datos simple - Yahoo Finance, por ejemplo, si usted recibe cotizaciones de bolsa a través de su llamada- API, el servicio gratuito que le permite conseguir las existencias actuales hasta a la fecha Presupuestos para empresas, que dar a la parte posterior de datos en el formato CSV super simple. Entonces, ¿cómo lo hacemos? Bueno notar, la mayor parte de este programa de casi la misma. Pero nótese aquí abajo, en lugar de imprimir los estudiantes de fuera, en la línea 35 en adelante, afirmo que estoy ahorrando el estudiantes en el disco, por lo que se guarda un archivo. Entonces noto que estoy declarando un FILE * - Ahora, esto es una especie de anomalía en C. Por alguna razón, FILE es todo en mayúsculas, que no es como la mayoría de otros tipos de datos en C. Pero esto es un built-in tipo de datos, FILE *. Y estoy declarando un puntero a un archivo, es cómo se puede pensar en eso. fopen significa abrir el archivo. ¿Qué archivo que desea abrir? Quiero abrir un archivo que yo quiero arbitrariamente llamar students.csv. Podría llamar a que cualquier cosa que yo quiera. Y luego tomar una conjetura. ¿Qué hace el segundo argumento a fopen probablemente significa? Derecha, w para escritura, podría ser r para lectura. Hay una para append si desee agregar filas y no sobrescribir todo el asunto. Pero yo sólo quiero crear este archivo una vez, así que utilizaré comillas w. Y sé que sólo a partir de haber leído la documentación, o de la página de manual. Si el archivo no es nulo - en otras palabras, si nada salió mal allí - permítanme repetir las estudiantes de 0 a 3. Y ahora note que hay algo muy ligeramente diferente acerca de la línea 41 aquí. No es printf. Es fprintf para el archivo de printf. Así que va a escribir al archivo. ¿Qué archivo? Aquel cuyo puntero se especifica como primer argumento. A continuación especificamos una cadena de formato. A continuación especificamos qué cadena que queremos conecte por primera ciento s, y a continuación, otra variable o la segunda por ciento s. Luego cerramos el archivo con fclose. De lo que liberar la memoria como antes, aunque Debo volver y agregar algunas comprobaciones para null. Y eso es todo. fopen, fprintf, fclose me da la capacidad de crear archivos de texto. Ahora, usted verá en el problema establecido cinco, que consiste en imágenes, que va a utilizar archivos binarios en lugar. Pero fundamentalmente, la idea es la misma, a pesar de que las funciones que usted lo va a hacer ver son un poco diferentes. Así gira torbellino, pero usted recibirá demasiado familiar con el archivo I/O-- entrada y salida - con el conjunto de procesadores cinco. Y cualquier pregunta acerca de la fundamentos iniciales aquí? ¿Sí? ¿Qué pasa si usted trata de liberar a un valor nulo? Creo que, a no ser libre ha conseguido un poco más fácil de usar, se puede potencialmente segfault. Pasando nulo es malo porque no lo hago creer molestias gratuitas para comprobar por ti, porque sería potencialmente una pérdida de tiempo para que lo haga por sí mismo todos en el mundo. Buena pregunta, sin embargo. Muy bien, por lo que este tipo de se nosotros para un tema interesante. El tema del problema establece cinco es la medicina forense. Al menos esa es una parte del conjunto de problemas. Los forenses generalmente se refiere a la recuperación de la información que puede o No puede haber sido borrado deliberadamente. Y así que pensé que le daría una rápida muestra de lo que realmente está pasando en todo esta vez por debajo de la capó de su ordenador. Por ejemplo, si usted tiene dentro de su ordenador portátil o el ordenador de sobremesa un disco duro, que es ya sea un mecánico dispositivo que en realidad hace girar - hay cosas circulares llamados platos que se ven muy parecido a lo que sólo tenía en la pantalla aquí, aunque esto es cada vez más de la vieja escuela. Se trata de una-y-uno-mitad-pulgada tres disco duro. Y tres y media pulgadas refiere de con de la cosa cuando lo instale en un ordenador. Muchos de ustedes en sus ordenadores portátiles ahora tienen unidades de estado sólido, o SSD, que no tienen partes móviles. Son más como RAM y menos como estos dispositivos mecánicos. Pero las ideas siguen siendo las mismas, sin duda en lo que respecta al problema planteado cinco. Y si lo piensas ahora de un disco duro representa ser un círculo, el cual Voy a dibujar como esto aquí. Cuando se crea un archivo en su computadora, si se trata de un SSD, o en este caso, un viejo disco duro de la escuela, ese archivo comprende múltiples bits. Digamos que es esto 0 y 1, un montón de 0s y 1s. Así que este es mi disco duro entero. Esto es al parecer un archivo bastante grande. Y está consumiendo el 0 y 1 en ese porción de la fuente física. Bueno, ¿qué es esa parte física? Bueno, resulta que en un disco duro, al menos de este tipo, hay estas diminutas partículas magnéticas. Y ellos tienen esencialmente el norte y sur para ellos, por lo que si usted convertir una de esas partículas magnéticas de esta manera, se podría decir que se trata de que representa un 1. Y si es al revés hacia el sur hasta norte, se podría decir que es que representa un 0. Así que en el mundo físico real, eso es cómo se puede representar algo en estado binario del 0 y el 1. Así que eso es todo un archivo es. Hay un montón de magnética partículas que son de esta manera o su De esta forma, los patrones que crean de 0 y 1. Pero resulta que cuando se guarda un archivo, alguna información se guarda por separado. Así que esta es una pequeña mesa, un directorio, por así decirlo. Y voy a llamar a este nombre de columna y Voy a llamar a esta ubicación de la columna. Y yo voy a decir, supongamos esta es mi hoja de vida. Mi resume.doc se almacena a ubicación, digamos 123. Siempre voy por ese número. Pero baste decir que al igual que en la memoria RAM, se puede tomar una unidad de disco duro eso es un gigabyte o 200 gigabytes o de un terabyte, y se puede numerar todos los bytes. Puede numerar todos los trozos de 8 bits. Así que vamos a decir que esta es la ubicación 123. Así que este directorio dentro de mi operación sistema recuerda que mi hoja de vida es en la ubicación 123. Pero se pone interesante cuando se elimina un archivo. Así, por ejemplo - y por suerte, la mayor parte del mundo ha atrapado en esto - ¿qué pasa cuando arrastra un archivo a la Papelera de Mac OS o su Windows Papelera de reciclaje? ¿Cuál es el propósito de hacer eso? Es obvio que es deshacerse de el archivo, pero lo que hace el acto de arrastrar y caer en la papelera o en su Papelera de reciclaje hacer en un ordenador? Absolutamente nada, de verdad. Es como una carpeta. Es una carpeta especial, para estar seguro. ¿Pero realmente borrar el archivo? Bueno, no, porque algunos de ustedes probablemente han sido, oh maldita sea, no lo hiciste quise hacer eso. Así se hace doble clic en el Papelera o la Papelera de reciclaje. Usted ha hurgó y que se haya recuperado el archivo simplemente arrastrándolo de ahí. Así que, claramente, no es necesariamente eliminarlo. Bien, que eres más inteligente que eso. Usted sabe que sólo arrastrándola a la Trash o Papelera de reciclaje no significa estás vaciar la papelera. Así que ir hasta el menú, y usted dice Vaciar papelera o Vaciar Papelera de reciclaje. Entonces, ¿qué sucede? Sí, por lo que se elimina más. Pero todo lo que sucede es esto. El ordenador olvida donde resume.doc era. Pero lo que no ha cambiado aparentemente en la foto? Los bits, el 0 y 1 que reclamo son en el sitio de algún aspecto físico del el hardware. Ellos todavía están allí. Es sólo el equipo tiene olvidan lo que son. Por lo que es esencialmente liberado del archivo bits de modo que puedan ser reutilizados. Pero no hasta que se cree más archivos, y más archivos y más archivos se probabilísticamente, los 0s y 1s, esas partículas magnéticas, se reutilizan, al revés o boca arriba, para otros archivos, 0s y 1s. Por lo que tiene esta ventana de tiempo. Y no es de predecible longitud, de verdad. Depende del tamaño de su disco conducir y la cantidad de archivos que tiene y la rapidez con que hagas otras nuevas. Pero hay esta ventana de tiempo durante el que ese archivo es todavía perfectamente recuperable. Así que si alguna vez utiliza programas como McAfee o Norton para tratar de recuperar datos, lo único que están haciendo es tratar de recuperar este directorio llamado a averiguar dónde estaba su archivo. Y a veces Norton y dirá: archivo es el 93% de reembolso. Bueno, ¿qué significa eso? Eso sólo significa que algún otro archivo casualmente terminó usando, por ejemplo, los bits de su archivo original. Entonces, ¿qué es en realidad involucrados en la recuperación de datos? Bueno, si usted no tiene algo como Norton preinstalado en el equipo, el mejor a veces se puede hacer es mirar en todo el disco duro en busca de los patrones de bits. Y uno de los temas de la Serie de problemas cinco es que va a buscar el equivalente a un disco duro, un forense imagen de una tarjeta compact flash de una cámara digital, la búsqueda de los 0s y 1s que normalmente, con alta probabilidad, representar a la comenzar de una imagen JPEG. Y ustedes pueden recuperar esas imágenes por asumiendo, si veo a este patrón de bits en la imagen forense, con alta probabilidad, que las marcas el inicio de un JPEG. Y si veo el mismo patrón de nuevo, que probablemente marca el inicio de otra JPEG, y otro JPEG, JPEG y otro. Y esto es por lo general la forma de recuperación de datos funcionará. Lo bueno de los archivos JPEG es a pesar de que el formato de archivo en sí es algo complejo, el comienzo de cada uno de tales archivo es en realidad bastante identificable y simple, como se verá, si no tienes ya. Así que vamos a echar un vistazo más de cerca por debajo la capucha en cuanto a exactamente lo que ha sido pasando, y lo que estos 0s y 1s son, para darle un poco más de un contexto para este desafío particular. [REPRODUCCIÓN DE VÍDEO] -Cuando sus tiendas de PC más de sus datos permanentes. Para ello, los datos viajan desde la RAM junto con las señales de software que le dicen El disco duro de la forma de almacenar los datos. Los circuitos de disco duro se traducen esas señales en tensión fluctuaciones. Estos, a su vez, controlan la unidad de disco partes móviles, algunos de los pocos partes móviles que quedan en el computadora moderna. Algunas de las señales de control de un motor que gira bandejas recubiertas de metal. Sus datos se almacenan en realidad en estos platos. Otras señales se mueven la lectura / escritura cabezas para leer o escribir datos en los discos. Esta maquinaria tan precisa que un ser humano pelo ni siquiera podía pasar entre el cabezas y platos giratorios. Sin embargo, todo funciona a velocidades fenomenales. [VIDEO PLAYBACK FIN] DAVID MALAN: Zoom en una pequeña profundizar ahora en lo que es en realidad en los platos. [REPRODUCCIÓN DE VÍDEO] -Echemos un vistazo a lo que acabamos de vio en cámara lenta. Cuando un breve pulso de electricidad es enviado a la cabeza de lectura / escritura, si volteretas en una pequeña electromagnética para de una fracción de segundo. El imán crea un campo, el cual cambia la polaridad de una pequeña, pequeña parte de las partículas de metal que abrigo de cada superficie del disco. Una serie patrón de estos pequeños, áreas cargada-up en el disco representa un solo bit de los datos en el número binario sistema utilizado por las computadoras. Ahora, si la corriente se envía de una manera a través de la cabeza de lectura / escritura, el área se polariza en una dirección. Si la corriente se envía en el dirección opuesta, la polarización se invierte. La manera de obtener los datos desde el disco duro? Simplemente revertir el proceso. Así que es que las partículas en el disco que obtener la corriente en el lectura / escritura de la cabeza en movimiento. Armar millones de éstos segmentos magnetizados, y usted tiene un archivo. Ahora, las piezas de un solo archivo puede estar dispersos por toda una unidad de platos, algo así como el desorden de papeles en su escritorio. Así que un archivo muy especial hace un seguimiento de dónde está todo. ¿No te gustaría tener algo así? [VIDEO PLAYBACK FIN] DAVID MALAN: OK, probablemente no. Entonces, ¿cuántos de ustedes crecí con estos? Aceptar, por lo que es cada vez menos manos cada año. Pero me alegro de que esté por lo menos familiarizados con ellos, porque esta y nuestra propia libro de demostración, por desgracia, se están muriendo muy retardar la muerte aquí de familiaridad. Pero esto es lo que, al menos, de vuelta en la escuela secundaria, el uso se utiliza para copias de seguridad. Y fue increíble, porque podía almacenar 1,4 megabytes en Este disco en particular. Y esta fue la versión de alta densidad, como se indica por la HD, que tiene es decir antes de los vídeos HD de hoy en día. Densidad estándar fue de 800 kilobytes. Y antes de eso, había Discos de 400 kilobytes. Y antes de eso, había 5 y 1/4 discos pulgadas, que eran verdaderas disquete, y un poco más ancho y más alto que estas cosas aquí. Pero en realidad se puede ver la llamada aspecto disquete de estos discos. Y funcionalmente, en realidad son bastante similar a los discos duros de al menos de este tipo. Una vez más, los SSD en los equipos más nuevos trabajar un poco diferente. Pero si traslada la pestaña pequeña de metal, en realidad se puede ver un poco de galleta, o bandejas. No es de metal como éste. Éste es en realidad algunos más baratos material plástico. Y usted puede tipo de moverla. Y has apunté simplemente borrado algunos número de bits o partículas magnéticos desde este disco. Así que gracias a Dios, no hay nada en él. Si esa cosa está en el camino - y la tapa sus ojos y los de su vecino - usted puede clase de sacar esto adelante toda la vaina fuera así. Pero hay un poco de primavera, así que ten consciente de que con sus ojos. Así que ahora usted tiene realmente un disquete. Y lo que es notable acerca de este es que en la medida en que este es un representación a pequeña escala de un mayor disco duro, estas cosas son super, super simple. Si se pellizca la parte inferior de la misma, ahora que fuera de esa cosa de metal, y la cáscara ellos abren, todo lo que hay es dos piezas de fieltro y la llamada disquete con una pieza de metal en el interior. Y ahí va la mitad de el contenido de mi disco. Ahí va otro medio de ellos. Pero eso es todo lo que daba vueltas en el interior de su equipo en antaño. Y además, a poner esto en perspectiva, lo grande que es la mayor parte de su duros estos días? 500 gigabytes, un terabyte, tal vez en una computadora de escritorio, 2 terabytes, 3 terabytes, 4 terabytes, ¿verdad? Se trata de un megabyte, más o menos, que ni siquiera puede caber un típico MP3 más en estos días, o algunos archivo de música similar. Así que un pequeño recuerdo para ti hoy, y también para ayudar a contextualizar lo que vamos a tomar por sentado ahora en el problema planteado cinco. Así que estos son tuyos para siempre. Así que permítanme transición a donde será pasar al siguiente conjunto de procesadores también. Así que ahora hemos establecido esta página para - oh, un par de anuncios de forma rápida. Este viernes, si usted desea unirse CS50 para el almuerzo, ir al lugar de costumbre, cs50.net/rsvp. Y proyecto final - así que por el plan de estudios, hemos publicado la especificación de proyecto fin de carrera ya. Darse cuenta de que eso no significa que es debido sobre todo pronto. Ha publicado, en realidad, sólo para obtener Ustedes que piensan al respecto. Y, en efecto, un super significativa porcentaje de que se aborda proyectos finales sobre el material que ni siquiera han llegado a la clase, pero será tan pronto como la próxima semana. Nótese, sin embargo, que la especificación exige un par de componentes diferentes de la proyecto final. El primero, en unas pocas semanas, es una pre-propuesta, un correo electrónico bastante informal para el TF para decirle o qué eres pensando para su proyecto, con ningún compromiso. Propuesta será su especial compromiso, diciendo: aquí, esto es lo que Me gustaría hacer para mi proyecto. ¿Qué piensa usted? Demasiado grande? Demasiado pequeño? ¿Es manejable? Y ves las especificaciones para más detalles. Un par de semanas después de que es el estado informar, que es una forma similar email informal a tu TF decir cuán muy por detrás de usted está en su final, aplicación de proyecto, seguido por el CS50 Hackathon a la que todos es invitado, que será un evento de 20:00 en una noche hasta las 7:00 AM de la mañana siguiente. Pizza, como yo lo he dicho en semanas cero, wil ser servido a las 9:00 PM, Comida china a las 1:00 PM. Y si usted todavía está despierto a las 5:00 de la mañana, lo llevaremos a IHOP para el desayuno. Así que la Hackathón es uno de los más experiencias memorables en la clase. A continuación, la aplicación se debe, y entonces el clímax Feria CS50. Más detalles sobre todas estas en las semanas venideras. Pero volvamos a algo vieja escuela - de nuevo, una matriz. Así que una serie estaba muy bien, ya que resuelve problemas como vimos sólo un Hace momento con estructuras estudiantiles poniendo un poco fuera de control si quiero tener un estudiante, estudiante dos, estudiante tres, dot dot dot estudiante, un número arbitrario de los estudiantes. Así matrices, hace unas semanas, se abalanzaron y resuelto todos nuestros problemas de la no sabiendo de antemano la cantidad de cosas de algún tipo puede ser que deseemos. Y hemos visto que las estructuras pueden ayudarnos organizar mejor nuestro código y mantener las variables conceptualmente similares, como un nombre y una casa, juntos, por lo que puede tratar como una sola entidad, en el interior de los cuales hay piezas más pequeñas. Pero matrices tienen algunas desventajas. ¿Cuáles son algunas de las desventajas nos hemos encontrado con matrices hasta el momento? ¿Qué es eso? Tamaño fijo - por lo que a pesar de que usted puede ser ser capaz de asignar memoria para una matriz, una vez que sabes cómo muchos estudiantes que tiene, cuántos caracteres tiene desde el usuario, una vez que ha asignado la matriz, has clase de pintadas a ti mismo en una esquina. Porque no se puede insertar nuevos elementos en el centro de una matriz. No se puede insertar más elementos al final de una matriz. Realmente, usted tiene que recurrir a la creación de un nueva gama, como hemos comentado, copiando lo viejo a lo nuevo. Y de nuevo, que es el dolor de cabeza que GetString ofertas por usted. Pero, de nuevo, ni siquiera se puede insertar algo en el centro de la matriz si la tasa no está totalmente llena. Por ejemplo, si esta matriz aquí de tamaño seis sólo tiene cinco cosas en ella, así, usted podría virar algo en el extremo. Pero lo que si desea insertar algo en el medio de la matriz, a pesar de que podría tener cinco de los seis que hay en él? Bueno, ¿qué podemos hacer cuando teníamos todo de nuestros voluntarios humanos en el escenario semana pasado? Si quisiéramos poner a alguien aquí, tampoco estas personas cómo mover este manera, o esta gente cómo mover este manera, y que se convirtieron caro. El desplazamiento de personas en el interior de un array terminó sumando y costeo nosotros tiempo, por lo tanto, gran parte de nuestro n al cuadrado veces corriendo como la ordenación por inserción, por ejemplo, en el peor de los casos. Así que las matrices son grandes, pero hay que sabe de antemano el tamaño que desee. Así que bien, aquí está la solución. Si no sé de antemano cuántos estudiantes que puedan tener, y sé una vez Yo decido, sin embargo, me tengo que quedar con esa muchos estudiantes, ¿por qué no acabo de siempre asignar el doble de espacio como yo podría pensar que necesito? ¿No es una solución razonable? Siendo realistas, no creo que estemos Va a necesitar más de 50 ranuras en un arreglo para una clase de tamaño mediano, así que vamos a redondear hacia arriba. Voy a hacer 100 slots en mi matriz, sólo por lo que definitivamente podemos obtener la número de estudiantes que espero estar en alguna clase de mediano tamaño. Así que ¿por qué no reunir y asignar más memoria, por lo general, para una matriz de lo que cree que incluso podría necesitar? ¿Cuál es esta simple retroceso a esa idea? Estás perdiendo la memoria. Literalmente, cada programa se escribe a continuación es tal vez el uso del doble de memoria que que realmente necesita. Y eso simplemente no se siente como un solución particularmente elegante. Por otra parte, sólo disminuye la probabilidad de que un problema. Si le sucede que tiene un curso muy popular un semestre y tiene 101 estudiantes, el programa sigue siendo enfrenta fundamentalmente el mismo problema. Así que por suerte, hay una solución a anuncio a todos nuestros problemas en la forma de estructuras de datos que están más complejos que los que hemos visto hasta el momento. Esto, afirmo, es una lista enlazada. Esta es una lista de los números - 9, 17, 22, 26, y 34 - que han sido unidas entre sí por medio de lo que he dibujado como flechas. En otras palabras, si yo quería representar una matriz, que podría hacer algo como esto. Y voy a poner esto en la cabeza en un momento. Que podía hacer - hola, muy bien. En espera. Equipo nuevo aquí, claro - Está bien. Así que si tengo estos números en orden de batalla - 9, 17, 22, 26, 24 - no necesariamente a escala. Muy bien, así que aquí está mi serie - Oh, Dios mío. Muy bien, así que aquí está mi matriz. Oh, Dios mío. [Risas] DAVID MALAN: Pretend. Es demasiado esfuerzo para volver y arreglar eso, por lo que - 26. Así que tenemos este conjunto de 9, 17, 22, 26 y 34. Para aquellos de ustedes puede ver el error vergonzoso que acabo de hacer, ahí está. Así que yo sostengo que este es un solución muy eficiente. He asignan tantos enteros como Necesito - uno, dos, tres, cuatro, cinco, o seis - y luego me he guardado los números dentro de esta matriz. Pero supongamos que, entonces, quiero insertar un valor como el número 8? Bueno, ¿a dónde va? Supongamos que quiero insertar un número como 20. Bueno, ¿a dónde va? En algún lugar en el medio, o el número 35 tiene que ir en algún lugar en el extremo. Pero me he quedado sin espacio. Y así, este es un reto fundamental de matrices que no son la solución. Afirmé hace un momento, GetString soluciona este problema. Si desea insertar un sexto número en esta matriz, lo que es al menos un solución que usted puede recurrir a ciencia cierta, al igual que hacemos con GetString? ¿Qué es eso? Bueno, hacerlo más grande se más fácil de decir que de hacer. No podemos necesariamente que la matriz más grande, pero ¿qué podemos hacer? Hacer una nueva matriz que es más grande, de tamaño 6, o tal vez el tamaño de 10, si queremos para adelantarse a las cosas, y luego copiar la antigua matriz en la nueva, y luego liberar la matriz de edad. Pero ¿cuál es el tiempo de ejecución ahora de ese proceso? Es gran O de n, debido a que la copia va a costar algunas unidades de tiempo, así que no es tan ideal si tenemos que asignar una nueva variedad, que va para consumir el doble de memoria temporalmente. Copie viejo en nuevo - Quiero decir, es sólo un dolor de cabeza, que es, de nuevo, ¿por qué escribimos GetString para usted. Así que ¿qué podemos hacer en su lugar? Bueno, ¿y si nuestra estructura de datos en realidad tiene lagunas en ella? Supongamos que me relajo mi meta de tener trozos contiguos de memoria, donde 9 está justo al lado de 17, que es justo al lado 22, y así sucesivamente. Y supongamos que el 9 puede ser aquí en RAM, y 17 pueden ser aquí en la memoria RAM, y 22 pueden estar aquí en la RAM. En otras palabras, yo no los necesito incluso espalda con espalda más. Sólo tengo que enhebrar una aguja de alguna manera a través de cada uno de estos números, o cada uno de estos nodos, ya que vamos a llamar la rectángulos como yo los he dibujado, a recordar cómo llegar a la última tales nodo de la primera. Entonces, ¿cuál es la construcción de programación que hemos visto hace poco tiempo con el que puede implementar ese hilo, o dibujado aquí, con la que puedo aplicar esas flechas? Así punteros, ¿verdad? Si asigno no sólo una int, pero un nodo - y por nodo, me refiero sólo a contenedor. Y visualmente, me refiero a un rectángulo. Por lo tanto un nodo aparentemente necesita para contener dos valores - el int sí mismo, y luego, como se deduce de la mitad inferior del rectángulo, espacio suficiente para un int. Así que pensar en el futuro aquí, lo grande que es este nodo, este contenedor de que se trate? ¿Cuántos bytes para la int? Presumiblemente 4, si es la misma, como de costumbre. Y entonces la cantidad de bytes para el puntero? 4. Así que este contenedor o este nodo, es va a ser una estructura de 8 bytes. Ah, y eso es una feliz coincidencia que hemos introducido esta noción de una estructura o una estructura de C. Así que yo sostengo que quiero dar un paso hacia este más sofisticado aplicación de una lista de números, una lista de números vinculados, tengo que hacer una poco más pensando en la delantera y declarar no sólo un int, pero una estructura que voy a llamar, convencionalmente aquí, el nodo. Podríamos llamarlo lo que queramos, pero nodo va a ser temática en un montón de las cosas que empezamos a mirar ahora. Dentro de ese nodo es un entero n. Y luego esta sintaxis, un poco extraño a primera vista - struct nodo * siguiente. Bueno pictóricamente, ¿qué es eso? Esa es la mitad inferior de el rectángulo que vimos hace un momento. Pero ¿por qué estoy diciendo struct nodo * en contraposición a nodo sólo *? Porque si ese puntero apunte en otro nodo, es sólo la dirección de un nodo. Eso es coherente con lo que hemos discutido acerca de los punteros hasta el momento. ¿Pero por qué, si puedo reclamar esta estructura es llamado nodo, ¿tengo que decir struct nodo aquí dentro? Exactamente. Es una especie de una realidad estúpida de C. La definición de tipos, por así decirlo, no tiene sucedido todavía. C es muy literal. Se lee el código en la parte superior abajo, de izquierda a derecha. Y hasta que llegue a ese punto y coma en la línea de fondo, supongo que lo que no funciona existir como un tipo de datos? Nodo, nodo, entre comillas. Pero debido a la más detallado declaración que hice en la primera línea - typedef struct node - porque eso fue primero, antes de que el llaves, eso es algo así como pre-educar Clang eso, saber qué, dame una estructura llamado nodo de estructura. Francamente, no me gusta llamar a las cosas struct nodo, struct nodo todo a través de mi código. Pero yo sólo voy a usar una vez, justo en el interior, para que yo pueda efectivamente crear una especie de referencia circular, no un puntero a mí mismo por sí mismo, sino un puntero a otro de un tipo idéntico. Así resulta que en una estructura de datos así, hay unos cuantos operaciones que podrían ser de interés para nosotros. Podríamos querer insertar en una lista como esta. Podríamos querer eliminar a partir de una lista como esta. Podríamos querer buscar en la lista de valor, o más generalmente, de la poligonal. Y travesía es sólo una forma elegante de diciendo comienzo a la izquierda y seguir todo el camino a la derecha. Y noten, incluso con este un poco más estructura de datos sofisticada, y mucho yo propongo que podamos pedir prestado un poco de las ideas de las últimas dos semanas y implementar una función llamada buscar así. Se va a devolver true o falsa, lo que indica, sí o No, n está en la lista. Su segundo argumento es un puntero a la propia lista, por lo que un puntero a un nodo. Todo lo que voy a hacer es declarar a continuación, una variable temporal. Lo llamaremos ptr por convención, para el puntero. Y yo asigno igual a la principio de la lista. Y ahora fíjense el bucle while. Mientras puntero no es igual null, voy a comprobar. Es puntero de flecha n igual a la n que fue aprobada en? Y espera un minuto - nuevo pedazo de sintaxis. ¿Cuál es la flecha, de repente? ¿Sí? Exactamente. Así, mientras hace unos minutos, se utilizó la notación de puntos para acceder a algo en el interior de un la estructura, si la variable que tienen no es la estructura en sí, sino un puntero a una estructura, por suerte, un pedazo de sintaxis que finalmente tiene sentido intuitivo. La flecha significa seguir el puntero, como nuestras flechas normalmente significan gráficamente, e ir a campo de datos en el interior. Así que la flecha es la misma cosa que punto, pero lo usa cuando se tiene un puntero. Así que para resumir a continuación, si el campo n interior de la estructura llamada puntero es igual a es igual a n, devolver true. De lo contrario, esta línea aquí - puntero es igual a puntero siguiente. Entonces, ¿qué está haciendo esto, aviso, es que si yo actualmente estoy apuntando a la estructura que contiene 9, y 9 no es el número Busco - Supongo que estoy buscando para n igual a 50 - Voy a actualizar mi puntero temporal al no señalar en este nodo más, pero puntero de flecha al lado, que se va a poner yo aquí. Ahora, me di cuenta es un torbellino introducción. El miércoles, en realidad vamos a hacer esto con algunos seres humanos y con un poco más código a un ritmo más lento. Pero damos cuenta, ahora estamos haciendo nuestros datos estructuras más complejas para que nuestro Los algoritmos pueden ser más eficientes, lo que va a ser requisito para pset seis, cuando cargamos en, de nuevo, los 150.000 palabras, pero deberá hacerlo de manera eficiente, y lo ideal es crear un programa que se ejecuta para nuestros usuarios que no están en lineal, no en n al cuadrado, pero en constante de tiempo, en el ideal. Nos vemos el miércoles. ALTAVOZ: En la próxima CS50, David olvida su caso base. DAVID MALAN: Y esa es la forma de enviar mensajes de texto con C. Lo que el - [MENSAJE DE TEXTO VARIOS NOTIFICACIÓN SOUNDS]