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

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


  Mostrar Mensajes
Páginas: 1 [2] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ... 26
11  Programación / Programación C/C++ / Re: Ayuda recursividad en: 6 Agosto 2016, 21:34 pm
La idea de do-while es interesante, yo la adapté de la siguiente manera para crear un código más breve. La idea es empezar por el último carácter (no nulo) de la cadena y comparar con el siguiente. Si son diferentes, imprimir, sino, retroceder un carácter. En la función
Código
  1. void elimina_repetido2( char *start, char *c_ptr )
  2. {
  3.  
  4.    static char c = '\0';
  5.  
  6.    if ( c_ptr == start || *c_ptr == '\0' )
  7.        return;
  8.    else {
  9.        if ( *c_ptr != c ) printf( "%c", *c_ptr );
  10.        c = *c_ptr;
  11.        c_ptr--;
  12.        elimina_repetido2( start, c_ptr );
  13.    }
  14. }
  15.  
start es un apuntador al inicio de la cadena (para saber cuando detenernos al retroceder), c_ptr es un apuntador al carácter actualmente analizado (empezando por el último). La variable interna c funciona como auxiliar para almacenar el valor del carácter siguiente al apuntado por c_ptr.

Programa principal:
Código
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4.  
  5. int main(void) {
  6.  
  7.    char s1[100];
  8.  
  9.    cout << "Intro cadena: ";
  10.    cin >> s1;
  11.  
  12.    cout << endl << "Salida:";
  13.    elimina_repetido2( s1, s1 + strlen(s1) - 1 );
  14.    cout << endl;
  15.  
  16.    return 0;
  17. }

Salida en pantalla:

Intro cadena: aaabbbccdddeeee

Salida:edcba
12  Programación / Programación C/C++ / Re: Ayuda recursividad en: 6 Agosto 2016, 03:04 am
Supongo que la debo utilizar de esta manera, ¿no?
Código
  1. int main(void) {
  2.  
  3.    char s1[100];
  4.  
  5.    sprintf( s1, "aaaabbbcccddddee");
  6.  
  7.    funcion(s1);
  8.  
  9.    return 0;
  10. }
  11.  
13  Programación / Programación C/C++ / Re: Funcion importar de txt en: 6 Agosto 2016, 02:46 am
Hola kuni2006,

Bueno, hay algunos detalles para que pueda funcionar correctamente. Al parecer tratas de leer el fichero de texto y almacenar dichos datos en un fichero binario (tal vez para gestionar una sencilla Base o Estructura de Datos).

En cuanto a fscanf(), no se si has leído el tema pero esta función recibe como argumento APUNTADORES a las variables donde debe escribirse la infromación:
Código
  1. fscanf(file, "%u %s %s %[^\n]s", &persona.DNI, &persona.fnac, &persona.apellido, &persona.nombres)

y nota que hempos usando el "&" para definir un apuntador al registro persona. Otro detalle, si vas a trabajar con ficheros binarios no se puede escribir con fprintf() (lo cual sería para escritura con formato sobre ficheros de texto) sino con fwrite(), tal como te dijo Alberto. En este caso se requiere como auxiliar las funciones ftell(), fseek() por lo que deberías leer un poco el tema para terminar de comprender (o pregunta por aquí). Esto en caso que usemos "C crudo", pues en C++ hay algunas clases definidas para ello que quizá hagan la tarea menos ruda (aunque yo me llevo muy bien con C crudo).

Otro detalle sería que inmediatamente luego de abrir los ficheros, es bueno cerciorarse que la operación se realizó exitosamente (open() devuelve un puntero no nulo), y en caso contrario salir del programa:
Código
  1. if ( ( file = fopen("nombres.txt", "rt") ) == NULL ) {
  2.     printf( "Error al abrir fichero \"nombres.txt\"\n" );
  3.     return;
  4. }

En nuestro caso, diseñé el programa para que, con propósitos demostrativos, luego escribir en el fichero binario también lo podamos leer a fin de inspeccionar el resultado. Por eso le cambié el modo de apertura como lo tenías "wb" a "r+b".

