Autor
|
Tema: Perdido y desesperado con este código (Leído 3,357 veces)
|
pacosn1111
Desconectado
Mensajes: 59
|
Hola de nuevo, como sabeis estoy escribiendo un motor de cifrado en C, pero no hay forma de hacerlo funcionar correctamente, os dejo el código: #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <math.h> // variables globales double claves[27][1000]; int clave[27]; // arrays globales char letras[]="abcdefghijklmnopqrstuvwxyz "; char cifrado[999999999]; char descifrado[999999999]; // prototipos de funciones void generar_clave(int); void ingresar_clave(int []); int comprobar_repetir_vector(int, int []); int comprobar_repetir_matriz(double, double [][1000]); void arrancar_motor(int, int); int suma(double); double aleatorio(int, int); void cifrar(int, int, char []); void descifrar(int, char []); int main() { generar_clave(15); arrancar_motor(15, 1); } // comprueba si un numero esta repetido en una matriz, si esta repetido devuelve 1, en caso contrario 0. int comprobar_repetir_matriz(double numero, double matriz[][1000]) { int x; int y; for(x=0; x<27; x++) { for(y=0;y<1000;y++) { if (numero==matriz[x][y]) { return 1; } } } return 0; } // comprueba si un numero esta repetido en un vector, si esta repetido devuelve 1, en caso contrario 0. int comprobar_repetir_vector(int numero, int vector[]){ int x; for(x=0; x<27;x++) { if(numero==vector[x]) { return 1; } } return 0; } // Devuelve la suma de las cifras de un numero int suma(double numero) { int resultado=0; while (numero>0) { resultado+=fmod(numero, 10); numero/=10; } return resultado; } //Genera un numero aleatorio sin decimales dentro de un rango entre max y min. double aleatorio(int max, int min) { return rand() % max + min ; } //Genera una clave optimidada y la guarda en la variable global clave. void generar_clave(int numero_suma) { int maximo, minimo, x, y, num_random; int max=120; int min=60; maximo=numero_suma*max/20; minimo=numero_suma*min/20; for(x=0;x<27;) { num_random=aleatorio(maximo, minimo); if (comprobar_repetir_vector(num_random, &clave[0])==1) { continue; } clave[x]=num_random; x++; } printf("se ha generado la clave: \n"); for(y=0;y<27;y++) { } } // Permite ingresar el valor de cualquier array en la variable global clave. void ingresar_clave(int array[]) { int x; for(x=0;x<27;x++) { clave[x]=array[x]; } } // Genera los numeros aleatorios correspondientes a cada letra y los guarda según corresponda en la matriz claves. void arrancar_motor(int numero_cifras, int cantidad_numeros){ int y, z, h; double num_random; double min =(double)pow(10, numero_cifras -1); double max =(double)pow(10, numero_cifras )-1; for(z=0; z<27; z++) { printf("Inicializando letra %c\n", letras [z ]); for(h=0; h<cantidad_numeros;) { num_random=aleatorio(max, min); if ((suma(num_random)==clave[z]) && (comprobar_repetir_matriz(num_random, claves))==0) { claves[z][h]=num_random; printf("%.0lf\n", num_random ); h++; } else { continue; } } } printf("se ha generado la clave: \n"); for(y=0;y<27;y++) { } printf("\ncon un numero de cifras de %d\n", numero_cifras ); } // Cifra un texto usando la clave almancenada en la variable global clave, el resultado lo guarda en la variable global cifrado. void cifrar(int numero_cifras, int cantidad_numeros, char texto[]) { int letra, letrass, x; char cifrado_inside [strlen(texto )*numero_cifras ]; char string_auxiliar[numero_cifras-1]; for(letra =0; strlen(texto )>letra ; letra ++) { for(letrass=0; letrass<27; letrass++) { if (texto[letra]==letras[letrass]) { sprintf(string_auxiliar , "%.0lf", claves [letrass ][(int)(aleatorio (cantidad_numeros -1, 0))]); strcat(cifrado_inside , string_auxiliar ); break; } } } strcpy(cifrado , cifrado_inside ); } // Descifra un texto cifrado anteriormente usando la clave almancenada en la variable global clave, el resultado lo guarda en la variable global descifrado. void descifrar(int numero_cifras, char cifrado[]) { char auxiliar[numero_cifras]; int x, y=0, z; for(x=0; x<strlen(cifrado); x++) { auxiliar[y]=cifrado[x]; y++; if(y==numero_cifras) { for(z=0; z<27; z++) { if(suma (atof(auxiliar ))==clave [z ]) { descifrado [strlen(descifrado )]=letras [z ]; y=0; break; } } } } }
La funcion aleatorio devuelve un numero aleatorio dentro de un rango, la función generar_clave genera una clave optimizada y la función arrancar_motor genera x numeros de x cifras cuyas cifras sumen x numero y lo guarda en un array para posteriormente cifrar o descifrar con esos numeros, pero se me ha atascado la funcion arrancar_motor, no funciona lo rapido que esperaba, ahora hasta se queda en "inicializando letra a" y de ahí no sale. Gracias de antemano. Saludos.
|
|
« Última modificación: 22 Abril 2015, 16:44 pm por pacosn1111 »
|
En línea
|
|
|
|
eferion
Desconectado
Mensajes: 1.248
|
1. Variables no inicializadasif (comprobar_repetir_vector(num_random, clave)==1)
int comprobar_repetir_vector(int numero, int *vector ) { int x; for(x=0; x<27;x++) { if(numero==vector[x]) return 1; } return 0; }
Si te das cuenta, no estás dando a "clave" unos valores iniciales... simplemente le asignas un valor y después verificas que dicho valor no esté repetido. ¿Problemas? Varios: - "clave" tendrá inicialmente valores aleatorios. Si uno de estos valores coincide con el que intentas ingresar el algoritmo dará este nuevo valor como no válido.
- No tiene sentido que para cada valor que intentas añadir a "clave" compruebes sus 27 posiciones... lo suyo sería comprobar desde 0 hasta N-1, siendo N el índice del número actual. De esta forma únicamente comparas el número actual con los ya insertados en el arreglo. Corrigiendo este punto podrías olvidarte del problema del punto anterior
- No es buena idea tener el "27" a pelo en el código. ¿Qué sucede si luego tienes que crear una clave de 40 elementos? Te toca editar ese número en varias partes del código... es bastante recomendable tener estos valores en un #define para evitar errores
2. Cuidado con los decimalesCuando trabajes con números decimales (float, double, ... ) tienes que tener muy en cuenta que NUNCA debes hacer una comparación directa, tipo "if( float == float )". ¿Por qué? Bueno, pues porque un número en coma flotante nunca va a ser 100% preciso. Los números en coma flotante tienen una serie de dígitos significativos, mientras que el resto pueden ser considerados "basura". Si tu fuerzas a una comparación exacta, esa basura va a hacer que la comparación sea bastante inestable. La forma de comparar si un número decimal es igual a otro pasa por asumir que dos números son iguales si el resto entre ellos es menor a X. Ejemplo: int main( ) { // Un float nunca es preciso 100%. // Esta inicialización intenta reflejar esta situación float a = 5.0001, b; for( b=1.0; b < 10.0; b+=1.0 ) { if( a == b ) { printf( "Bucle 1 OK!!!\n" ); break; } } for( b=1.0; b < 10.0; b+=1.0 ) { if( fabs( a - b ) < 0.001 ) { printf( "Bucle 2 OK!!!\n" ); break; } } }
¿Dónde realizas este tipo de comprobaciones? Por ejemplo en la función "suma", que se llama desde "arrancar_motor"... esa es, al menos, una de las razones por las que el código "tarda mucho". Un saludo
|
|
|
En línea
|
|
|
|
pacosn1111
Desconectado
Mensajes: 59
|
1. Variables no inicializadasif (comprobar_repetir_vector(num_random, clave)==1)
int comprobar_repetir_vector(int numero, int *vector ) { int x; for(x=0; x<27;x++) { if(numero==vector[x]) return 1; } return 0; }
Si te das cuenta, no estás dando a "clave" unos valores iniciales... simplemente le asignas un valor y después verificas que dicho valor no esté repetido. ¿Problemas? Varios: - "clave" tendrá inicialmente valores aleatorios. Si uno de estos valores coincide con el que intentas ingresar el algoritmo dará este nuevo valor como no válido.
- No tiene sentido que para cada valor que intentas añadir a "clave" compruebes sus 27 posiciones... lo suyo sería comprobar desde 0 hasta N-1, siendo N el índice del número actual. De esta forma únicamente comparas el número actual con los ya insertados en el arreglo. Corrigiendo este punto podrías olvidarte del problema del punto anterior
- No es buena idea tener el "27" a pelo en el código. ¿Qué sucede si luego tienes que crear una clave de 40 elementos? Te toca editar ese número en varias partes del código... es bastante recomendable tener estos valores en un #define para evitar errores
2. Cuidado con los decimalesCuando trabajes con números decimales (float, double, ... ) tienes que tener muy en cuenta que NUNCA debes hacer una comparación directa, tipo "if( float == float )". ¿Por qué? Bueno, pues porque un número en coma flotante nunca va a ser 100% preciso. Los números en coma flotante tienen una serie de dígitos significativos, mientras que el resto pueden ser considerados "basura". Si tu fuerzas a una comparación exacta, esa basura va a hacer que la comparación sea bastante inestable. La forma de comparar si un número decimal es igual a otro pasa por asumir que dos números son iguales si el resto entre ellos es menor a X. Ejemplo: int main( ) { // Un float nunca es preciso 100%. // Esta inicialización intenta reflejar esta situación float a = 5.0001, b; for( b=1.0; b < 10.0; b+=1.0 ) { if( a == b ) { printf( "Bucle 1 OK!!!\n" ); break; } } for( b=1.0; b < 10.0; b+=1.0 ) { if( fabs( a - b ) < 0.001 ) { printf( "Bucle 2 OK!!!\n" ); break; } } }
¿Dónde realizas este tipo de comprobaciones? Por ejemplo en la función "suma", que se llama desde "arrancar_motor"... esa es, a l menos, una de las razones por las que el có digo "tarda mucho". Un saludo Gracias, muy buena explicación, en cuanto llegue a casa (estoy en el trabajo) lo implemento y os cuento que tal va. Saludos.
|
|
|
En línea
|
|
|
|
pacosn1111
Desconectado
Mensajes: 59
|
Hola otra vez, he corregido los fallos que me has comentado y los he corregido, os dejo el código corregido: #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <math.h> // constantes #define numero_de_letras 27 // variables globales double claves[numero_de_letras][1000]; int clave[numero_de_letras]; // arrays globales char letras[]="abcdefghijklmnopqrstuvwxyz "; char cifrado[999999999]; char descifrado[999999999]; // prototipos de funciones void generar_clave(int); void ingresar_clave(int []); int comprobar_repetir_vector(int, int, int []); int comprobar_repetir_matriz(int, double, double [][1000]); void arrancar_motor(int, int); int suma(double); double aleatorio(int, int); void cifrar(int, int, char []); void descifrar(int, char []); int main() { generar_clave(15); arrancar_motor(15, 1); } // comprueba si un numero esta repetido en una matriz, si esta repetido devuelve 1, en caso contrario 0. int comprobar_repetir_matriz(int n, double numero, double matriz[][1000]) { int x; int y; for(x=0; x<n-1; x++) { for(y=0;y<1000;y++) { if (numero==matriz[x][y]) { return 1; } } } return 0; } // comprueba si un numero esta repetido en un vector, si esta repetido devuelve 1, en caso contrario 0. int comprobar_repetir_vector(int n, int numero, int vector[]){ int x; for(x=0; x<n-1;x++) { if(numero==vector[x]) { return 1; } } return 0; } // Devuelve la suma de las cifras de un numero int suma(double numero) { int resultado=0; while (numero>0) { resultado+=fmod(numero, 10); numero/=10; } return resultado; } //Genera un numero aleatorio sin decimales dentro de un rango entre max y min. double aleatorio(int max, int min) { return rand () % (max -min +1) + min ; } //Genera una clave optimidada y la guarda en la variable global clave. void generar_clave(int numero_suma) { int maximo, minimo, x, y, num_random; int max=120; int min=60; maximo=numero_suma*max/20; minimo=numero_suma*min/20; for(x=0;x<numero_de_letras;) { num_random=aleatorio(maximo, minimo); if (comprobar_repetir_vector(x, num_random, &clave[0])==1) { continue; } clave[x]=num_random; x++; } printf("se ha generado la clave: \n"); for(y=0;y<numero_de_letras;y++) { } } // Permite ingresar el valor de cualquier array en la variable global clave. void ingresar_clave(int array[]) { int x; for(x=0;x<numero_de_letras;x++) { clave[x]=array[x]; } } // Genera los numeros aleatorios correspondientes a cada letra y los guarda según corresponda en la matriz claves. void arrancar_motor(int numero_cifras, int cantidad_numeros){ int y, z, h; double num_random; double min =(double)pow(10.0, numero_cifras -1); double max =(double)pow(10.0, numero_cifras )-1; for(z=0; z<numero_de_letras; z++) { printf("Inicializando letra %c\n", letras [z ]); for(h=0; h<cantidad_numeros;) { num_random=aleatorio(max, min); if (((fabs(suma (num_random )-clave [z ])) < 0.001) && (comprobar_repetir_matriz (z , num_random , claves ))==0) { claves[z][h]=num_random; printf("%.0lf\n", num_random ); h++; } else { continue; } } } printf("se ha generado la clave: \n"); for(y=0;y<numero_de_letras;y++) { } printf("\ncon un numero de cifras de %d\n", numero_cifras ); } // Cifra un texto usando la clave almancenada en la variable global clave, el resultado lo guarda en la variable global cifrado. void cifrar(int numero_cifras, int cantidad_numeros, char texto[]) { int letra, letrass, x; char cifrado_inside [strlen(texto )*numero_cifras ]; char string_auxiliar[numero_cifras-1]; for(letra =0; strlen(texto )>letra ; letra ++) { for(letrass=0; letrass<numero_de_letras; letrass++) { if (texto[letra]==letras[letrass]) { sprintf(string_auxiliar , "%.0lf", claves [letrass ][(int)(aleatorio (cantidad_numeros -1, 0))]); strcat(cifrado_inside , string_auxiliar ); break; } } } strcpy(cifrado , cifrado_inside ); } // Descifra un texto cifrado anteriormente usando la clave almancenada en la variable global clave, el resultado lo guarda en la variable global descifrado. void descifrar(int numero_cifras, char cifrado[]) { char auxiliar[numero_cifras]; int x, y=0, z; for(x=0; x<strlen(cifrado); x++) { auxiliar[y]=cifrado[x]; y++; if(y==numero_cifras) { for(z=0; z<numero_de_letras; z++) { if(suma (atof(auxiliar ))==clave [z ]) { descifrado [strlen(descifrado )]=letras [z ]; y=0; break; } } } } }
Pero ahora está en que el código no compila, el gcc me da el siguiente error: pruebas: En la función `_fini': (.fini+0x0): definiciones múltiples de `_fini' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crti.o:(.fini+0x0): primero se definió aquí pruebas: En la función `data_start': (.data+0x0): definiciones múltiples de `__data_start' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crt1.o:(.data+0x0): primero se definió aquí pruebas: En la función `data_start': (.data+0x8): definiciones múltiples de `__dso_handle' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/crtbegin.o:(.data+0x0): primero se definió aquí pruebas:(.rodata+0x0): definiciones múltiples de `_IO_stdin_used' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crt1.o:(.rodata.cst4+0x0): primero se definió aquí pruebas: En la función `_start': (.text+0x0): definiciones múltiples de `_start' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crt1.o:(.text+0x0): primero se definió aquí pruebas: En la función `_init': (.init+0x0): definiciones múltiples de `_init' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../lib/crti.o:(.init+0x0): primero se definió aquí /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/crtend.o:(.tm_clone_table+0x0): definiciones múltiples de `__TMC_END__' pruebas:(.data+0x30): primero se definió aquí /usr/bin/ld: error en pruebas(.eh_frame); no se creará la tabla .eh_frame_hdr. collect2: error: ld devolvió el estado de salida 1
No se que estoy haciendo mal la verdad, uso gcc en gnu/linux, exactamente en antergos, y para compilarlo hago un "gcc pruebas -o pruebas.c -lm". He probado a compilarlo con compiladores online para ver si es que era mi pc y no el código, y me da el error: In function `arrancar_motor': undefined reference to `pow' undefined reference to `pow'
En cambio como puedes ver está incluida la librería math.h ¿ Me puedes echar un cable con este error ?, ¿ he implementado bien las corecciones que has descrito en el anterior comentario ?. Saludos.
|
|
« Última modificación: 22 Abril 2015, 17:48 pm por pacosn1111 »
|
En línea
|
|
|
|
T. Collins
Desconectado
Mensajes: 206
|
gcc pruebas.c -o pruebas -lm
|
|
|
En línea
|
|
|
|
pacosn1111
Desconectado
Mensajes: 59
|
gcc pruebas.c -o pruebas -lm
Ostras, que despiste, perdonad, ya lo he compilado y lo he probado, el caso es que si arranco el motor con una clave de 10 cifras arranca perfecto, pero cuando le meto ya 15 o 20 genera un único número aleatorio, este: "-2147483648". Saludos.
|
|
« Última modificación: 22 Abril 2015, 17:47 pm por pacosn1111 »
|
En línea
|
|
|
|
T. Collins
Desconectado
Mensajes: 206
|
Estás utilizando pow que puede devolver números muy grandes que no entran en cualquier tipo de variable.
|
|
|
En línea
|
|
|
|
pacosn1111
Desconectado
Mensajes: 59
|
voy avanzando, dejo el codigo que llevo ahora: #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <math.h> // constantes #define numero_de_letras 27 // variables globales double claves[numero_de_letras][1000]; int clave[numero_de_letras]; // arrays globales char letras[]="abcdefghijklmnopqrstuvwxyz "; char cifrado[999999999]; char descifrado[999999999]; // prototipos de funciones void generar_clave(int); void ingresar_clave(int []); int comprobar_repetir_vector(int, int, int []); int comprobar_repetir_matriz(int, double, double [][1000]); void arrancar_motor(int, int); int suma(double); double aleatorio(double, double); void cifrar(int, int, char []); void descifrar(int, char []); int main() { generar_clave(10); arrancar_motor(10, 1); } // comprueba si un numero esta repetido en una matriz, si esta repetido devuelve 1, en caso contrario 0. int comprobar_repetir_matriz(int n, double numero, double matriz[][1000]) { int x; int y; for(x=0; x<n-1; x++) { for(y=0;y<1000;y++) { if (numero==matriz[x][y]) { return 1; } } } return 0; } // comprueba si un numero esta repetido en un vector, si esta repetido devuelve 1, en caso contrario 0. int comprobar_repetir_vector(int n, int numero, int vector[]){ int x; for(x=0; x<n-1;x++) { if(numero==vector[x]) { return 1; } } return 0; } // Devuelve la suma de las cifras de un numero int suma(double numero) { int resultado=0; while (numero>0) { resultado+=fmod(numero, 10); numero/=10; } return resultado; } //Genera un numero aleatorio sin decimales dentro de un rango entre max y min. double aleatorio(double max, double min) { return fmod (rand (), (max -min +1) + min ); } //Genera una clave optimidada y la guarda en la variable global clave. void generar_clave(int numero_suma) { int maximo, minimo, x, y, num_random; int max=120; int min=60; maximo=numero_suma*max/20; minimo=numero_suma*min/20; for(x=0;x<numero_de_letras;) { num_random=aleatorio(maximo, minimo); if (comprobar_repetir_vector(x, num_random, &clave[0])==1) { continue; } clave[x]=num_random; x++; } printf("se ha generado la clave: \n"); for(y=0;y<numero_de_letras;y++) { } } // Permite ingresar el valor de cualquier array en la variable global clave. void ingresar_clave(int array[]) { int x; for(x=0;x<numero_de_letras;x++) { clave[x]=array[x]; } } // Genera los numeros aleatorios correspondientes a cada letra y los guarda según corresponda en la matriz claves. void arrancar_motor(int numero_cifras, int cantidad_numeros){ int y, z, h; double num_random; double min =(double)pow(10.0, numero_cifras -1); double max =(double)pow(10.0, numero_cifras )-1; for(z=0; z<numero_de_letras; z++) { printf("Inicializando letra %c\n", letras [z ]); for(h=0; h<cantidad_numeros;) { num_random=aleatorio(max, min); if (((fabs(suma (num_random )-clave [z ])) < 0.001) && (comprobar_repetir_matriz (z , num_random , claves ))==0) { claves[z][h]=num_random; printf("%.0lf\n", num_random ); h++; } else { continue; } } } printf("se ha generado la clave: \n"); for(y=0;y<numero_de_letras;y++) { } printf("\ncon un numero de cifras de %d\n", numero_cifras ); } // Cifra un texto usando la clave almancenada en la variable global clave, el resultado lo guarda en la variable global cifrado. void cifrar(int numero_cifras, int cantidad_numeros, char texto[]) { int letra, letrass, x; char cifrado_inside [strlen(texto )*numero_cifras ]; char string_auxiliar[numero_cifras-1]; for(letra =0; strlen(texto )>letra ; letra ++) { for(letrass=0; letrass<numero_de_letras; letrass++) { if (texto[letra]==letras[letrass]) { sprintf(string_auxiliar , "%.0lf", claves [letrass ][(int)(aleatorio (cantidad_numeros -1, 0))]); strcat(cifrado_inside , string_auxiliar ); break; } } } strcpy(cifrado , cifrado_inside ); } // Descifra un texto cifrado anteriormente usando la clave almancenada en la variable global clave, el resultado lo guarda en la variable global descifrado. void descifrar(int numero_cifras, char cifrado[]) { char auxiliar[numero_cifras]; int x, y=0, z; for(x=0; x<strlen(cifrado); x++) { auxiliar[y]=cifrado[x]; y++; if(y==numero_cifras) { for(z=0; z<numero_de_letras; z++) { if(suma (atof(auxiliar ))==clave [z ]) { descifrado [strlen(descifrado )]=letras [z ]; y=0; break; } } } } }
Pero ahora el problema es que se generan numeros aleatorios con cifras incorrectas, es decir que si tienen que generarse de 10 cifras, se generan de 10 cifras y alguno que otro de 8 y 9. ¿Podeis echarle un vistazo?. Saludos
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
He perdido parte de codigo fuente de un programa de VB 6.0...
Ingeniería Inversa
|
Shook
|
3
|
2,902
|
24 Agosto 2005, 21:23 pm
por titocosa
|
|
|
por favor ayuda codigo de seguridad perdido nokia 6070
Dispositivos Móviles (PDA's, Smartphones, Tablets)
|
dollvip
|
5
|
9,874
|
24 Febrero 2016, 14:18 pm
por Shell Root
|
|
|
Le podeis echar un ojo a este codigo??. Es un codigo pequeño y facil.
« 1 2 »
PHP
|
70N1
|
10
|
7,254
|
19 Febrero 2010, 18:14 pm
por 70N1
|
|
|
Ayudenme con este codigo en C porfavor.!!debo entregar este deber hoy :(
Programación C/C++
|
Matahembras
|
0
|
1,649
|
15 Febrero 2015, 20:53 pm
por Matahembras
|
|
|
Este año empece arquitectura y ando perdido con autocad
Software
|
pepino32
|
2
|
2,023
|
28 Julio 2020, 13:01 pm
por pepino32
|
|