Autor
|
Tema: [Ayuda-C] Bucle infinito (Leído 3,106 veces)
|
Miky Gonzalez
Desconectado
Mensajes: 87
http://mikygonzalez.comule.com/blog/
|
Estaba programando en C un ensamblador para programas de mi máquina virtual (decidí continuar un proyecto). Tengo el siguiente código: /*! Ejemplo de lector de archivo */ #include <stdio.h> #include <stdlib.h> /*! Declaración de variables locales */ enum {lex_PARI = '(', lex_PARD = ')', lex_LLAI = '{', lex_LLAD = '}'}; unsigned short int pos = 0x00; unsigned int codigo_volumen; unsigned char *codigo; FILE *codigo_archivo; void siguiente_lexema(unsigned char *codigo); void buscar_caracter(char caracter) { while((caracter != codigo[pos]) && (pos < codigo_volumen)) { siguiente_lexema(codigo); pos++; } if(pos == codigo_volumen) printf("Se esperaba '%c'", caracter ); } // modo == 0 (si cadena) // modo == 1 (si entero) void identificador(unsigned char *codigo, char modo) { return; } int saber_letra(char caracter) { return (((caracter >= 'A') && (caracter <= 'Z')) || ((caracter >= 'a') && (caracter <= 'z'))); } int saber_numero(char caracter) { return ((caracter >= '0') && (caracter <= '9')); } void siguiente_lexema(unsigned char *codigo) { switch(codigo[pos]) { case lex_PARI: printf("Encontrado: %c\n", lex_PARI ); buscar_caracter(lex_PARD); break; case lex_LLAI: printf("Encontrado: %c\n", lex_LLAI ); buscar_caracter(lex_LLAD); break; default: if(saber_letra(codigo[pos])) identificador(codigo, 0); else if(saber_numero(codigo[pos])) identificador(codigo, 1); /* * TODO: Mostrar error. Ignorar espacios, salto de línea y tabulador */ else ; break; } return; } int main(int argc, char **argv) { if(argc < 2) { printf("Uso: %s <archivo>\n", argv [0]); return 0; } codigo_archivo = fopen(argv [1], "r"); if(!codigo_archivo) { printf("[ASM] Error al leer el archivo %s\n", argv [1]); return 0; } /* Calcular tamaño (volumen) del código */ fseek(codigo_archivo , 0, SEEK_END ); codigo_volumen = ftell(codigo_archivo ); if(!codigo_volumen) { printf("[ASM] No hay instrucciones...\n"); return 0; } /* Reservar el espacio necesario para almacenar * el código en memoria. Si existe, copiarlo. */ codigo = (unsigned char *)malloc(codigo_volumen ); if(!fread(codigo , 1, codigo_volumen , codigo_archivo )) { printf("[ASM] Error en lectura de archivo...\n"); return 0; } else fclose(codigo_archivo ); while(pos < codigo_volumen) { siguiente_lexema(codigo); pos++; } return 0; }
El problema está en que dado un archivo: { { { ( {} )( } } }
Entra en un bucle infinito. He revisado muchas veces el código pero no veo ningún error de direcciones, punteros... ¿Alguien puede determinar a causa de que?
|
|
|
En línea
|
Mi blog personal, con información acerca de programación, seguridad, desarrollo y electrónica: EN CONSTRUCCIÓN
|
|
|
0xDani
Desconectado
Mensajes: 1.077
|
Quizá sea porque siguiente_lexema() llama a buscar_caracter(), que a su vez llama a siguiente_lexema()...
Si quieres hacer un ensamblador te recomendaría usar un lenguaje más sencillo como Python y expresiones regulares, si el rendimiento no te importa demasiado.
|
|
|
En línea
|
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!
I code for $$$ Hago trabajos en C/C++ Contactar por PM
|
|
|
xv0
Desconectado
Mensajes: 1.027
|
Depuralo asi sabras donde esta el problema. Tambien podrias hacer funciones como esta te dejo este link, es un deliminador de caracteres pero puedes adaptarlo, mira el ultimo mensaje que deje. http://foro.elhacker.net/asm/ayuda_con_funcion_split-t386501.15.html Un saludo.
|
|
« Última modificación: 10 Octubre 2013, 21:57 pm por cpu2 »
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
El error principal ya lo indico 0xDani: Quizá sea porque siguiente_lexema() llama a buscar_caracter(), que a su vez llama a siguiente_lexema()... Y como en ningún momento se modifica el valor de la variable "global" "pos" ello resulta en una recursion infinita. ---- Aparte de eso se puede mejorar el programa: * Falta consistencia, por ejemplo la función "buscar_caracter" accede directamente a la variable "global" "codigo" mientras que la función "siguiente_lexema" accede a la misma variable en base a su único parámetro. * Deberías sustituir tus funciones "saber_letra" y "saber_numero" por "isalpha" e "isdigit" (prototipos en <ctype.h>). Si por alguna razón debes utilizar funciones propias puedes eliminar todos los paréntesis en ellas ya que no son necesarios. * No generes tus propios mensajes de error si una función de entrada/salida falla, en su lugar relega ese trabajo a la función perror. * Si abres un archivo en modo texto calcular su numero de caracteres en base a fseek+ftell es problemático en el mejor de los casos ya que al hacerlo obtienes la posición en bytes y esto puede funcionar o no. Un ejemplo, si tenemos en MS Windows el archivo de texto: Su contenido son dos lineas de texto, los diez caracteres requieren doce bytes (aquí el avance de linea se representa por la secuencia '\r' + '\n'). Si en ese SO ejecutamos el programa: #include <stdio.h> #include <stdlib.h> #define NOM_ENTRADA "Entrada.txt" int main(void) { FILE *entrada; long num_bytes; int num_chars; if ((entrada = fopen(NOM_ENTRADA , "rt")) == NULL ){ return EXIT_FAILURE; } fseek(entrada , 0, SEEK_END ); num_bytes = ftell(entrada ); for (num_chars = 0; fgetc(entrada ) != EOF ; num_chars ++) ; printf("numero de caracteres: %d\n", num_chars ); printf("numero de bytes: %ld\n", num_bytes ); return EXIT_SUCCESS; }
Su salida es: numero de caracteres: 10 numero de bytes: 12 En Linux no hay problema. Un saludo
|
|
|
En línea
|
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language
|
|
|
Miky Gonzalez
Desconectado
Mensajes: 87
http://mikygonzalez.comule.com/blog/
|
Gracias por la ayuda, al final resultó ser un problema estúpido. No aumentaba la variable pos en un determinado caso: que los paréntesis sean escritos juntos. Respecto al comentario de rir3760: La falta de consistencia está solucionado. Si te preguntas el porqué paso código como parámetro se debe a que en un futuro implementaré hilos para hacer el proceso más rápido (analizar varios archivos al mismo tiempo). Utilizo funciones (podría hacerlo con un #define pero aumentaría tamaño del código) propias porque me han resultado ser más rápidas (linux). Los mensajes de error prefiero especificarlos yo, para tener un control absoluto del sistema de errores que se produzcan en el programa. La forma en la que tengo implementada el código no podría admitir el uso de fgetc() para leer el tamaño del archivo, a no ser que la lectura y el analizado se hagan de una forma atómica. No se producirá ningún error, porque carácteres como ' ', '\t', '\n', '\r'... serán descartados de análisis. El código resultante: /*! Ejemplo de lector de archivo */ #include <stdio.h> #include <string.h> #include <stdlib.h> #define NUM_INSTR 2 /*! Declaración de variables locales */ enum {lex_PARI = '(', lex_PARD = ')', lex_LLAI = '{', lex_LLAD = '}'}; unsigned short int pos = 0x00; unsigned int codigo_volumen; char lista_instrucciones[NUM_INSTR][10] = { {"PRINT"}, {"EXIT"} }; void siguiente_lexema(unsigned char *codigo); int saber_letra(char caracter); void buscar_caracter(char caracter, unsigned char *codigo) { pos++; while((codigo[pos] != caracter) && (pos < codigo_volumen)) siguiente_lexema(codigo); if(pos == codigo_volumen) printf("Se esperaba '%c'", caracter ); } /* * TODO: Identificar palabra reservada ó símbolo */ // modo == 0 (si cadena) // modo == 1 (si entero) void identificador_cadena(unsigned char *codigo) { unsigned short int pos_buffer = 0; char *buffer = (char *)malloc(1 * sizeof(char)); while(saber_letra(codigo[pos])) { buffer[pos_buffer] = codigo[pos]; pos++; pos_buffer++; buffer = (char *)realloc(buffer , (pos_buffer + 1) * sizeof(char)); } // Reutilizar variable pos_buffer for(pos_buffer = 0; pos_buffer < NUM_INSTR; pos_buffer++) if(strcmp(buffer , lista_instrucciones [pos_buffer ])) printf("Encontrado %s en %s", lista_instrucciones [pos_buffer ], buffer ); return; } int saber_letra(char caracter) { return ((caracter >= 'A') && (caracter <= 'Z')) || ((caracter >= 'a') && (caracter <= 'z')); } int saber_numero(char caracter) { return (caracter >= '0') && (caracter <= '9'); } void siguiente_lexema(unsigned char *codigo) { switch(codigo[pos]) { case lex_PARI: printf("Encontrado: %c\n", lex_PARI ); buscar_caracter(lex_PARD, codigo); break; case lex_LLAI: printf("Encontrado: %c\n", lex_LLAI ); buscar_caracter(lex_LLAD, codigo); break; default: if(saber_letra(codigo[pos])) identificador_cadena(codigo); else if(saber_numero(codigo[pos])) //identificador(codigo, 1); ; /* * TODO: Mostrar error. Ignorar espacios, salto de línea y tabulador */ else ; break; } pos++; return; } int main(int argc, char **argv) { if(argc < 2) { printf("Uso: %s <archivo>\n", argv [0]); return 0; } FILE *codigo_archivo = fopen(argv [1], "r"); if(!codigo_archivo) { printf("[ASM] Error al leer el archivo %s\n", argv [1]); return 0; } /* Calcular tamaño (volumen) del código */ fseek(codigo_archivo , 0, SEEK_END ); codigo_volumen = ftell(codigo_archivo ); if(!codigo_volumen) { printf("[ASM] No hay instrucciones...\n"); return 0; } /* Reservar el espacio necesario para almacenar * el código en memoria. Si existe, copiarlo. */ unsigned char *codigo = (unsigned char *)malloc(codigo_volumen ); if(!fread(codigo , 1, codigo_volumen , codigo_archivo )) { printf("[ASM] Error en lectura de archivo...\n"); return 0; } else fclose(codigo_archivo ); while(pos < codigo_volumen) siguiente_lexema(codigo); return 0; }
|
|
« Última modificación: 11 Octubre 2013, 16:27 pm por Miky Gonzalez »
|
En línea
|
Mi blog personal, con información acerca de programación, seguridad, desarrollo y electrónica: EN CONSTRUCCIÓN
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Como hacer que un bucle no se infinito cuando ingreso letras en un switch
Programación C/C++
|
zenemijinterjb
|
1
|
1,951
|
30 Noviembre 2014, 02:26 am
por rir3760
|
|
|
tengo un bucle infinito conmigo, HELP!
Java
|
sowi12
|
7
|
3,078
|
15 Septiembre 2015, 22:17 pm
por 0roch1
|
|
|
Ayuda Phyton bucle infinito
Scripting
|
SkaTrumpet
|
1
|
1,898
|
1 Diciembre 2015, 01:06 am
por daryo
|
|
|
Bucle Infinito ayuda.
Programación C/C++
|
jtrujilloj
|
1
|
2,368
|
13 Febrero 2018, 09:42 am
por vangodp
|
|
|
error, bucle infinito, alguien que me ayude a evitar el bucle infinito
Programación C/C++
|
marcos0204
|
4
|
2,865
|
27 Marzo 2020, 22:44 pm
por fary
|
|