elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 7 8 9 10 [11] 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
101  Sistemas Operativos / GNU/Linux / Re: Arrancar con gnome por defecto en lugar de kde en: 25 Marzo 2014, 19:18 pm
Gracias por la ayuda, intentaré la solución propuesta (con algo más de investigación personal) y cuento sobre el resultado.
102  Programación / Programación C/C++ / Re: C++ - Problema con implementación del QuickSort. en: 25 Marzo 2014, 19:15 pm
No me gusta hacer procesos asi recursivamente, cuesta mas tiempo y hay riesgo de que te estalle la pila.

Pero he de reconocer que recursivamente sale elegante.

Estoy de acuerdo, la recursividad está bien para practicar y llegar a comprenderla, pero leí en un libro de programación que su uso excesivo se desaconseja. Aunque sea una solución "bonita", es menos eficiente que un ciclo repetitivo tradicional porque (1) corre el riesgo de desbordar la pila, y (2) incurre en sobrecarga de tiempo por llamadas a función.

Cuando llamas a función debes:
  • colocar en la pila el estado actual de las variables del programa principal
  • colocar en la pila la dirección retorno de la función (la siguiente instrucción a ser ejecutada luego de regresar de la misma)
  • colocar en la pila los argumentos de llamada de la función
  • cambiar la dirección del apuntador de programa a la primera instrucción ejecutable de la función que es llamada (esto es propiamente, invocar la función)
  • ejecutar la función y al encontrar el return, colocar en la pila el valor de retorno de la misma
  • rescatar de la pila la dirección de retorno al programa principal
  • rescatar de la pila el estado de las variables del programa (no se bien si estos dos últimos pasos son así o al revés)

por eso es más costoso en tiempo de ejecución que un ciclo normal, lo que sería un problema solo en el caso de un excesivo número de repeticiones.

Es sólo un elemento más para tomar en cuenta, no es que yo esté prohibiendo el uso de la recursión, al final programador toma la decisión final de una manera ponderada.
103  Programación / Programación C/C++ / Re: Alinear texto (Solucionado) en: 25 Marzo 2014, 19:01 pm
Bueno, nolasco las soluciones que te dimos eran usando herramientas elementales. Claro que también se puede con los métodos más avanzados de manipulación de flujo E/S de C++.

Muy creativo tu método eferion, usar sprintf() para crear la cadena de formato que luego es pasada a printf(). Y por supuesto que no me molesta que hayas tomado mi idea, e incluso haberla mejorado  :D

Amigo leosansan, si me permites la opinión me parece bien tu código pero está como "críptico", me costó leerlo. Es como si tratara de meter varias cosas en una sola, y no se hasta que punto ese estilo puede resultar claro para un tercero. ¿Por qué no lo haces un poquito más "despejado"?
104  Sistemas Operativos / GNU/Linux / Re: Arrancar con gnome por defecto en lugar de kde en: 24 Marzo 2014, 21:00 pm
Tengo Ubuntu10 (y de ahí no me cambio), precisamente porque no me gustó ese unity/gnome3

Y no se si Ubuntu10 posee session manager. En todo caso, configurar el session manager tendrá el efecto de modificar archivos de sistema para que el cambio tenga efecto. Pa' eso entro como root y cambio el fichero yo mismo, ¿ven lo que trato de decir? Es que siempre me ha gustado más trabajar con mi consola que con IDE's e interfaces gráficas.

EL problema que me pasó fue que instalé ambos escritorios, pero como fue kde kuego que gnome, se me quedó kde por defecto. Entonces lo que hago es entrar como root, cerrar el proceso kdm y la sesión X, luego lanzar gdm:

pkill -SIGTERM -x kdm
pkill -SIGTERM -t tty7
gdm start &

Esta no es la solución óptima claro. Pero lo que pienso es que en el /etc/init.d debe haber algún script que lance al kdm por defecto al inicio. ¿Cuál rayos es?  :huh:

Ejecuto pstree, pero me sale del NetworkManager para adelante, no aparece cuándo "nació" el proceso kdm. Quizá debe ser algo con los scripts en los directorios /etc/rcX.d, he buscado en ellos manualmente pero sin poder encontrar nada ...