Aquí el código fuente:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct persona {
  6. unsigned int DNI;
  7. char fnac[21];
  8. char apellido[51];
  9. char nombres[51];
  10. };
  11. typedef struct persona Persona;
  12.  
  13. void importar(char* nombreArchivo);
  14.  
  15. int main( ) {
  16.  
  17. char *nombreArchivo = "datos.dat";
  18.  
  19. importar( nombreArchivo );
  20.  
  21. return 0;
  22. }
  23.  
  24. void importar(char* nombreArchivo)
  25. {
  26.    Persona persona;
  27.    FILE* file;
  28.    FILE* file1;
  29. int count;
  30. int N_datos;
  31.  
  32. if ( ( file = fopen("nombres.txt", "rt") ) == NULL ) {
  33. printf( "Error al abrir fichero \"nombres.txt\"\n" );
  34. return;
  35. }
  36. if ( ( file1 = fopen(nombreArchivo, "r+b") ) == NULL ) {
  37. printf( "Error al abrir fichero \"nombres.txt\"\n" );
  38. return;
  39. }
  40.  
  41.    printf( "\nEscribiendo en fichero binario:\n" );
  42. count = 0;
  43.    while (EOF != fscanf(file, "%u %s %s %[^\n]s", &persona.DNI, &persona.fnac, &persona.apellido, &persona.nombres))
  44.    {
  45.        /* === Escribiendo en el fichero binario === */
  46.        fseek( file1, count * sizeof(Persona), SEEK_SET );
  47.        fwrite( &persona, sizeof(Persona), 1, file1 );
  48.        printf( "Dato %d:\n", count + 1 );
  49.     printf( "  DNI: %u\n", persona.DNI );
  50.     printf( "  DNI: %s\n", persona.fnac );
  51.     printf( "  DNI: %s\n", persona.apellido );
  52.     printf( "  DNI: %s\n", persona.nombres );
  53.     printf( "========================================\n" );
  54.  
  55.        count++; /* actualizar contador */
  56.    }
  57.    fclose( file ); /* cerrar fichero de texto */
  58.  
  59.    /* === Ahora verificando los datos === */
  60.    fseek( file1, 0, SEEK_END );
  61.    N_datos = (int) (ftell( file1 ) / sizeof(Persona));
  62.  
  63.    printf( "\nLeyendo del fichero binario:\n" );
  64. fseek( file1, 0, SEEK_SET ); /* posicionando al principio del fichero */
  65.    for ( count = 0; count < N_datos; count++ ) {
  66.        fread( &persona, sizeof(Persona), 1, file1 );
  67.     printf( "Dato %d:\n", count + 1 );
  68.     printf( "  DNI: %u\n", persona.DNI );
  69.     printf( "  DNI: %s\n", persona.fnac );
  70.     printf( "  DNI: %s\n", persona.apellido );
  71.     printf( "  DNI: %s\n", persona.nombres );
  72.     printf( "========================================\n" );
  73.    }
  74.  
  75.    fclose( file1 ); /* cerrar fichero binario */
  76. }

y suponiendo que en "nombres.txt" tengamos el siguiente contenido

12345 01/02/1980 Perez Jose Maria
85749 05/07/1978 Ramirez Ana Patricia
85711 21/07/1991 Fernandez Juan Manuel


el resultado sería:

Escribiendo en fichero binario:
Dato 1:
  DNI: 12345
  DNI: 01/02/1980
  DNI: Perez
  DNI: Jose Maria
========================================
Dato 2:
  DNI: 85749
  DNI: 05/07/1978
  DNI: Ramirez
  DNI: Ana Patricia
========================================
Dato 3:
  DNI: 85711
  DNI: 21/07/1991
  DNI: Fernandez
  DNI: Juan Manuel
========================================

Leyendo del fichero binario:
Dato 1:
  DNI: 12345
  DNI: 01/02/1980
  DNI: Perez
  DNI: Jose Maria
========================================
Dato 2:
  DNI: 85749
  DNI: 05/07/1978
  DNI: Ramirez
  DNI: Ana Patricia
========================================
Dato 3:
  DNI: 85711
  DNI: 21/07/1991
  DNI: Fernandez
  DNI: Juan Manuel
========================================


