[Powered by Google Translate] Problema Sección Set 2: Edición Hacker Rob Bowden, Universidad de Harvard Esto es CS50. CS50.TV Por lo tanto, soy Rob. Soy estudiante de último año en Kirkland. Este es mi tercer año TFing CS50. Es la primera vez que estamos cambiando de la sección tradicional conferencia-estilo, donde sólo un poco de lo que sucedió en opinión conferencia y luego ustedes hacer preguntas, ahora a ser mucho más basado en problemas, donde utilizamos los espacios, y - Oh, así que la idea es ir al enlace que te envié y luego vas a estar en mi espacio. ¿Nadie tiene una computadora portátil? Bien. Así que vamos a usar esto, y vamos a estar haciendo los problemas de vivir en la sección y discutirlas y averiguar lo que está mal y yo podría tirar un poco de su código, y yo podría hablar de sus ideas. Entonces, ¿alguien ha tenido problemas? Puedes chatear en el lado, yo no sé si tendremos razón para ello. Ahora, como el supersección anterior, si estuviera en esa clase, ya sabes de qué se trata. En todos los conjuntos P que va a ser estas secciones. Entonces P-set 2, pliego de condiciones, supongo que lo vi en P-1 juego ya. Pero podemos ver P-set 2 para lo que vamos a ir sobre la actualidad. Y verás una sección de preguntas. Así que esto va a ser en todos los P-series, habrá una sección de preguntas. Hasta ahora hemos dicho: "Considere esto una oportunidad para practicar". No se le pidió que presentara este programa. La idea es que estos se supone que el tipo de ayuda a empezar con el conjunto de problemas. Supongo que en la edición de Hacker, muchos de ellos se supone que son sólo cosas nuevas e interesantes que aprender. Puede que no sean directamente aplicables al conjunto de problemas. Y en este momento no vamos a tener que someterlos, pero en teoría, para conjuntos de problemas posteriores, es posible que los presente, y por lo tanto usted puede venir a la sección o mirar la sección para obtener las respuestas, o simplemente puedes conseguirlos por su cuenta si usted no tiene ganas de disfrutar de mi presencia. Así que el - Creo que esta es la primera. Oh. Además, en estas secciones de preguntas ya os hemos hará preguntas acerca de los pantalones cortos. Así que supongo que, en teoría, se supone que debes ver esto antes de llegar a la sección, pero está bien si no lo hace, vamos a ir sobre ellos de todos modos. Así que podemos comenzar con éstas: "¿Cómo un bucle while difieren de un bucle do-while? ¿Cuándo es el último particularmente útil? " Así que alguien tiene alguna - [Estudiante] El do-while siempre se ejecutará al menos una vez. Sí. Así que esa es la diferencia. Un bucle while - I'Ll hazlo aquí - bucle while, tenemos la condición aquí mismo, mientras que un do-while, usted no tiene una condición hasta que lleguemos hasta aquí. Y así, cuando el programa se ejecuta, y se pone al bucle while, inmediatamente se comprueba si se cumple esta condición. Si esa condición no es cierto, se acaba de saltar el bucle completo. Do-while, ya que el programa se está ejecutando, se pone al "hacer". Nada sucede en este momento, sólo continúa ejecutando. Luego cuando llega el "tiempo", si la condición es verdadera, que va a tejer por atrás y hacerlo de nuevo y una y otra vez hasta que la condición no es verdadera y entonces sólo se concreta. Por lo tanto, la diferencia es, que esto puede pasar directamente desde el principio. Esto necesariamente se ejecuta una vez y luego puede ejecutar más veces si la condición sigue siendo cierto. De modo que el bucle mientras que sólo lo hará una vez, o - el bucle while - no tenga que hacerlo en absoluto, ya que en cuanto lleguemos a él, si la condición es falsa, sólo tendremos que pasar directamente sobre él. Considerando que el do-while, lo vamos a ejecutar una vez, necesariamente. Entonces, cuando llegamos a la condición, comprobamos si es cierto o falso. Si es cierto, vamos a hacerlo de nuevo, y si es falso, sólo tendremos que seguir adelante. Por eso, cuando es este último particularmente útil? Así que puedo decir que en la totalidad de los 4 años, 3 años, lo que sea, que he estado programando, he utilizado este, al igual que, menos de 10 veces. Y, probablemente, cinco de ellos están en CS50 cuando estamos introduciendo do-while. Así que cuando usted utiliza do-while? ¿Cuándo es el - sí? [Estudiante] Cuando usted está tratando de obtener la entrada del usuario, o algo que desee comprobar - Si. Así que do-while bucles, entrada de usuario es el grande. Es por eso que en los conjuntos de problemas primero de un par, cuando quieras hacer al usuario, como, "Dame una cadena," no se puede continuar hasta que llegue esa cadena. Y por lo que, necesariamente, tienen que pedir la cadena de por lo menos una vez. Pero si contestan algo malo, entonces usted necesita para tejer por atrás y volver a preguntar. Pero más allá de la entrada del usuario, es muy raro que me encuentro con un caso donde quiero bucle "al menos una vez", pero posiblemente más. Preguntas o -? ¿Alguien ha utilizado un bucle do-while en otro sitio? Bien. Así que el siguiente es: "¿Qué identificador no declarado suelen indicar si emitida por sonido metálico? " Entonces, ¿qué tipo de código podría escribir para obtener 'identificador no declarado? [Estudiante] Que x = 2? Así que sólo puedo intentar aquí, x = 2. Vamos a ejecutar este - ¡oh, no haga clic en él. Así que aquí tenemos - todos los derechos. "El uso de x identificador no declarado". Así que ese es el identificador no declarado, una variable. A menudo se llama una variable de un identificador. Así que tal vez no sabe que es en realidad una variable, y no sabe lo que es. Así que es un identificador. Entonces, ¿por qué está declarado? Si. Así que para ser claros sobre la terminología, la declaración de una variable es cuando usted dice "x int" o "S String", lo que sea. La inicialización de la variable, o la asignación de la variable, es cuando usted dice "x = 2". Así que podemos hacer esto en pasos separados, int x, x = 2, y hasta que - podemos tener un montón de cosas aquí - pero hasta esta línea pasa, x sigue sin inicializar, pero ha sido declarado. Y, entonces, obviamente, puede hacerlo en una línea, y ahora estamos declarando y la inicialización. ¿Preguntas? Y finalmente, "¿Por qué no es el cifrado César muy seguro?" Así que primero, ¿alguien quiere decir lo que el cifrado César es? [Estudiante] Caesar Cipher es justo que asigne, puede cambiar cada letra, un cierto número de cartas repasar y volver otra vez, y no es muy seguro, ya que sólo hay 26 opciones posibles y sólo hay que probar cada uno de ellos hasta que lo consigas. Oh. Por lo tanto, debo repetirlo? El cifrado César, es - Es decir, se le trata con él sobre los problemas que usted - o supongo que la edición estándar del conjunto de problemas que no está en la edición hacker. Así que en la edición estándar para el conjunto de problemas, se obtiene un mensaje como: "Hola, mundo" y también tiene un número como 6, y se toma ese mensaje, y cada personaje individual, lo gira por seis posiciones en el alfabeto. Así que la 'h' se convertiría en hola h-i-j-k-l-m-n. Así que la primera letra será n. Hacemos lo mismo con el correo. Si tenemos una, digamos, z o algo así, entonces nos envuelva la vuelta a 'A'. Pero cada personaje tiene un ciclo de 6 caracteres más adelante en el alfabeto, y no es muy seguro ya que sólo hay 26 posibilidades de cuántas maneras se puede envolver una sola letra. Así que usted puede probar todo 26 de ellos y, presumiblemente, de un mensaje bastante largo, sólo 1 de los 26 posibles cosas va a ser legible, y el legible va a ser el mensaje original. Así que no es una muy buena manera de encriptar cualquier cosa. Sin relación con esos pantalones cortos, "¿Qué es una función?" Entonces, ¿qué es una función? Sí. [Estudiante] Es como un pedazo de código que se puede llamar para ir a través y luego obtener el valor de retorno de lo que sea. Si. Así que voy a contestar también responder a la siguiente - o por repetición también acaba de responder a la siguiente. Puede utilizar las funciones en lugar de simplemente copiar y pegar el código una y otra vez. Basta con echar ese código, lo puso en una succion, y entonces se podría simplemente llamar a la función en todo cuanto has estado copiando y pegando. Así funciones son útiles. Así que ahora vamos a resolver problemas reales. La primera de ellas. Así que la idea de la primera es, se le pasa una cadena, ya pesar de la - o es lo que dice todo en minúsculas? No dice en minúsculas. De modo que el mensaje puede ser cualquier cosa, y - oh no. Lo hace. "Para simplificar, se puede suponer que el usuario sólo va a introducir letras minúsculas y espacios." Así que le pase un mensaje con sólo letras minúsculas y luego alternar entre el capital y minúsculas - Podemos cambiar la cadena a ser capital y minúsculas, alternando. Así que antes de darle un segundo para bucear incluso en el problema, ¿qué es lo primero que tenemos que hacer? Oh, ¿qué acabo de hacer clic en? Oh, me acaba de hacer clic en un e-mail aquí. Así que lo primero que tenemos que hacer - estoy buscando a la persona equivocada? ¿Es esto parte de éste? No, esos son todavía allí, sin embargo. Bueno, todavía está aquí. Ahora no podemos asumir -? Sí. Aquí no podemos suponer que es sólo minúsculas y espacios. Así que ahora tenemos que lidiar con el hecho de que las cartas pueden ser lo que queramos que sean. Así que lo primero que queremos hacer es entender el mensaje. Sólo tenemos que conseguir una cadena, string s = GetString, está bien. Ahora bien, este problema, hay un par de formas de hacerlo. Pero vamos a querer utilizar operadores bit a bit aquí. ¿Hay personas que no se encontraban en el supersección, o algo, y no sé lo que son operadores bit a bit? O cómo se relacionan con ASCII de alguna manera? [Estudiante] yo no estaba en la supersección, pero sé lo que son operadores bit a bit. Bien. Así que no tengo que ir a través de los fundamentos de ellos, pero te lo explico lo que vamos a querer utilizar aquí. Así que 'A': Representación binaria del capital A, el número es 65. Yo sólo voy a mirar - 41 va a ser 01000001. Así que debe ser del 65 en decimal, por lo que esta es la representación binaria del carácter de capital A. Ahora, la representación binaria de la minúscula 'a' va a ser lo mismo, casi. ¿Es eso - 6, sí. Esto es correcto. Así el capital binario Un minúsculas, binario 'a'. Así que notar que la diferencia entre A y A 'a' es este único bit. Y esto pasa a ser el bit 32, el bit que representa el número 32. Y eso tiene sentido puesto que A es 65; 'a' es 97. La diferencia entre ellos es de 32. Así que ahora que sabemos que podemos pasar de la A a la 'a' mediante la adopción de un y bit a bit que ORing, con - que se parece a un 1. Este es un O-lógico, con 00100000, y que va a darnos 'a'. Y que podemos obtener de la 'a' a la A, bit a bit AND con 11, 0 en ese lugar, 11111. Así que esto, entonces nos dará exactamente lo que 'a' era, pero se anulan este bit individual, por lo que tendremos 01000001, yo no sé si he contado bien. Pero esta técnica de bit a bit ORing llegar desde la capital a minúsculas, y bit a bit AND para obtener de minúsculas a capital no es exclusiva de A. Todas las letras, K vs K, Z vs z, todos ellos son sólo va a diferir en este único bit. Y para que pueda usar esto para cambiar de cualquier letra minúscula a cualquier letra mayúscula y viceversa. Bien. Así que una manera fácil de conseguir de esto - así que en vez de tener que escribir cualquier cosa 1011111 es - una manera fácil de representar este número, y esto no es una que fui en el supersección, pero tilde (~) es otro operador bit a bit. Lo que ~ hace es que analiza la representación de bits. Tomemos cualquier número. Esto es sólo un número binario, y lo ~ hace es que sólo invierte todos los bits. Así que este fue un 1, ahora un 0, esto es un 0, ahora un 1, 010100. Así que eso es todo ~ no. Así que 32 va a ser el número - deshacerse de eso - así que 32 va a ser el número 00100000, y así de esta ~ va a ser este número aquí que yo AND 'a' con. ¿Todo el mundo ve eso? Esto es bastante común, como cuando se quiere averiguar por las cosas que más tarde podríamos estar viendo, cuando queremos ver si - o queremos que todo, cada bit individual excepto por 1 se tiende a hacer ~ de la parte que nosotros no queremos establecer. Así que no queremos que el conjunto de 32 bits, por lo que es de ~ 32. Bien. Así que podemos usar todos los que están aquí. Muy bien, así que está bien si no estás hecho, que poco a poco se acerco juntos, o caminar sobre esto, así que - a través de esto. Caminar a través de esto. Así que tenemos nuestra cadena, y queremos un bucle sobre cada personaje en esa cadena y hacer algo con ella. Entonces, ¿cómo hacemos un bucle sobre una cuerda? ¿Qué debemos usar? Yo no lo voy a hacer aquí. Si. Así que tengo mi iterador, y él lo dijo, pero ¿cómo puedo saber cuántos caracteres se encuentran en la cuerda? Strlen (s), entonces i + +. Así que lo que hemos hecho aquí no es la mejor manera de hacer las cosas. ¿Alguien sabe por qué? Debido a que usted está comprobando el idioma de la cadena cada vez. Así que vamos a querer mover strlen, podría decir aquí, int longitud = strlen (s), y luego hacer i > 1 bit. Podría ser más de 1 bit, siempre y cuando todos los bits de debajo de esta posición son los mismos. Así que necesitamos por lo menos 26 caracteres - o, hay 26 caracteres. Así que necesitamos por lo menos 26 números para representar la diferencia - La diferencia entre A y, 'a' tiene que ser de al menos 26 o de lo contrario no habría representado todos los números de capital. Esto significa que A, si empezamos a 1, que va a utilizar todos estos bits, todos estos primeros 5 bits para representar todo a la Z. Es por eso que el siguiente bit o bit de esto, el siguiente bit es el que ha optado por distinguir entre A y A '.' Por eso también, en la tabla ASCII, hay 5 símbolos que separan las letras mayúsculas de las minúsculas. Dado que esos son los símbolos, el extra 5 que trae a colación el 32 es la diferencia entre ellos. [Estudiante] Así que podemos hacerlo, porque ASCII está diseñado de esa manera. Sí. Pero ASCII - la diferencia también podría ser tanto de estos bits. Al igual que, si A fuera 10000001, y 'a' es 11100001 - me olvide, lo que sea. Pero si fuera así, entonces podría usar 'a' - A. Es que ahora la diferencia entre A y A 'a' es todavía estos 2 bits. Creo que ha escrito 48. ¿Es 32 + 64? Yo creo que es? Todavía sería 2 bits de cada carácter;, como, Z y Z, K y k, todavía tendrían los mismos bits exactos establecidos excepción de los 2 bits. Así que, mientras que siempre es cierto, independientemente de si estamos usando ASCII o algún otro sistema, mientras que sólo hay un número fijo de bits que son diferentes para cada personaje, luego de que funciona bien. Es sólo que el 32 se creó porque es el primero que podríamos utilizar. >> Cool. Yo tiendo a preferir, en caso de que no hemos visto, si el bloque es más que una sola línea, usted puede deshacerse de las llaves, así que tiendo a preferir hacerlo. Además, usted sabe lo que puede hacer cosas como s [i] + = 1? También puede hacer s [i] = 32 AND bit a bit. Y bit a bit OR = 32. Además, cuentan mod 2 == 0. Así que recuerde que - no lo voy a escribir - cualquier valor distinto de cero es verdadero y 0 es falso. Así que "si mod cuenta 2 == 0" es lo mismo que decir "si no cuentan mod 2". Probablemente me acaba de invertir las líneas y le dijo: "si el recuento mod 2, realizar las OR 1, más se la AND 1 ", por lo que no necesitaba el" no ". Pero esto funciona igual de bien. ¿Y qué otra cosa puedo hacer aquí? Se les puede combinar con ternario si quería, pero después de que acabara de hacer las cosas más desordenado y probablemente más difícil de leer, así que no vamos a hacer eso. Alguien tiene alguna sugerencia? ¿Eso es todo el problema pedí? Oh yeah. Así que deshacerse de estas líneas vacías, ahora vamos a imprimir f,% s es el de las cadenas, Vamos a imprimir f, s. Ahora vamos a ejecutarlo. ¿He hecho algo mal? Eso es un \ ", quiero un n. Bien. Ahora vamos a ejecutarlo. Probablemente voy a gritar a mí. Strlen está en string.h. Así que esto es lo bueno de Clang es que le dice lo que se encuentra, en lugar de GCC que sólo dice: "Oye, te olvidaste de algo, no sé lo que era." Pero esto me va a decir: "Vosotros pensasteis que incluya string.h". Así que no me pedirá nada, por lo que no está diciendo nada. Pero vamos a hacer con su ejemplo, "thanks 4 the add". Esto se ve muy bien. ¡Hurra. Así que volviendo a su principal, yo casi nunca lo hacen. Es opcional. Y principal es la única función para la que es opcional. Si usted no devuelve nada de principal, se supone que la intención de devolver 0. ¿Preguntas? Bien. Así que ahora el segundo problema. "Recuerde que en la segunda conferencia 2 semanas de intercambio de valores que las variables de 2 'al pasar esos dos variables a una función (aunque haya sido convocada swap) no es exactamente funciona, al menos no sin 'punteros' ". Y hacer caso omiso de los punteros hasta que lleguemos a ellos. Queremos intercambiar dos variables; no estamos usando una función para hacerlo. Todavía vamos a hacerlo en principal como se dice. Pero para usar esos 2 variables, no queremos usar una variable temporal. Hay dos maneras de hacer esto. Se puede hacer uso de sus operadores binarios tradicionales. Así que ¿alguien sabe una manera rápida y sucia de hacer eso? En realidad, puede tardar un minuto de pensar. Si tengo - Voy a poner el problema arriba como se lo preguntan. Así que si tengo dos variables, A, que es simplemente un entero que me dan, y B suma variable, que es otro número entero que me dan. Así que si tengo estas 2 variables, ahora quiero intercambiarlas. El tradicional, usando sus operadores binarios regulares, es decir, como +, -, ÷. No bitwise operadores que actúan en binario. Así que usando -, +, ÷, y todos esos. Podríamos cambiar haciendo algo como a = a + b, y b = a - b, a = a - b. Por lo tanto, la cordura cheque, y luego vamos a ver por qué funciona. Digamos que a = 7, b = 3, entonces a + b va a ser 10. Así que ahora estamos estableciendo a = 10, y luego hacemos b = a - b. Así que estamos haciendo b = a - b, que va a ser 7, y b = a - b de nuevo, o a = a - b. Que va a ser de 10 - 7, que es 3. Así que ahora, con razón, era "un '7, b tenía 3 años, y ahora es de 7 y b' a 'es 3. Para que tipo de sentido, 'a' es la combinación de los números 2. En este momento, "a" es la combinación, y entonces estamos restando el b original, y entonces estamos restando lo que fue el original "a." Pero esto no funciona para todos los números. Para ver esto, consideremos un sistema, por lo que normalmente ocurre enteros como 32 bits. Vamos a trabajar en algo que es sólo como 4 bits. Espero llegar a un buen ejemplo en estos momentos. Así que, lo sé, esto será fácil. Digamos que nuestros 2 números son 1111 y 1111, por lo que estamos en binario en estos momentos. En décimas reales, si usted quiere pensar de esa manera, a. = 15 y b = 15 Y lo que esperamos, después de que los swap - que ni siquiera tienen que ser los mismos números, pero lo hice de esta manera. Hagamos que ellos no los mismos números. Vamos a hacer 1111 y 0001. Así que a = 15 y b = 1. Después de cambiarlos, esperamos que 'a' igual a 1 y b para ser 15. Por lo tanto el primer paso es a = a + b. Nuestros números son sólo 4 bits de ancho, por lo que 'un', que es 1111, + b, que es 0001, va a terminar siendo 10000, pero sólo tenemos 4 bits. Así que ahora a = 0. Y ahora queremos fijar b = a - b - de hecho, sigue funcionando a la perfección. a = a - vamos a ver si esto funciona perfectamente - b. Así entonces b = 0 - 1, que todavía sería 15, y entonces a = a - b, que sería 1. Tal vez esto funciona. Siento que hay una razón que no funciona con regularidad. De acuerdo, por lo que trabajar en el supuesto de que no funciona con operaciones binarias regulares, y voy a buscar - Voy a buscar en Google para ver si eso es cierto. Por eso queremos hacerlo mediante operadores bit a bit, y la clave aquí es XOR. Por lo tanto, la introducción de XOR (^) si usted no lo ha visto todavía. Es, de nuevo, un operador bit a bit por lo que actúa poco a poco, y es - Si usted tiene los bits 0 y 1, entonces esto va a ser 1. Si usted tiene los bits 1 y 0, que va a ser 1, tiene los bits 0 y 0 será 0, y si usted tiene los bits 1 y 1 será 0. Así que es como OR. Si cualquiera de los bits son verdaderas, es 1, pero a diferencia de O, no pueden ser los dos bits que son verdaderas. O habría este ser 1, XOR tendría este ser 0. Así que vamos a querer utilizar XOR aquí. Piense en esto por un minuto, voy a Google. Bueno, no se puede leer que, estoy actualmente en la página XOR algoritmo de intercambio. Esperemos que esto explica por qué No puedo - Este es exactamente el algoritmo que acabamos de hacer. Sigo sin ver por qué - Tengo que acaba de recoger un mal ejemplo, pero este caso donde 'a' pasó a convertirse en 0, después de llegar a 5 bits, por lo que ahora 'a' es 0, eso es lo que se llama "desbordamiento entero". Según Wikipedia, "A diferencia de la permuta XOR, esta modificación requiere que usa algunos métodos para garantizar que x + y no causa un desbordamiento de entero. " Así que este tiene problemas, lo que fue desbordamiento de entero, pero hice algo mal. No estoy seguro. Voy a tratar de llegar a otro. [Estudiante] Bueno, no es de desbordamiento de enteros cuando usted está tratando de poner un número en allí más grande que la cantidad de bits que se han asignado? Si. Disponemos de 4 bits. Eso es - teníamos 4 bits, que a continuación, intenta agregar 1 a la misma, por lo que terminamos con 5 bits. Pero el quinto bit sólo se corta, sí. En realidad, might - [Estudiante] ¿Esto te generará un error, o tiene que - que arrojaría un error? No. Así que no hay error. Al llegar al nivel de ensamblado, un poco especial en alguna parte se establece que decía que había un exceso de capacidad, pero en C que tipo de sólo no se ocupan de eso. Usted realmente no puede ocuparse de ella a menos que utilice las instrucciones especiales de montaje en C. Pensemos intercambio XOR. Y creo que el artículo de Wikipedia también podría haber estado diciendo que - Por lo tanto, también planteó la aritmética modular, así que supongo que era, en teoría, hacer aritmética modular cuando dije que el 0 - 1 es 15 otra vez. Así que en realidad podría - en un procesador regular que hace 0 - 1 = 15. Ya que terminan en 0, se resta 1, por lo que entonces, sólo se envuelve de nuevo hacia 1111. Así que este algoritmo podría funcionar, el a + b, el a - b, b - a, que podría estar bien. Pero hay algunos procesadores que no lo hacen, por lo que no estaría bien en aquellos específicos. Intercambio XOR funciona en cualquier procesador. Bien. La idea es que se supone que debe ser el mismo, sin embargo. Dónde estamos utilizando XOR para conseguir de alguna manera la información de ambos en 1 de las variables, y luego extraer la información de las variables individuales de nuevo. Así que ¿alguien tiene ideas / respuesta? [Respuesta Estudiantil, ininteligible] Así que esto debería funcionar, y también, XOR es conmutativa. Independientemente de qué orden estos 2 números resultan ser en aquí, Este resultado va a ser el mismo. Así que a ^ b es b ^ a. Usted también puede ver este escrito como una ^ = b, b = a ^, a ^ = b de nuevo. Así que esto es lo correcto, y ver por qué esto funciona, piense en los bits. El uso de un número más bien pequeño, digamos 11001, y 01100. Así que esto es 'a', lo que es b. Así que a ^ = b. Vamos a ser la creación 'a' = a la XOR de estas 2 cosas. Así 1 ^ 0 es 1; 1 ^ 1 es 0; 0 ^ 1 es 1, y 0 ^ 0 es 0; 1 ^ 0 es 1. Así que 'a,' si nos fijamos en el número decimal, que va a ser - no vas a ver mucho de la relación entre el original 'a' y el nuevo 'a,' pero mirando a los bits, 'a' es ahora como una malla de la información tanto de la original 'a' y b del original. Así que si tomamos b ^ a, vemos que vamos a terminar en el original 'a'. Y si tomamos el original 'a' ^ el nuevo 'a,' vemos que terminamos en el b original. Así que (a ^ b) ^ b = el original 'a.' Y (a ^ b) ^ a = b original. No es - otra forma de ver esto es algo en sí XOR es siempre 0. Así 1101 ^ 1101, todos los bits se va a ser el mismo. Así que nunca va a ser un caso en que 1 es un 0 y el otro es 1. Así que esto es 0000. El mismo con esto. (A ^ b) ^ b es como un ^ (b ^ b). (B ^ b) va a ser 0, a ^ 0 es sólo va a ser "a", puesto que todos los bits son 0. Así que los únicos que van a estar donde 'a' fue originalmente un 1 - tenía unos. Y la misma idea aquí, yo estoy bastante seguro de que es también conmutativa. Si. Yo he dicho antes que era conmutativa. El ^ 'a,' y es asociativa, así que ahora (b ^ a) ^ a. Y podemos hacer b ^ (a ^ a). Y así, una vez más, obtenemos el b original. Así que 'a' es ahora la combinación de 'A' y B juntos. Con nuestro nuevo combo 'a' decimos b = combo 'a' ^ b el original, obtenemos la original 'a.' Y ahora un combo = 'a' ^ b del nuevo, que era la original - o lo que es ahora lo que era 'a' o b. Ese es el caso aquí. Esto es = b, b edad. Así que ahora todo está en el orden cambiado. Si en realidad se veía en los bits, b = a ^ b, va a XOR estos 2, y la respuesta va a ser esto, y entonces a = a ^ b se XORing estos 2 y la respuesta es la siguiente. ¿Preguntas? Bien. Así que el último es algo mucho más difícil. [Estudiante] Creo que tiene una duda al respecto. >> Oh, lo siento. [Estudiante] ¿Qué es realmente más rápido? Si utiliza este XOR, o es si se declara una nueva variable? Entonces, ¿qué es más rápido, se declara una nueva variable o usar XOR a cambiar? La respuesta es, con toda probabilidad, una variable temporal. Y es que una vez que se compila abajo - por lo que en el nivel de ensamblado, no hay tal cosa como variables locales o cualesquiera variables temporales o de cualquiera de estas cosas. Son como - no hay memoria, y hay registros. Los registros son donde las cosas están ocurriendo activamente. No agregue 2 cosas en la memoria, agregar 2 cosas en los registros. Y traer cosas de la memoria en los registros para luego añadir, y entonces usted puede volver a ponerlos en la memoria, pero toda la acción sucede en los registros. Así que cuando usted está utilizando el enfoque variable temporal, por lo general lo que sucede es estos 2 números ya están en los registros. Y luego, a partir de ese momento, después de haberlos cambiado, sólo voy a empezar a usar el otro registro. En cualquier lugar donde había estado utilizando b, sólo se usará el registro que ya estaba almacenando 'a'. Por lo tanto, no necesita hacer nada para hacer realidad el intercambio. ¿Sí? [Estudiante] Pero también requiere más memoria, ¿no? Sólo serán más memoria si se necesita almacenar dicha variable temporal. Como si luego usa esa variable temporal de nuevo en alguna parte, entonces - o se asigna algo a esa variable temporal. Así que si en algún momento en el tiempo 'a,' b en temperatura tienen valores distintos o algo así, entonces va a tener posiciones distintas en la memoria, pero es cierto que hay muchas variables locales que sólo existen en registros. En cuyo caso, nunca se ha puesto en la memoria, y por lo que nunca está perdiendo la memoria. Bien. La última pregunta es un poco más. Así que aquí, en este aparato CS50, existe un diccionario. Y la razón de esto es porque [? B66] es un corrector ortográfico en el que estará escribiendo utilizando tablas hash o trata o alguna estructura de datos. Usted va a estar escribiendo un corrector ortográfico, y usted va a estar usando este diccionario para hacerlo. Pero para este problema, sólo vamos a mirar hacia arriba para ver si una palabra está en el diccionario. Así que en lugar de almacenar todo el diccionario de alguna estructura de datos y mirando por encima de todo un documento para ver si algo está mal escrito, sólo queremos encontrar una palabra. Así que sólo puede escanear a través de todo el diccionario y si no se encuentra la palabra en el diccionario entero, entonces no estaba allí. Si escanear a través de todo el diccionario y veo la palabra, entonces estamos bien, que lo encontramos. Aquí dice que queremos empezar a buscar en C de manejo de archivos de función, ya que queremos leer el diccionario, pero voy a dar la receta aquí en cuanto a las funciones que debe pensar. Voy a escribir sobre Spaces. Así que los principales que podría querer mirar f se abre y luego, inevitablemente, f cerrado, que irá al final de su programa, y ​​f f exploración. También puede utilizar f leer, pero es probable que no desee ya que - usted no termine encima de necesitar eso. F exploración f es lo que vas a utilizar para escanear en el diccionario. Y lo que no es necesario codificar la solución, sólo trato y como pseudo-código de la forma a una solución, y luego vamos a hablar de ello. Y, de hecho, puesto que ya te dio estos, si vas a cualquier terminal o shell de su aparato, Yo - Yo suelo - si usted no ha visto todavía, no sé si lo has hecho en clase, pero el hombre, por lo que las páginas de manual, son muy útiles para observar casi cualquier función. Así que puedo hacer, como, f hombre, escaneo f. Esta es ahora la información sobre la familia f exploración de las funciones. Yo también podría hacer f hombre, abierto, y que me dará los detalles de eso. Así que si usted sabe cuál es la función que está usando, o que usted está leyendo el código y ves alguna función y usted es como, "¿Qué hace esto?" Sólo el hombre que la función de nombre. Hay un par de ejemplos raros donde es posible que tenga que decir gusta. man 2 que el nombre de la función, o man 3 que el nombre de la función, pero sólo tienes que hacer que el hombre si el nombre de la función no le suceda a trabajar por primera vez. [Estudiante] Así que me estoy leyendo la página de manual para abrir, pero todavía estoy confundido sobre cómo usarlo y el programa. Bien. Muchas de las páginas del manual son menos que útiles. Son más útiles si ya saben lo que hacen y luego sólo tiene que recordar el orden de los argumentos o algo así. O se le puede dar un panorama general, pero algunos de ellos son muy abrumador. Como f exploración f, también. Te da la información para todas estas funciones, y una línea que pasa por aquí para decir, "F exploración f lee desde el punto cadena o un arroyo." Pero f abrirla. Así que, ¿cómo usamos f abierto? La idea de un programa que tiene que hacer el archivo de E / S que primero tiene que abrir el archivo que queremos hacer las cosas con, e inevitablemente, leer cosas de ese archivo y hacer cosas con ellos. F abierto es lo que usamos para abrir el archivo. Lo que volvamos, ¿y qué archivo queremos abrir, nos da la - aquí se dice "/ user / share / dict / words". Este es el archivo que desea abrir, y queremos abrirlo - tenemos que especificar explícitamente si queremos abrir para leer o si queremos abrirlo a escribir. Hay un par de combinaciones y esas cosas, pero queremos abrir este para la lectura. Queremos leer desde el archivo. Entonces, ¿qué hace este cambio? Se devuelve un archivo de estrella (*), y sólo voy a mostrar todo en la variable f, de modo *, de nuevo, es un puntero, pero no queremos hacer frente a los punteros. Usted puede pensar en como f, f es ahora la variable que se va a utilizar para representar el archivo. Así que si usted quiere leer el archivo, lee de f. Si desea cerrar el archivo, cierra f. Así que al final del programa, cuando inevitablemente quiere cerrar el archivo, ¿qué debemos hacer? Queremos cerrar f. Así que ahora la función de último archivo que vamos a querer utilizar es el escaneo f, f f exploración. Y lo que hace es que analiza el archivo en busca de un patrón que corresponda. En cuanto a la página del manual aquí, vemos que f int f exploración, ignorar el valor devuelto por el momento. El primer argumento es la corriente * archivo, por lo que el primer argumento que vamos a querer pasar es f. Estamos explorando sobre f. El segundo argumento es una cadena de formato. Te daré una cadena de formato en estos momentos. Creo que nos pasó a decir: 127S \ n, que mucho de eso es innecesario. La idea de lo que esa cadena de formato es, es que se pueda imaginar f exploración como lo opuesto a la f impresión. Así impresión f, f impresión que también utilizan este tipo de parámetro de formato, pero en f impresión de lo que estamos haciendo es - echemos un vistazo a un equivalente. Así imprimir f, y de hecho hay también f impresión f, donde el primer argumento va a ser f. Cuando se imprime f, podríamos decir algo como, "print 127S \ n" y luego, si le pasamos un poco de cuerda, que va a imprimir esta cadena y luego una nueva línea. ¿Qué significa 127, estoy bastante seguro, pero nunca me he limitado a ella, Ni siquiera tendría que decir '127 'en el f impresión, pero lo que significa es imprimir los primeros 127 caracteres. Así que estoy bastante seguro de que es así. Usted puede buscar en Google para eso. Pero en la siguiente estoy casi seguro de que significa eso. Así que esto es imprimir los primeros 127 caracteres, seguido de una nueva línea. F exploración f ahora, en vez de mirar a una variable y de imprimirlo, que va a ver un poco de cuerda, y almacenar el patrón en la variable. Vamos a utilizar realmente f exploración en un ejemplo diferente. Así que vamos a decir que tuvimos algún tipo int x = 4, y queríamos crear una cadena hecha de - quiso crear la cadena que era como, este vendrá mucho más tarde, algo que es como 4.jpg. Así que esto podría ser un programa donde tendrá contador suma, Resumiendo contrarrestar i, y desea ahorrar un montón de imágenes. Así que usted quiere ahorrar i.jpg, donde i es un poco iteración del bucle. Entonces, ¿cómo hacemos para que esta cadena JPEG? Si quieres imprimir 4.jpg, podríamos decir f impresión, d.jpg%, y entonces se imprime para que JPEG. Pero si queremos salvar el 4.jpg cadena, utilizamos f exploración. Así que la cadena s - en realidad nos puedo - carácter, char s, vamos a ir 100. Así que me acaba de declarar algún arreglo de 100 caracteres, y eso es lo que estamos inevitablemente va a almacenar esa JPEG pulg Así que vamos a usar f escaneado y el formato, cómo diríamos d.jpg% con el fin de imprimir 4.jpg, el formato de este va a ser d.jpg%. Así que el formato es d.jpg%, lo que quiere reemplazar con% d es x, y ahora tenemos que guardar esa cadena en alguna parte. Y donde vamos a almacenar esta cadena está en el array s. Así que después de esta línea de código, s, si imprimimos f, s% s de la variable, que va a imprimir 4.jpg. Entonces f exploración f es la misma que scan f, excepto que ahora ve hacia el archivo por lo que para almacenar en s. Eso es lo que el último argumento va a ser. Queremos guardar - "familia f Scan de exploraciones funciones en tanto de acuerdo al formato que trató a continuación. Si se almacenan en los puntos de ubicación podría regresar - " No, puede ser bueno. Déjame pensar por un segundo. Así exploración f no lo hace - ¿qué diablos es la función que hace eso? Así exploración f no se va a tomar un entero y hacer punto jpg. Va a [murmura]. Guardar variable int en cadena int C. ¿Qué es esta variable, o lo que es esta función se llama? Sí. Eso es - sí. Así que lo que se define a usted antes era s f impresión, que - que tiene mucho más sentido, ¿por qué me dijo que era mucho más parecido f impresión. Scan f es todavía una especie de f impresión, pero f s de impresión se va a escanear a través de y sustituya las variables y ahora se almacenan en una cadena. En lugar de imprimirlo, lo almacena en una cadena. Así que ignora que por completo. Usted todavía puede pensar en el especificador de formato como el de f impresión. Así que ahora, si queríamos hacer lo 4.jpg, haríamos f s de impresión, x de esto. Entonces, ¿qué está haciendo exploración f - ¿Cuál era tu pregunta va a ser? [Estudiante] Estoy confundido sobre lo que estamos tratando de hacer aquí con que JPEG. ¿Se puede explicar que una vez más? Así que esta fue - es menos relevent de exploración f f ahora, con suerte, se unirá de nuevo en algún tipo de camino. Pero lo que inicialmente tenía la intención de mostrar era - es en realidad directamente relacionados con éstos [? F5] Vas a estar usando f s de impresión, donde, digamos que tenemos 100 imágenes, y quieres leer la imagen 1.jpg, 2.jpg, 3.jpg. Así que para hacer eso, tiene que f abierto, y entonces usted tiene que pasar en la cadena que desea abrir. Así que nos gustaría abrir 1.jpg, con el fin de crear la cadena que es 1.jpg, hacemos s f impresión de% d.jpg--no lo hicimos para int i = 0. i <40, i + +. Así impresión% s f d.jpg de i. Así que después de esta línea, ahora la variable o el arreglo s va a 1.jpg. O 0.jpg, 1.jpg, 2.jpg. Por esto se puede abrir, a su vez, cada imagen para leer. Así que eso es lo que s imprimir f hace. ¿Ves lo que s imprimir f está haciendo ahora? [Estudiante] Bueno, por lo que está tomando - crea una cadena, something.jpg, a continuación, lo guarda. Sí. Crea - esta es otra cadena de formato, al igual que f f escaneo y de impresión, donde se inserta todas las variables en el segundo argumento, podría ser s en lugar de i. Tal vez - quiero decir, ese es el caso. Pero cualquiera que sea el orden de los argumentos es. Se va a introducir todas las variables en la cadena de formato y luego almacenar en nuestro buffer, lo llamamos un buffer, que es donde se está almacenando la cadena. Así que estamos almacenando dentro de la cadena s con el formato correcto,% d de haber sido sustituido por 4. [Estudiante] Así que si hacemos esto, es la variable f sólo va a ser reasignado? Sí. Así que debemos cerrar la f original antes de hacer esto. Pero - y luego también, si no hubiera un f abrir aquí, entonces tendríamos que decir - Si. Pero sería abrir un centenar de archivos diferentes. [Estudiante] Pero no sería capaz de acceder o - Está bien. Bien. Así exploración f, f exploración f, es una especie de la misma idea, pero en vez de, en lugar de almacenarla en una cadena, es más como estás ahora repasando un pinchazo y una coincidencia de patrones en contra de esta cadena y almacenar los resultados en variables. Usted puede utilizar f exploración para analizar por algo así 4.jpg y almacenar el número entero en 4 x int suma. Eso es lo que se puede utilizar para exploración f. F f exploración va a hacer que en la línea de comandos. En realidad estoy bastante seguro de que esto es lo que la biblioteca CS50 hace. Así que cuando usted dice, "get int," es escaneado f-ing sobre - f exploración es la forma en que recibe la entrada del usuario. F f exploración que va a hacer lo mismo pero usando un archivo a escanear de nuevo. Así que aquí estamos explorando sobre este archivo. El patrón que estamos tratando de coincidir con alguna cadena que es de 127 caracteres de longitud seguido de una nueva línea Así que estoy bastante seguro de que podríamos incluso a decir "match s", ya que en el diccionario sucede que tenemos, no está garantizado que la palabra es larga, y f f exploración, creo, no se detendrá ante la nueva línea no importa qué. Pero vamos a incluir la nueva línea en el partido, y - [Estudiante] Si no incluimos la nueva línea, no lo encontraría partes de una palabra? It - cada una - ver el diccionario - Así, en el diccionario, se trata de todas nuestras palabras. Cada uno está en una nueva línea. F El análisis se va a recoger esta palabra. Si no incluimos la nueva línea, entonces es posible que la siguiente exploración f sólo leerá la nueva línea. Pero incluso entonces sólo nueva línea pasará por alto la nueva línea. Pero nunca vamos a obtener parte de una palabra, ya que siempre estamos leyendo a una nueva línea, no importa lo que pase. [Estudiante] Pero lo que si usted busca la palabra "cissa," como cissa. Va a encontrar eso, y decir que es una coincidencia? Así que aquí estamos - se lee en - esto es realmente un buen punto. Nunca estamos usando la corriente - la palabra que estamos buscando es el argumento de comando de primera línea. Así cadena, palabra = argv 1. Así que la cadena que estamos buscando es argv 1. No estamos buscando una palabra en absoluto en nuestra f exploración. Lo que estábamos haciendo con la exploración f está consiguiendo cada palabra en el diccionario, y luego una vez que tengamos esa palabra que vamos a usar strcmp para compararlos. Vamos a comparar nuestra palabra y lo que acabamos de leer pulg Por lo tanto, inevitablemente, vamos a terminar haciendo un montón de exploración fs hasta que da la casualidad de que f exploración volverá - ha de devolver uno, el tiempo que ha coincidido con una nueva palabra, y volverá otra cosa tan pronto como se han logrado alcanzar la palabra. Estamos leyendo el diccionario entero, almacenar línea a línea cada palabra en la variable s. Entonces estamos comparando palabra con s, y si la comparación == 0, strcmp pasa a traer 0 si un partido se hizo. Así que si lo fue de 0, entonces podemos imprimir f, emparejado, o palabra en el diccionario, o lo que usted desee imprimir f. Y entonces - que no quieren f cerrar una y otra vez. Este es el tipo de cosas que queremos hacer, y no estamos sólo en busca de la palabra en el diccionario. Así que podríamos hacer eso, si quisiéramos buscar su patrón, Cissa, como dijiste antes, si quisiéramos buscar ese patrón, entonces sería fallar en el caso porque eso no es realmente una palabra, sino una de las palabras en el diccionario que pasa a tener en ella. Por lo que se correspondería con esta palabra, pero este subconjunto de la palabra no es una palabra en sí. Pero esa no es la forma en que se esté usando, estamos leyendo en cada palabra y luego comparar la palabra que tenemos con esa palabra. Así que siempre estamos comparando palabras completas. Me pueden enviar las soluciones finalizadas después. Esta es una especie de cerca la respuesta correcta, creo. [Comentario Estudiante, ininteligible] Oh, ¿puedo deshacerme de eso antes? Char s, creo que dijo 127 - se me olvida lo que es el más grande. Vamos a hacer 128, por lo que ahora s es lo suficientemente largo. No es necesario imprimir nada. También vamos a querer tener cerca a nuestro archivo, y que debe ser sobre la respuesta correcta. CS50.TV