105  Programación / Programación C/C++ / Re: Problema con errorC2296 en C++ en: 24 Marzo 2014, 20:47 pm
Me perdí de un rato en el foro, pero bueno .....

Respecto a getchar() y system("PAUSE"), aunque operan similarmente, la primera es estándar y funcionará en cualquier sistema. La segunda, se puede garantizar siempre que estés en un sistema Windows.

Lo que ocurre es que system(str) pasa la cadena str al procesador de comandos del sistema operativo. Hacer system(str) es lo mismo que abrir el Símbolo de Sistema de Windows y escribir el contenido de la cadena str en él. Y como es de suponer, la cadena será interpretada en el contexto del sistema operativo de que se trate.

Por esta razón, recomendamos usar getchar() que tiene un comportamiento predecible. Lo que hace

c = getchar();

es esperar la pulsación de una tecla, seguida de ENTER (o de la secuencia EOF) y depositar el código ASCII de esta tecla en c. Si pulsas 'A' y luego ENTER asignará en c el valor 97 que es el código ASCII de la letra 'a'.
Si pulsas sólo ENTER entonces retornará al programa inmediatamente. Por eso la invocación de getchar() es para los programadores de C un equivalente a "Pulse ENTER para continuar", jejeje.

=====================================
De todas las soluciones publicadas creo que la mejor (más eficiente computacionalmente) sería la de leosansan porque no requiere siquiera calcular el módulo i%2. Yo la reduciría "un pelín" con:
Código
  1. int signo = -1;
  2.  
  3. for (i = 1;  i<= n; i++, signo *= -1)
  4.   pi = pi + signo * 1.0/(2*i+1);