Un saludo, y cualquier cosa pregunta por aquí.
14  Programación / Programación C/C++ / Re: Ayuda recursividad en: 6 Agosto 2016, 00:27 am
Hola avesudra. Bueno, ya que piden resolverlo con recursividad, se me ocurre crear dos funciones, una para eliminar los caracteres repetidos, y otra para invertir la cadena.

Por ejemplo, sea la cadena "aaaabbbcccddddeee", entonces la idea es que cada vez que llamemos la función se elimina una repetición. La función compara el primer carácter de la cadena con el segundo, si son iguales elimina la repetición de este carácter y se vuelve a llamar a sí misma. Tras esto, compara el segundo con el tercero y así sucesivamente. Entonces tras la primera ejecución devuelve "abbbcccddddeee", tras la segunda devuelve "abcccddddeee", y así sucesivamente. La función se ha codificado de manera que imprima los resultados parciales y así se pueda ver cómo va trabajando.

En cuánto a la parte de invertir la cadena, lo que hacemos es intercambiar los caracteres opuestos con respecto al centro, desde afuera hacia adentro. Por ejemplo, dada la cadena "abcde", intercambiamos 1º y 5º, luego 2º y 4º y así sucesivamente. El proceso se detiene cuando la cantidad de reordenamientos supera la mitad de la longitud de la cadena.

Código
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <iostream>
  5.  
  6. using namespace std;
  7.  
  8. void elimina_repetido( char *s );
  9. int invertir_cadena( char *s );
  10.  
  11. int main(void) {
  12.  
  13. char s1[100];
  14.  
  15. sprintf( s1, "aaaabbbcccddddee");
  16.  
  17. cout << "Eliminando repetidos" << endl
  18. << "==============================" << endl;
  19. elimina_repetido ( s1 );
  20.  
  21. cout << "Invirtiendo cadena" << endl
  22. << "==============================" << endl;
  23. invertir_cadena( s1 );
  24.  
  25. return 0;
  26. }
  27.  
  28. /* Devuelve cero cuando se termine de analizar toda la
  29.  * cadena, y 1 si falta por analizar.
  30.  * La cadena transformada queda almacenada en el mismo
  31.  * argumento s.
  32.  * La función almacena la posición del último carácter leído
  33.  * (usando variables internas estáticas)
  34.  */
  35. void elimina_repetido( char* s )
  36. {
  37. static int pos = 0;
  38. int k; /* indice auxiliar */
  39. int count; /* cuantos caracteres repetidos */
  40. char c1;
  41.  
  42. c1 = s[pos];
  43. if ( c1 == '\0' ) return; /* terminó de analizar la cadena*/
  44.  
  45. k = pos + 1;
  46. if ( s[k] == c1 ) {
  47. while ( s[k] == c1 && s[k] != '\0' ) {
  48. k++;
  49. }
  50. count = k - ( pos + 1 ); /* cantidad de caracteres repetidos, después de c1 */
  51.  
  52. /* Ahora s[k] es el primer carácter posterior a s[pos] distinto
  53. * de c1. Vamos a mover hacia atrás los restantes caracteres,
  54. * un total de <count> posiciones
  55. */
  56. while ( s[k] != '\0' ) {
  57. s[k - count] = s[k];
  58. k++;
  59. }
  60. s[k - count] = '\0';
  61. }
  62.  
  63. /* mostrar la cadena */
  64. cout << "   " << s << endl;
  65.  
  66. /* preparar para el próximo llamado de la función */
  67. pos++;
  68. elimina_repetido( s );
  69. }
  70.  
  71. /* Reordena la cadena, intercambiando los caracteres en posiciones
  72.  * opuestas respecto al centro, desde afuera hacia adentro.
  73.  * El proceso termina cuando el número de reordenamientos
  74.  * supera la mitad de la longitud de la cadena.
  75.  */
  76. int invertir_cadena( char *s )
  77. {
  78. static int count = 0;
  79. int k, N;
  80. char c;
  81.  
  82. N = strlen(s);
  83. if ( count == N || N == 0 ) return 0;
  84.  
  85. /* intercambia las posiciones */
  86. c = s[count];
  87. s[count] = s[N - count - 1];
  88. s[N - count - 1] = c;
  89.  
  90. cout << "   " << s << endl;
  91.  
  92. count++;
  93. if  ( count < N / 2 ) invertir_cadena( s );
  94. }

