[Powered by Google Translate] Vamos a hablar de las estructuras. Las estructuras nos proporcionan una forma de agrupar un montón de variables juntas en un paquete agradable. Es probablemente más fácil para ver un ejemplo inmediato, por eso decimos estructura, luego abrir llave, y en esta estructura, vamos a tener una edad int, un nombre char *, y eso es todo. Puede parecer extraño con un punto y coma después de una llave, pero es de hecho necesario, con las estructuras. Cualquier tipo válido puede ir dentro de la definición de estructura. Aquí, hemos utilizado un int y un char *, pero también se puede utilizar una matriz, de, digamos, 100 elementos o incluso en otra estructura. Cuando usted está utilizando estructuras en C, está creando nuevos tipos de una colección de otros tipos. Aquí, estamos haciendo un nuevo tipo de un entero y un char *. Como veremos más adelante, una estructura tipo está en un montón de maneras equivalentes de cualquier otro tipo que estamos acostumbrados. Por lo general, voy a estar comparando cómo un tipo struct es similar a un tipo entero. Mientras que el código que escribió es válida C, no es muy útil, clang y nos dará una advertencia. ¿Recuerda cómo sus estructuras y son similares? Bueno, básicamente, dijo int, que no es una línea muy útil. Así que en realidad declarar una variable de ese tipo dándole un nombre antes del punto y coma. Llamaremos a la estudiante variable. Ahora hemos declarado una variable llamada estudiantes con el tipo de propuesta por la estructura. ¿Cómo podemos llegar a las variables dentro de la estructura? Técnicamente, los nombres de estas variables son miembros. Para acceder a cualquier miembro particular de una estructura estudiante, se añade un punto al nombre de la variable, seguido del nombre del elemento que desea. Así que aquí, las únicas dos posibilidades válidas son student.age y student.name. Y podemos hacer algo como student.age = 12 y student.name = estudiante. Ahora lo que si queríamos hacer un estudiante de segundo? Se podría pensar que copiar y pegar estas líneas y cambiar un estudiante a 2 o algo así, y que va a funcionar, pero técnicamente, estudiante y estudiante 2 no tienen el mismo tipo. Vea, usted no será capaz de asignar el uno al otro. Esto es debido a que, hasta ahora, su estructura ha sido anónimo. Tenemos que darle un nombre. Para hacer esto, introduzca el nombre de la estructura después de la palabra struct. estudiante, seguido por la definición. Todavía podemos inmediatamente declarar una variable de tipo struct estudiante, como lo hicimos antes. Lo llamaremos S1 Al dar a la estructura de un nombre, ahora podemos utilizar estudiante struct en casi la misma forma que usaría int. Por lo tanto, se puede declarar una variable de tipo struct estudiante, como struct estudiante S2. Al igual que las matrices, estructuras proporcionan una sintaxis de inicialización de acceso directo, por lo que podemos decir, estructura estudiante S2 es igual a llave de apertura 3, S2. Aquí, S2.age será 3, y S2.name apuntará a S2. Piense en todas las cosas que puedes hacer con un tipo int y la mayoría de ellos se puede hacer con un tipo struct estudiante. Se puede utilizar un estudiante struct como un tipo de un parámetro de función. Podemos utilizar struct estudiante dentro de una estructura nueva. Podemos tener un puntero a una struct estudiante. Podemos hacer tamaño del estudiante estructura. Estudiante Struct es un tipo al igual que int es un tipo. También podemos asignar S1 a S2 ya que ambos son del mismo tipo, por lo que podemos hacer S1 = S2. ¿Qué pasa si no hacemos S1.age = 10? ¿Cambia S2 en absoluto? Una vez más, pensar en las estructuras sólo como enteros normales. Si asignamos un poco de X int a int Y algunos, como X = Y y cambie X, como en X + +, Y no cambia en absoluto? Y aquí no cambia, por lo que tampoco S2 arriba. S2.age es todavía 3. Pero tenga en cuenta que cuando se asigna una estructura a otra, todos los punteros aún apuntan a la misma cosa, desde que se acabo de copiar. Si usted no desea que los punteros a ser compartida, tendrás que manejar manualmente que, quizás por malicking un bloque de memoria para uno de los punteros para apuntar a y copiar los datos de nuevo. Puede ser molesto tener que escribir struct estudiante en todas partes. El uso de un tipo de definición, podemos hacer tipo def struct y lo vamos a llamar estudiante. Ahora, podemos usar cualquier estudiante que hemos utilizado para uso de los estudiantes estructura. Esta definición es un tipo struct anónimo y lo llama estudiante. Pero si vamos a mantener el identificador de estudiante al lado de la palabra struct, como en el estudiante typedef struct, podríamos utilizar tanto el estudiante y el estudiante struct indistintamente ahora. Ni siquiera tiene que tener el mismo nombre. Podríamos escribir def estudiante struct para Bob y luego struct estudiante y Bob Sería tipos intercambiables. Independientemente de la definición de tipo, necesitamos el siguiente identificador a struct Si la definición de la estructura es recursiva. Por ejemplo, def tipo struct nodo y se define como un int val y contará con un puntero que apunta a otro nodo struct., como en struct nodo * siguiente. Y entonces lo llamaremos nodo. Esta estructura es recursiva, ya que la definición de struct nodo contiene en su interior un puntero a un nodo de estructura. Tenga en cuenta que tenemos que decir struct nodo * siguiente dentro de la definición de la estructura de nodo, ya que la definición de tipos no ha terminado todavía que nos permita simplificar este a sólo * siguiente nodo. Usted aprenderá más sobre las estructuras similares a este cuando se trata de las listas enlazadas y árboles. ¿Qué pasa con las estructuras en una función? Esto también es perfectamente válido. Podríamos tener anular la función que toma como argumento, estudiante s y hace algo con ese estudiante. Y luego podemos pasarlo como struct estudiante como tal. Func de S1 de antes. La estructura se comporta exactamente como un número entero cuando se pasa a una función. Func recibe una copia de S1 y por lo tanto no puede modificar S1; más bien, sólo la copia que se almacena en S. Si desea que la función para poder modificar S1, función tendrá que tomar una estudiante * S, y que tendrá que pasar por dirección S1, así. Estudiante * S, funciones y S1. Hay otra razón para pasar por dirección aquí. ¿Y si nuestra estructura contenía 100 campos? Cada vez que pasa un estudiante de funcionar, nuestro programa tiene que copiar todos los 100 campos en función de S argumento, incluso si no se utiliza la gran mayoría de ellos. Así que incluso si func no planea modificar el estudiante, si todavía puede ser de gran valor para pasar por la dirección. Bueno, ¿qué pasa si queremos crear un puntero a una estructura? Podríamos hacer algo como estudiante * S es igual a malloc tamaño de los alumnos. Tenga en cuenta que el tamaño de todavía trabaja aquí. Entonces, ¿cómo podemos ahora tener acceso al miembro edad del bloque que los puntos S para? En primer lugar, puede ser que piense que hacer * S.age = 4, pero esto no va a funcionar bastante. Dado que esto realmente se interpretará como * S.age entre paréntesis = 4, que incluso no compilar, ya que S no es una estructura o mejor dicho un puntero a una estructura, por lo que el punto no va a funcionar aquí. Podríamos hacer (* S). = 4 años pero los paréntesis puede ser molesto y confuso. Afortunadamente, contamos con un operador de flecha especial que se ve algo como S-> edad = 4. Estas dos formas de hacer referencia a la edad son equivalentes y que realmente no necesita siempre el operador de flecha, pero hace que las cosas se ven más bonitas. Puesto que S es un indicador a una bloque de memoria que contiene la estructura, se puede pensar en la edad S> como seguir la flecha del cursor y agarrar el miembro de la edad. Entonces, ¿por qué nos utilizan estructuras? Es definitivamente posible alejarse con sólo los números enteros primitivos, caracteres, punteros y similares que estamos acostumbrados; en lugar de S1 y S2 antes, que podría haber tenido edad1, edad2, nombre1, nombre2 y todo en las variables independientes. Esto está muy bien, con sólo 2 estudiantes, pero lo que si tuviéramos 10 de ellos? ¿Y si en lugar de sólo los campos 2, la estructura estudiante contaba con 100 campos? GPA, cursos, color de pelo, el sexo, etc. En lugar de sólo 10 estructuras, necesitamos 1.000 variables separadas. Además, considere una función que toma esa estructura con 100 campos con su único argumento e imprime todos los campos. Si no usamos una estructura, cada vez que llamamos a esa función, tenemos que pasar a los 100 variables, y si tenemos 100 variables para el estudiante 1, y 100 variables para el estudiante 2, tenemos que estar seguros de que no accidentalmente se pasa de algunas variables de un estudiante y algunas variables del estudiante 2. Es imposible cometer el mismo error con una estructura, ya que todas las variables de 100 están contenidos en un único paquete. Sólo un par de notas finales: Si usted ha entendido todo hasta este punto, muy bien. El resto del video es sólo por el bien de la integridad ". Debido a que las estructuras pueden contener cualquier tipo de puntero, también pueden contener punteros a funciones. Si está familiarizado con la programación orientada a objetos, esto proporciona una manera de utilizar las estructuras de programa en un estilo orientado a objetos. Más información sobre los punteros de función en otro momento. También, a veces usted puede tener dos estructuras cuyas definiciones dependen uno del otro. Por ejemplo, podríamos tener struct A, que se define como un puntero a una struct B, struct B * X, y ahora podemos tener una estructura B que se define como un puntero a una estructura A, struct A * Y. Pero esto no va a compilar, ya que B struct no existe en el momento en que struct A está siendo compilado. Y si cambiamos struct struct A y B, entonces nos quedaríamos con el mismo problema; esta vez, con un struct no existente. Para solucionar esto, podemos escribir struct B; antes de la definición de la estructura A. Esto se llama una declaración hacia adelante. Esto sólo deja que el compilador sabe que struct B es un tipo válido que estará totalmente definido más adelante o en otro lugar. Mi nombre es Rob Bowden, y esto es CS50. [CS50.TV]