y buena la observación del "1." en lugar de "1".
106  Programación / Programación C/C++ / Re: [DUDA] Punteros en: 24 Marzo 2014, 20:23 pm
Modestia aparte kayron  :-[. Luego que pases años programando como nosotros, lo harás igual jajaja  :D
107  Programación / Programación C/C++ / Re: Proyecto calculadora: Convertir infijo a posfijo. en: 24 Marzo 2014, 19:40 pm
Bueno, revisé la función ConvertirNumero(), pero veo que usa objetos complejos como listas. Sin embargo me parece excelente la filosofía usada para reconocer la sintaxis de la cadena, y obtener el número representado. Así que me tomé la libertad de redactarla en un código algo más elemental.

Lo que hago es no formar un conjunto con los dígitos que conforman la parte entera y la parte fraccionaria, sino reconocer los índices inicial y de dichos elementos en la cadena original. Luego voy tomando los dígitos y multiplicándolos por una potencia de 10. Adicionalmente, reemplazar el pow() por una variable base que en cada ciclo se multiplica por 10. Esa era la idea original de la función, creo que se mantiene igual pero ahora compila más rápido porque no necesita enlazar con bibliotecas de clases, jeje.
Código
  1. double str_to_dbl( const char *s, int *index_ptr ) {
  2.  
  3.   char c;
  4.   int i;
  5.   int int_start, int_end; /* indices de inicio y fin de parte entera */
  6.   int frac_start,frac_end; /* indices de inicio y fin de parte fraccionaria */
  7.   char sign = 0; /* flag de signo, 1 para negativo */
  8.   double number, base;
  9.  
  10.   /* descartamos espacios en blanco iniciales */
  11.   i = 0;
  12.   while ( s[i] == ' ' )
  13.      i++;
  14.  
  15.   /* reconocemos el carácter de signo (opcional) */
  16.   if ( ( c = s[i] ) == '+' || c == '-' ) {
  17.      if ( c == '-' ) sign = 1;
  18.      i++;
  19.   }
  20.  
  21.   /* reconocemos la parte entera, si la hay */
  22.   int_start = -1;
  23.   while ( ( c = s[i] ) >= '0' && c <= '9' ) {
  24.      if ( int_start == -1 ) int_start = i;
  25.      i++;
  26.   }
  27.   if ( int_start != -1 )
  28.      int_end = i - 1;
  29.  
  30.   /* caracter de punto decimal */
  31.   if ( s[i] == '.' ) {
  32.  
  33.      i++;
  34.      /* reconocemos la parte decimal, si la hay */
  35.      frac_start = -1;
  36.      while ( ( c = s[i] ) >= '0' && c <= '9' ) {
  37.         if ( frac_start == -1 ) frac_start = i;
  38.         i++;
  39.      }
  40.      if ( frac_start != -1 )
  41.         frac_end = i - 1;
  42.   }
  43.  
  44.   /* calcular el número */
  45.   number = 0;
  46.   if ( int_start != -1 ) {
  47.      base = 1;
  48.      while ( int_end >= int_start ) {
  49.         number += (s[int_end] - '0') * base;
  50.         int_end--;
  51.         base *= 10;
  52.      }
  53.   }
  54.   if ( frac_start != -1 ) {
  55.      base = 10;
  56.      while ( frac_start <= frac_end ) {
  57.         number += (s[frac_start] - '0') / base;
  58.         frac_start++;
  59.         base *= 10;
  60.      }
  61.   }
  62.   if ( sign ) number *= -1;
  63.  
  64.   if ( int_start != -1 || frac_start != -1 )
  65.      *index_ptr = i;
  66.   else
  67.      *index_ptr = -1;
  68.  
  69.   return number;
  70. }

Un pequeño detalle en la función ConvertirNumero es que arrojaba error si el número carecía de parte entera, e.g. -.35. Esto se corrige disponiendo que tanto la parte entera como la decimal sean opcionales, pero deba estar presente una de las dos:
Código
  1. if ( int_start != -1 || frac_start != -1 )
  2.   /* ... */

¿Pero sabes qué? Desempolvando los papeles veo que la función de biblioteca strtod(const char *s, char **endptr) ya nos hace este trabajo, y además actualiza endptr al primer caracter de la cadena no reconocible como parte de un número, y si coincide con el primero de la cadena significa que no se pudo reconocer ningún número. Es de biblioteca, es estándar y sobre todo, ya está hecha, jajaja.

Sin embargo, habría una razón para que nuestras funciones pudieran preferibles a strtod(): que podrían avisar sobre error de sintaxis. Pero para que las mismas puedan competir contra la función de biblioteca les hace falta que reconozcan números en formato de notación exponencial o científica.
108  Programación / Programación C/C++ / Re: problema con archivo de texto en: 24 Marzo 2014, 18:45 pm
Estoy viendo que el fichero de entrada tiene:

Et12_xyz123     ADCA      1,PC
%ET3        LDAA      #$90
Netq%23        RMB      556
etv1
XYZ        Ldaaxyz   4
        %XYZ
        a.c.      %1111000
Abc        SWI%

y sólo en la primera línea empieza con "Et" (por cierto, 'E' en mayúsculas, 't' en minúsculas, ¿no tendrá eso que ver?). Lo que pregunto es si sólo las líneas que comiencen con la frase clave "ET", o "Et" se descomponen en ETIQUETA, CODOP y OPERANDO.
109  Programación / Programación C/C++ / Re: [DUDA] Punteros en: 24 Marzo 2014, 18:19 pm
Kayron,

Para explicarte un poco las cosas, un arreglo es un puntero. O sea, cuando declaras:

int x[3];

entonces "x" no es más que un apuntador al primer elemento del arreglo. Entonces será lo mismo:

*x que x[0]
*(x+1) que x[1]
*(x+2) que x[2]

En *(x+1) entre los paréntesis se realiza aritmética de punteros para incrementar en 1 en valor del puntero (la dirección física del dato). O sea, que x+1 contiene la dirección del dato x[1]. Ojo, la dirección no el dato en sí mismo. Para acceder el valor contenido en dicha dirección debemos usar el operador de indirección "*". Por eso, *(x+1)

Espero lo hayas podido entender clarito, jeje. Ahora, te cuento que hay gente que escribe &x[0] que es redundante, es lo mismo que x; del mismo modo &x[1] es lo mismo que x+1.

En tu programa si quieres usar exclusivamente puntero y no indexación de arreglos, debes disponer de un apuntador a char para recorrer los caracteres de la frase. Ese creo que lo llamaste fp. Su valor inicial es frase, de este modo queda apuntado al primer elemento del arreglo. Luego, las expresiones

frase

se han de cambiar por *fp y en cada ciclo el valor del puntero es incrementado con fp++ para que direccione a la siguiente letra de la frase.

Para el caso de las vocales, el mismo arreglo vocales sirve como puntero (!!!).
La expresión

vocales[ i ]++

se cambia por (*(vocales + i))++ con cada valor de i desde 0 hasta 4. Los dobles paréntesis son necesarios porque el operador de incremento "++" tiene igual precedencia que el de indirección "*", pero se evalúa de derecha a izquierda. De colocar:

*(vocales + i)++

se hubiera interpretado *((vocales + i)++) que no es lo que queremos.

El código:
Código
  1. void cuentavocales(char frase[])
  2. {
  3.   int vocales[5] = {0};
  4.   char * fp;
  5.  
  6.   printf("Introduce una frase: \n");
  7.   gets(frase);
  8.  
  9.   /* La idea es que fp recorra el arreglo frase. Se inicializa al primer
  10.     * ELEMENTO (no el primer INDICE) del arreglo. */
  11.   fp = frase;
  12.  
  13.   while ( *fp != '\0' )
  14.   {
  15.      if (*fp=='a'|| *fp=='A') (*vocales)++;
  16.      else if (*fp=='e' || *fp=='E') (*(vocales + 1))++;
  17.      else if (*fp=='i' || *fp=='I') (*(vocales + 2))++;
  18.      else if (*fp=='o' || *fp=='O') (*(vocales + 3))++;
  19.      else if (*fp=='u' || *fp=='U') (*(vocales + 4))++;
  20.  
  21.      fp++; /* aumentamos el puntero que recorre la frase */
  22.   }
  23.   //Mostramos los resultados por pantalla
  24.   printf("Estadística \n");
  25.   printf("as: %d \n", *vocales);
  26.   printf("es: %d \n", *(vocales + 1));
  27.   printf("is: %d \n", *(vocales + 2));
  28.   printf("os: %d \n", *(vocales + 3));
  29.   printf("us: %d \n", *(vocales + 4));
  30.   printf("\n TOTAL: %d\n", *vocales + *(vocales + 1) + *(vocales + 2)
  31.          + *(vocales + 3) + *(vocales + 4) );
  32. }
  33.  

Ahora no usas índices en ninguna parte, sólo punteros. Por cierto, lo probé y funciona correctamente.

================================
EDITO:

Estaba revisando tu código y la verdad es que le faltaba poco para funcionar. Por ejemplo, para incrementar el conteo de la vocal 'e' reemplaza

pv=pv+1;
pv++;

por

*(pv + 1) = *(pv + 1) + 1;

lo cual es completamente equivalente a

pv[1] = pv[1] + 1;

También puedes sintetizarlo a:

(*(pv+1))++;


Quedaría entonces:
Código
  1. void cuentavocales2(char frase[5])
  2. {
  3.   int i=0,vocales[5]= {0};
  4.   int * pv;
  5.   pv = vocales;
  6.  
  7.   printf("Introduce una frase: \n");
  8.   gets(frase);
  9.   for(i=0; i<strlen(frase); i++)
  10.   {
  11.      if(frase[i]=='a'|| frase[i]=='A')
  12.         (*pv)++;
  13.      else if(frase[i]=='e' || frase[i]=='E')
  14.         (*(pv+1))++;
  15.      else if(frase[i]=='i' || frase[i]=='I')
  16.         (*(pv+2))++;
  17.      else if(frase[i]=='o' || frase[i]=='O')
  18.         (*(pv+3))++;
  19.      else if(frase[i]=='u' || frase[i]=='U')
  20.         (*(pv+4))++;
  21.   }
  22.  
  23. //Mostramos los resultados por pantalla
  24.   printf("Estadística \n");
  25.   printf("as: %d \n",*pv);
  26.   printf("es: %d \n",*(pv+1));
  27.   printf("is: %d \n",*(pv+2));
  28.   printf("os: %d \n",*(pv+3));
  29.   printf("us: %d \n",*(pv+4));
  30.   printf("\n TOTAL: %d\n",*pv+*(pv+1)+*(pv+2)+*(pv+3)+*(pv+4));
  31. }
  32.  

Tu código anterior estaba malo porque con

pv = pv + 1;
pv++;

estás incrementando los valores del puntero, o sea las DIRECCIONES de los datos, y no los datos en sí mismos. Tal vez con

pv = pv + 1;
(*pv)++;

donde modificas pv para que apunte a la posición de la vocal 'e', y luego incrementas el valor en el arreglo. El problema es que ya el valor del puntero te queda alterado, no apunta a vocales[0] sino a vocales[1]. Tendría que ser en todo caso

pv = pv + 1;
(*pv)++;
pv = pv - 1;

donde "acomodas" de nuevo el valor del puntero. Pero eso es completamente equivalente a

*(pv + 1) = *(pv + 1) + 1;

 :)