Aquí podemos ver el resultado:

Eliminando repetidos
==============================
   abbbcccddddee
   abcccddddee
   abcddddee
   abcdee
   abcde
Invirtiendo cadena
==============================
   ebcda
   edcba


Un saludo, Yoel.
15  Programación / Programación C/C++ / Re: consulta sobre el uso del ampersand en variables de tipo string en: 19 Enero 2016, 14:25 pm
Porque cuando le pasas una cadena solamente, como el caso de pax, no le pasas la dirección.

Recuerda que en C las cadenas son arreglos de datos char, y como en todo arreglo en C, el nombre del arreglo es un apuntador al primer elemento del mismo. En otras palabras, el nombre de la cadena es realmente una variable tipo char* (puntero a char) que contiene la dirección de memoria del primer carácter de la misma.

Código
  1. char str[] = "Hola mundo";
  2.  
  3. printf( "contenido de str: %s\n", str );
  4. printf( "pero str es un puntero cuyo valor es: %p\n", str );
  5. printf( "y apunta al primer elemento el cual es --> '%c'\n", *str );

Salida:

    contenido de str: Hola mundo
    pero str es un puntero cuyo valor es: 0xbfcbe9b5
    y apunta al primer elemento el cual es --> 'H'


Saludos, Yoel.

16  Programación / Programación C/C++ / Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C] en: 19 Enero 2016, 14:05 pm
NOB2014, puedes aumentar la precisión cambiando en donde dice FLT_EPSILON por la constante DBL_EPSILON

En este caso cambias del épsilon de la máquina para punto flotante al épsilon para precisión doble. Creo que al manejar más de nueve decimales estás considerando una precisión doble, por eso requieres DBL_EPSILON

Saludos, Yoel
17  Programación / Programación C/C++ / Re: Interpretar o compilar desde txt en: 18 Enero 2016, 18:50 pm
Crea tu propio mini-intérprete, más o menos lo que te recomendó ivance.

Ahora, si el archivo contiene íntegramente código C válido, puedes programar un pequeño script de bath (Windows) o bash (Linux) con órdenes al sistema operativo, para que invoque el compilador de C sobre el fichero que tienes, genere el ejecutable, y lo ejecute.

Saludos, Yoel
Puedes enviarme un M.P.
18  Programación / Programación C/C++ / Re: Establecer la cantidad de dígitos a la derecha de la coma [lenguaje C] en: 18 Enero 2016, 18:39 pm
Bueno, .... está muy interesante el tema!

El problema parece ser que el redondeo a entero de un número teóricamente entero, no es necesariamente un "entero" desde el punto de vista de la máquina.
Entonces cuando multiplicamos por 10, nunca llegamos a obtener un "entero" desde el punto de vista de la máquina.

Probé a hacer lo siguiente, incluir la biblioteca <math.h>, y mandar a imprimir en cada ciclo la diferencia entre el número actual, y el redondeo del mismo. Lo imprimimos en notación científica para apreciar mejor el orden de magnitud del número
Código
  1. while( contador < 20 && fabs(numero - round(numero)) != 0 ) {
  2.        contador++;
  3. numero *= 10;
  4. printf("Numero es ...: %lf, van: %d decimales\n", numero, contador );
  5. printf("  Diferencia: %.2E\n", fabs(numero - round(numero)));
  6. }
  7.  
(donde la condición del contador menor a 20 es para prevenir ciclo infinito). El resultado será

 Ingrese un numero con decimales...: .2155
1.19E-07
Numero es ...: 2.155000, van: 1 decimales
  Diferencia: 1.55E-01
Numero es ...: 21.550000, van: 2 decimales
  Diferencia: 4.50E-01
Numero es ...: 215.500000, van: 3 decimales
  Diferencia: 5.00E-01
Numero es ...: 2155.000000, van: 4 decimales
  Diferencia: 4.55E-13
Numero es ...: 21550.000000, van: 5 decimales
  Diferencia: 3.64E-12
Numero es ...: 215500.000000, van: 6 decimales
  Diferencia: 2.91E-11
Numero es ...: 2155000.000000, van: 7 decimales
  Diferencia: 4.66E-10
Numero es ...: 21550000.000000, van: 8 decimales
  Diferencia: 3.73E-09
Numero es ...: 215500000.000000, van: 9 decimales
  Diferencia: 2.98E-08
Numero es ...: 2155000000.000000, van: 10 decimales
  Diferencia: 4.77E-07


Pero vemos que el algún momento la diferencia entre ambos es un número muy pequeño, teóricamente cero pero que en la práctica no es cero. Debe ser un número menor al épsilon de la máquina, el cual desde el punto de vista teórico debemos tomaralo como un cero. Por lo tanto detenemos el ciclo cuando la diferencia entre el número y su redondeo sea menor a dicho épsilon:
Código
  1. while( contador < 20 && fabs(numero - round(numero)) > FLT_EPSILON ) {
  2.    contador++;
  3.    numero *= 10;
  4.    printf("Numero es ...: %lf, van: %d decimales\n", numero, contador );
  5.    printf("  Diferencia: %.2E\n", fabs(numero - round(numero)));
  6. }
  7. }

Con lo cual se obtiene lo esperado

 Ingrese un numero con decimales...: .2155
1.19E-07
Numero es ...: 2.155000, van: 1 decimales
  Diferencia: 1.55E-01
Numero es ...: 21.550000, van: 2 decimales
  Diferencia: 4.50E-01
Numero es ...: 215.500000, van: 3 decimales
  Diferencia: 5.00E-01
Numero es ...: 2155.000000, van: 4 decimales
  Diferencia: 4.55E-13

 Total de digitos despues de la coma..:4


De todos modos, creo que lo más seguro en estos casos sigue siendo recibir el número como cadena, y convertirlo internamente a número según un algoritmo implementado directamente por nosotros. Creo que así debe ser la manera como trabajan los intérpretes de comandos como cmd, o bash

Un saludo, Yoel
Puedes enviarme un M.P.



Por cierto, respondiendo este post tuve que editar el mensaje como 10 veces, recortarlo, editarlo por partes, etc ....

El servicio anti-DOS me enviaba una alerta de "Attention Required", como que supuestamente estaba intentando invadir el foro con Scripting Injection. Lo cual es totalmente falso, entonces no se por qué el anti-DOS me rebotaba a cada rato. A lo mejor estaba malinterpretando como nocivas las etiquetas "code", o "tt"
19  Programación / Programación C/C++ / Re: Dudas de programa en C en: 18 Enero 2016, 18:27 pm
Disculpa Orb,

El mayor y el menor se inicializan al primer elemento del arreglo. Pues no puedes estar adivinando un número "inmensamente grande", o uno "inmensamente pequeño" (siempre habrá un número mayor o menor que otro). ¿Qué tal si el usuario pasa valores negativos?
Código
  1. mayor = datos[0];      /* <-- primer elemento */
  2. menor = datos[0];      /* <-- primer elemento */
  3. suma = 0;
  4. for(i=1 ; i <cantidad_datos ; i++){      /* inicias el ciclo con el segundo elemento, y de ahi en adelante */
  5.    if(datos[i] > mayor)
  6.        mayor = datos[i];
  7.    if(datos[i] < menos)
  8.        menos = datos[i];
  9.    suma = suma + datos[i];
  10. }
  11. promedio = suma / cantidad_datos;

y en este caso hemos reunido el cálculo de mayor, menor y suma en el mismo ciclo, de acuerdo a la sugerencia de fary
20  Programación / Programación C/C++ / Re: factorización de un número en: 18 Enero 2016, 17:23 pm
Bueno, al margen de que todas las respuestas anteriores están muy bien y el programa corre perfectamente, tengo una pequeña pregunta respecto al propósito del problema.

¿Se trata de todos los divisores (enteros) del número, o sólo de los divisores primos?

Por ejemplo, probando el programa para el número 24 daría 4 divisores, a saber:

2, 2, 2, 3

Estos divisores así calculados serán primos, pero en realidad son sólo dos divisores distintos: 2 y 3. Faltarían las combinaciones:

1, 2, 3, 4, 6, 12, 24

Entonces, divisores distintos son 7 (5 si se excluyen la unidad y el propio 24), y primos son sólo 2. ¿Qué es lo que se quiere?
Páginas: 1 [2] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ... 26
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines