|
231
|
Programación / Programación C/C++ / Re: Borrar texto en la consola usando c
|
en: 2 Mayo 2019, 21:15 pm
|
Respecto a lo de realloc, la verdad no lo sabía, lo había metido porque el código es parte de un trabajo para la universidad, que estamos aprendiendo a programar C, y estaba probando las funciones de asignación dinámica. Si me dices que si no me ahorro mucha memoria puede ser contraproducente, mejor lo quito. Si es por practicar, lo puedes dejar. No va a fallar ni a darte problemas. Simplemente te decía que cuando hablamos de cosas tan simples, como unos pocos bytes, normalmente no vale la pena intentar optimizar. El realloc perfectamente puede decidir no cambiar nada, es decir, no "reducir" la memoria, y simplemente dejar todo como está. Es perfectamente válido y tu programa funcionará sin problemas, pero en ese caso estarías haciendo esa llamada de forma innecesaria (a eso me refería con contraproducente: estás trabajando de más, posiblemente sin beneficio). Es simplemente un consejo general, que antes de optimizar hay que revisar bien lo que hacemos. Muchas veces una "optimización" hecha sin análisis, puede incluso hacer que un programa tenga un rendimiento peor al que tenía antes de la supuesta optimización. Pero te repito, como práctica no hay problema. Cuando tengas más experiencia ya sabrás cuándo vale la pena buscar optimizar y cuándo no.
|
|
|
232
|
Programación / Programación C/C++ / Re: Representación visual de punteros y punteros a punteros..
|
en: 2 Mayo 2019, 20:50 pm
|
Sí, sería como la pusiste. Obviamente estamos hablando de punteros, y en concreto, un puntero a punteros para simular matrices de manera dinámica. En una matriz "real" (arreglo bidimensional): la memoria es toda contigua y existe en la pila, pero evidentemente, y desde que estás hablado de punteros a punteros, no es a lo que te refieres. A menos que te haya entendido mal.
|
|
|
233
|
Programación / Programación C/C++ / Re: Borrar texto en la consola usando c
|
en: 2 Mayo 2019, 20:29 pm
|
Bueno, en realidad es "\b \b", pero supongo que sólo fue error de dedo. Veo algunos problemas con tu código, pero como no usaste etiquetas GeSHi, no sé si algunos sean sólo partes que se "comió" el foro. Algunos detalles: ¿qué pasa si el usuario presiona y presiona y presiona retroceso muchas veces? Luego tienes esto: El return hace que la ejecución del programa regrese a main, por lo que no tiene sentido poner instrucciones después, ya que nunca se ejecutarán. Y de cualquier forma, ese free era incorrecto. Quien llama a tu función es quien debe liberar esa memoria. Si tú la liberaras dentro de la función Password, ya no es válida. Siendo un programa tan simple y pequeño, probablemente aún así funcionaría "correctamente" (por pura suerte) pero sería un error. El realloc está de más. Es un ejemplo perfecto de optimización prematura. Intentar ahorrarte unos pocos bytes realmente no optimiza nada (quizás hace un par de décadas y si estuvieras programando para un microcontrolador con unos pocos KB de memoria, pero hoy...) y de hecho puede ser contraproducente. Por cuestiones de eficiencia, funciones como malloc y realloc pueden reservar más memoria que la que les pides. Puede ser, por ejemplo, en bloques múltiplos de cierto número. El caso es que, sobre todo sabiendo que estás reservando sólo unos pocos bytes, es probable que realloc considere más eficiente dejar que se "desperdicien" unos pocos bytes, y decida no tocar esa memoria, con lo cual, sólo estarías complicando más tu código, llamando a una función innecesariamente, y sin ahorrarte un sólo byte. Las optimizaciones hay que hacerlas cuando realmente tengamos la necesidad, hayamos identificado un problema, y hayamos sopesado pros y contras. Hacerlas por hacerlas suele traer problemas y muy poco (normalmente ningún) beneficio.
|
|
|
234
|
Programación / Programación C/C++ / Re: Representación visual de punteros y punteros a punteros..
|
en: 2 Mayo 2019, 19:42 pm
|
No quedaría de ninguna forma, porque tu código ni siquiera compilaría. Sería más bien: int **matriz = new int*[10]; for(int i = 0; i < 10; i++) matriz[i] = new int[10];
Lo que tendrías es: el puntero matriz en la pila, apuntando al inicio de un bloque (localizado en el heap) de 10 punteros, cada uno de los cuales apuntaría al inicio de un bloque de 10 enteros, ubicados también en el heap.
|
|
|
235
|
Programación / Programación C/C++ / Re: Duda sobre una parte del libro de k&r
|
en: 1 Mayo 2019, 20:31 pm
|
No tendría sentido decir que getch y ungetch no pueden verlas. O es un error grave del traductor, o lo estás malinterpretando. Dado que apenas empiezas, es normal que mucho de esto te sea confuso. La palabra static en C (y C++) es un asunto medio complicado. Por ejemplo, tiene distinto significado según dónde se use. Esto no es una exageración, literalmente, quienes crearon las reglas del lenguaje decidieron reutilizar la palabra static para no aumentar "innecesariamente" el número de palabras reservadas. Eso ha sido motivo de debate prácticamente desde el principio, con muchos programadores considerando que las reglas fueron un error, que se debió haber recurrido a diferentes palabras reservadas para los distintos usos, etc. pero pues esto es lo que hay. Te doy una explicación muy breve, limitándome a lo relevante para este ejemplo. Ten en cuenta que el asunto es mucho más complejo que la simplificación que estoy haciendo, pero tratar de ser más completo y riguroso resultaría en un texto muy largo y no tiene caso complicar más esto (igual si no lo entiendes del todo, lo puedes guardar como referencia para cuando ya sepas más). Los dos usos de static que son relevantes ahora son en referencia a la duración de una variable, y a su "visibilidad" (realmente en inglés se le llama linkage). La duración se refiere a durante cuánto tiempo "existe" una variable. Las variables locales (no static) tienen duración automática, es decir, sólo existen dentro del bloque (por ejemplo, función) donde fueron definidos. Las variables globales tienen duración estática: existen durante toda la ejecución del programa. En cuanto a la visibilidad, por defecto, las variables globales tienen visibilidad externa: pueden ser accedidas desde otros archivos fuente. Lo único que se necesita es que desde esos otros archivos el programador indique al compilador que va a usar estas variables. La forma correcta es, desde esos otros archivos, declararlas como extern. Por ejemplo, siguiendo el ejemplo de getch.c, si yo incluyera ese archivo en un proyecto mío, y agregara otro archivo (digamos, externo.c) y pusiera esta declaración: Esto le avisa al compilador que voy a usar una variable entera llamada bufp, que está definida en algún otro lado (en este caso, en getch.c). Fíjate que el hecho de que yo haya puesto la palabra extern indica que yo sé que esa variable está definida en otro archivo, y que de forma intencionada quiero acceder a ella. Pero resulta que la palabra extern no es del todo indispensable. Si yo la omitiera, y simplemente la declarara así en mi archivo: Creyendo que estoy definiendo una variable únicamente para uso mío, estaría equivocado. En realidad estaría compartiendo la misma variable que getch, justo como si la hubiera declarado como extern. Porque aunque no es lo más correcto, muchos compiladores permiten omitir el especificador extern (siempre que se cumplan ciertas condiciones). En este caso, mi programa compilaría perfectamente y sin errores, pero, de forma totalmente accidental e indeseada, estaría compartiendo una variable con el otro archivo  . Ojo, esto no funciona en todos los compiladores (y los compiladores de C++ son más estrictos), pero es muy probable que el compilador de C que uses lo permita sin marcar error. Al declarar una variable global como static, especificas que tiene visibilidad (o alcance) interna, y no se puede acceder desde fuera. Con eso evitas accesos, intencionales o no, desde el exterior. Muchos piensan que se debió usar una palabra reservada nueva (por ejemplo "intern") para este fin, ya que en realidad no estamos declarando la variable como estática; desde el momento en que es variable global, ya es estática, y nosotros simplemente estamos cambiando su visibilidad. La palabra static no tiene realmente sentido en este contexto, pero en fin...
|
|
|
236
|
Programación / Programación C/C++ / Re: Duda sobre una parte del libro de k&r
|
en: 1 Mayo 2019, 05:33 am
|
Kernighan y Ritchie llaman "external" a las variables globales. Para las variables declaradas como extern usan, precisamente, la palabra "extern". En español se tradujeron ambas como "externa(s)", y de ahí que pudiera haber confusión. Ahora, no sé si copiaste el código incorrecto, pero en mi libro sí aparecen las variables como static: static char buf[BUFSIZE]; /* buffer for ungetch */ static int bufp = 0; /* next free position in buf */
int getch(void) { ... } void ungetch(int c) { ... } En cuanto a tu duda: cuando declaras variables globales no static, de forma implícita tienen enlace externo, es decir, son accesibles ("visibles") fuera del archivo fuente en el que están declaradas (aunque no hayas usado la palabra extern). Esto quiere decir que si declaras variables globales no static con el mismo nombre en distintos archivos, en realidad se refieren a la misma variable. Cualquier modificación que hagas dentro de uno, afectará los otros. En esencia, estás compartiendo la variable a lo largo de más de un archivo. Al declararlas static, como pasa con buf y bufp, se "ocultan", es decir, sólo existen en el archivo en que se declararon. Cualquier otra variable global declarada en otro archivo de tu programa sería independiente de éstas.
|
|
|
238
|
Programación / Programación C/C++ / Re: como evitar el error de linker : Duplicated symbol for Architecture x86?
|
en: 28 Abril 2019, 20:58 pm
|
Se me pasó preguntarte si habías probado la forma más obvia: los clásicos include guards. Pones en tu .h: #ifndef NOMBRE_H #define NOMBRE_H
//Contenido de tu archivo...
#endif Esta es la forma estándar. Todas las demás son dependientes del compilador (aunque #pragma once es soportada por prácticamente todos). Esto no debería fallarte. Si siguiera sin funcionar, significaría que tu IDE está haciendo algo muy, muy mal.
|
|
|
240
|
Programación / Programación C/C++ / Re: Como puedo reproduccir 2 sonidos al mismo tiempo en DevC++
|
en: 24 Abril 2019, 22:24 pm
|
Con PlaySound no se puede. La forma más sencilla de hacerlo en Windows sin recurrir a bibliotecas como SDL y demás, es con MCI. La función a utilizar es mciSendString. Un ejemplo de su uso: mciSendString("open archivo.wav alias sonido1", NULL, 0, NULL); El parámetro importante es el primero, que es un comando con la acción a realizar. En este caso se abre el archivo y se le da un alias. A partir de aquí, mandas comandos como "play sonido1", "stop sonido1", etc.; para reproducir más sonidos, ábrelos asignándoles un alias distinto. Para más datos, googlea la función. Eso sí, igual que PlaySound, esto te puede servir para cosas sencillas, pero si necesitaras más control sobre la reproducción, menos latencia, etc. se necesitan métodos más complicados, o usar bibliotecas que lo faciliten.
|
|
|
|
|
|
|