110  Programación / Programación C/C++ / Re: Alinear texto en: 24 Marzo 2014, 17:47 pm
Bueno, hace falta indicar que tipo de justificación quieres para los datos dentro de la columna, si a la izquierda, al centro o a la derecha. Yo voy a suponer que a la izquierda, por ser lo más usual. La solución que voy a proponer la he usado varias veces en mis programas, y no usa nada sofisticado, de hecho se puede compilar en C.

La idea es calcular el mayor ancho entre todos los campos de cada columna, e ir depositando el resultado en un arreglo ColumnsWidth[] de "anchos de columna". Luego, al imprimir los campos, pones al final los espacios en blanco necesarios para completar el ancho establecido para esa columna. Supuse también dos espacios adicionales entre columnas, sino aparece todo pegado.
Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. /* Imprimir una tabla alineada en columnas, con justificación a la izquierda
  6.  * By Yoel, xD */
  7. int main() {
  8.  
  9.   int i, j;
  10.   int ColumnsWidth[4];
  11.   size_t width;
  12.  
  13.   /* Contenido de la tabla, pones luego el código que la genera */
  14.   char *tabla[2][4] = {{"Hacker", "Perro", "Labrador", "Macho"},
  15.      {"Fugi", "Camaleon", "Silvestre", "Hembra"}
  16.   };
  17.   char *titulos[4] = {"Nombre", "Animal", "Raza", "Sexo"};
  18.  
  19.   for ( j = 0; j < 4; j++ ) {
  20.      ColumnsWidth[j] = 0;
  21.      /* calcula el mayor ancho entre todos los campos de la columna j */
  22.      if ( ( width = strlen(titulos[j]) ) > ColumnsWidth[j] )
  23.         ColumnsWidth[j] = width;
  24.      for ( i = 0; i < 2; i++ )
  25.         if ( ( width = strlen(tabla[i][j]) ) > ColumnsWidth[j] )
  26.            ColumnsWidth[j] = width;
  27.      /* dos espacios adicionales */
  28.      ColumnsWidth[j] += 2;
  29.   }
  30.  
  31.   /* Ahora luego de imprimir cada palabra, colocas espacios en blanco hasta completar
  32.     * el ancho que debe tener la columna, más dos espacios adicionales */
  33.   for ( j = 0; j < 4; j++ ) {
  34.      width = strlen( titulos[j] );
  35.      printf( "%s", titulos[j] );
  36.      while ( width++ < ColumnsWidth[j] ) putchar(' ');
  37.   }
  38.   printf( "\n\n" );
  39.   for ( i = 0; i < 2; i++ ) {
  40.      for ( j = 0; j < 4; j++ ) {
  41.         width = strlen( tabla[i][j] );
  42.         printf( "%s", tabla[i][j] );
  43.         while ( width++ < ColumnsWidth[j] ) putchar(' ');
  44.      }
  45.      printf( "\n" );
  46.   }
  47.  
  48.   return 0;
  49. }

Salida:
Código:
Nombre  Animal    Raza       Sexo    

Hacker  Perro     Labrador   Macho   
Fugi    Camaleon  Silvestre  Hembra

¿Era lo que querías? Si vas a compilar en C++, cambia <stdlib.h>, <stdio.h>, <string.h> por <cstlib>, <cstdio>, <iostream>, y los respectivos printf() por instrucciones de flujo cout.
Páginas: 1 2 3 4 5 6 7 8 9 10 [11] 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines