Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: m@o_614 en 16 Febrero 2014, 21:18 pm



Título: modos de direccionamiento
Publicado por: m@o_614 en 16 Febrero 2014, 21:18 pm
Saludos, tengo el siguiente codigo que dado un operando (una cadena) tiene que verificar que modo de direccionamiento es, puede ser inmediato,directo o indexado, yo ahora estoy verificando cuando un operando es indexado, esto es: que el primer caracter sea un corchete [, que el segundo caracter sea una d ó D, que el tercer caracter sea una coma, y ya que verificaste los primeros 3 el termino que va despues de la coma puede ser X,Y,SP,PC, o sea algo como:

[D,X], [D,Y], [D,SP], [D,PC]  

el problema lo tengo en la funcion direccionamientoIndexado() que se supone que me tiene que imprimir el termino que va despues de la coma, pero cuando los operandos son: [D,SP] o [D,PC] el segundo termino lo imprime como SSP en vez de SP y no entiendo por qué. EL codigo va leyendo desde la coma hasta el corcheta ] y lo que se encuentre entre estos dos los guarda en una cadena

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define INMEDIATO '#'
  5. #define DIRECTO '$'
  6. #define INDEXADO '['
  7.  
  8. void modoDireccionamiento(char *operando);
  9. void direccionamientoIndexado(char *operando);
  10. int esNumeroBase16(char caracter);
  11. int esLetraBase16(char caracter);
  12. int esOctal(char caracter);
  13. int esBinario(char caracter);
  14.  
  15. int main()
  16. {
  17.    char *operando = "[D,PC]";
  18.    modoDireccionamiento(operando);
  19.    return 0;
  20. }
  21.  
  22. void modoDireccionamiento(char *operando)
  23. {
  24.    int car,esInmediato,esDirecto,esIndexado,tam,i;
  25.    tam = strlen(operando);
  26.    car = operando[0];
  27.    switch(car)
  28.    {
  29.        case INMEDIATO:
  30.           esInmediato = 1;
  31.           car = operando[1];
  32.           switch(car)
  33.           {
  34.               case '\0':
  35.                  printf("Es un formato invalido para un modo de direccionamiento inmediato\n");
  36.                  break;
  37.               case '$':
  38.                  for(i = 2;((i < tam)&&(esInmediato));i++)
  39.                  {
  40.                      if((!esNumeroBase16(operando[i]))&&(!esLetraBase16(operando[i])))
  41.                         esInmediato = 0;
  42.                  }
  43.                  if(!esInmediato)
  44.                     printf("Se encontro un digito invalido para un numero de base 16");
  45.                  break;
  46.               case '@':
  47.                  for(i = 2;((i < tam)&&(esInmediato));i++)
  48.                  {
  49.                      if(!esOctal(operando[i]))
  50.                         esInmediato = 0;
  51.                  }
  52.                  if(!esInmediato)
  53.                     printf("Se encontro un digito invalido para un numero de base 8");
  54.                  break;
  55.               case '%':
  56.                  for(i = 2;((i < tam)&&(esInmediato));i++)
  57.                  {
  58.                      if(!esBinario(operando[i]))
  59.                         esInmediato = 0;
  60.                  }
  61.                  if(!esInmediato)
  62.                     printf("Se encontro un digito invalido para un numero de base 2");
  63.                  break;
  64.               default:
  65.                  printf("Error");
  66.           }
  67.           break;
  68.        case DIRECTO:
  69.           esDirecto = 1;
  70.           if(operando[1] == '\0')
  71.              printf("Es un formato invalido para un modo de direccionamiento directo\n");
  72.           else
  73.           {
  74.               for(i = 2;((i < tam)&&(esDirecto));i++)
  75.               {
  76.                   if((!esNumeroBase16(operando[i]))&&(!esLetraBase16(operando[i])))
  77.                      esDirecto = 0;
  78.               }
  79.               if(!esDirecto)
  80.                  printf("Se encontro un digito invalido para un numero de base 16");
  81.           }
  82.           break;
  83.        case INDEXADO:
  84.           esIndexado = 1;
  85.           car = operando[1];
  86.           switch(car)
  87.           {
  88.               case '\0':
  89.                  printf("Es un formato invalido para un modo de direccionamiento indexado\n");
  90.                  break;
  91.               case ',':
  92.                  printf("No puede haber una instruccion vacia antes de la coma");
  93.                  break;
  94.               case 'd':
  95.               case 'D':
  96.                  if(operando[2] == ',')
  97.                  {
  98.                      direccionamientoIndexado(operando);
  99.                         //esIndexado = 0;
  100.                  }
  101.                  //if(!esIndexado)
  102.                     //printf("Es un formato invalido para direccionamiento indexado");
  103.                  break;
  104.               default:
  105.                  printf("Error");
  106.           }
  107.           break;
  108.        default:
  109.           printf("Error: es un formato invalido para los modos de direccionamiento inmediato\n");
  110.    }
  111. }
  112.  
  113. int esNumeroBase16(char caracter)
  114. {
  115.    if(caracter >= '0' && caracter <= '9')
  116.       return 1;
  117.    else
  118.       return 0;
  119. }
  120.  
  121. int esLetraBase16(char caracter)
  122. {
  123.    if((caracter >= 'A' && caracter <= 'F')||(caracter >= 'a' && caracter <= 'f'))
  124.       return 1;
  125.    else
  126.       return 0;
  127. }
  128.  
  129. int esOctal(char caracter)
  130. {
  131.    if(caracter >= '0' && caracter <= '7')
  132.       return 1;
  133.    else
  134.       return 0;
  135. }
  136.  
  137. int esBinario(char caracter)
  138. {
  139.    if(caracter == '1' || caracter == '0')
  140.       return 1;
  141.    else
  142.       return 0;
  143. }
  144.  
  145. void direccionamientoIndexado(char *operando)
  146. {
  147.    int i;
  148.    char *cadena = NULL,c[2];
  149.    cadena = calloc(2,sizeof(char));
  150.    for(i = 3;operando[i] != ']';i++)
  151.    {
  152.        sprintf(c,"%c",operando[i]);
  153.        strcat(cadena,c);
  154.        printf("%s",cadena);
  155.    }
  156. }
  157.  

si alguien me pudiera decir donde esta el error se lo agradeceria mucho


Título: Re: modos de direccionamiento
Publicado por: erest0r en 17 Febrero 2014, 01:10 am
Hola debe ser cuando ejecutas strcat(cadena,c); a la primera vez le estas pasando en este caso 'P' que es lo que tiene la variable c en ese momento, pero cuando vuelva a ejecutarse strcat(cadena,c); en ese momento le estas pasando ahora "PC" que es lo que tiene la variable c despues, y por eso se repite 2 veces el primer caracter.

Corrijo: El error esta en que la primera vez se muestra lo que tiene la variable cadena en ese momento que es 'P', luego a la segunda iteracion le pasas a cadena la letra 'C', cuando muestres de nuevo el contenido de cadena se reflejara "PC", y por eso se ve que se repite la 'P' 2 veces, en todo caso la sentencia printf("%s",cadena); deberia ir fuera del ciclo for.


Título: Re: modos de direccionamiento
Publicado por: m@o_614 en 17 Febrero 2014, 19:18 pm
gracias erest0r por tu respuesta, ya cambie el printf que me estaba dando problemas ahora me queda una duda, para comparar cadenas tengo que usar strcmp pero si tengo que verificar si la cadena es "X","Y","SP" o "PC", no habra una manera de reducir el codigo en esa parte donde tengo los strcmps en el if??:

Código
  1. int direccionamientoIndexado(char *operando)
  2. {
  3.    int i;
  4.    char *cadena = NULL,c[2];
  5.    cadena = calloc(2,sizeof(char));
  6.    for(i = 3;operando[i] != ']';i++)
  7.    {
  8.        sprintf(c,"%c",operando[i]);
  9.        strcat(cadena,c);
  10.    }
  11.    printf("%s",cadena);
  12.    if((strcmp(cadena,"X") == 0)||(strcmp(cadena,"Y") == 0)||(strcmp(cadena,"SP") == 0)||(strcmp(cadena,"PC") == 0))
  13.       return 1;
  14.    else
  15.       return 0;
  16. }
  17.  

gracias


Título: Re: modos de direccionamiento
Publicado por: erest0r en 18 Febrero 2014, 04:38 am
Hola, ¿que te parece esta manera?

Código
  1. int direccionamientoIndexado(char *operando)
  2. {
  3.    int i;
  4.    char *cadena = NULL,c[2];
  5.    char index[4][3] = { "X", "Y", "SP", "PC" };
  6.    cadena = (char *)calloc(2,sizeof(char));
  7.    for(i = 3;operando[i] != ']';i++)
  8.    {
  9.        sprintf(c,"%c",operando[i]);
  10.        strcat(cadena,c);
  11.    }
  12.    printf("%s",cadena);
  13.  
  14.    for( i = 0; i < 4; i++ )
  15.    {
  16.        if( strcmp(cadena, index[i]) == 0 )
  17.            return 1;
  18.    }
  19.       return 0;
  20. }
  21.  

De esa forma el IF se hace mas corto, solo que se agrega una variable de cadena para compararla en cada iteracion con tu variable "cadena", si es igual a una de ellas retorna 1, sino retorna 0.


Título: Re: modos de direccionamiento
Publicado por: m@o_614 en 18 Febrero 2014, 16:12 pm
gracias erest0r, si de esa manera es mucho mejor, y asi ya no tengo que repetir tantos strcmp's en la línea del if. Una última pregunta, una vez que ya tengo concatenadas todas las letras que quiero en la cadena(con ayuda del strcat), tengo que agregarle al final el carácter de fin de cadena '\0'? para que no almacene basura


Título: Re: modos de direccionamiento
Publicado por: erest0r en 18 Febrero 2014, 17:35 pm
En tu caso no es necesario, ya que cuando creas el tamaño de "cadena" lo haces con funcion calloc, y ello lo inicializa con todas sus posiciones en '\0', aun asi, por lo general es recomendable que dejes al menos una posicion libre para finalizarle con '\0' y asi el programa pueda reconocer el fin de cadena, si lo hicieras con un malloc, te crea el arreglo con contenido basura y al mostrar lo que tiene "cadena" te mostrara lo que le asignaste mas toda esa informacion basura.


Título: Re: modos de direccionamiento
Publicado por: rir3760 en 18 Febrero 2014, 18:27 pm
estoy verificando cuando un operando es indexado, esto es: que el primer caracter sea un corchete [, que el segundo caracter sea una d ó D, que el tercer caracter sea una coma, y ya que verificaste los primeros 3 el termino que va despues de la coma puede ser X,Y,SP,PC, o sea algo como:

[D,X], [D,Y], [D,SP], [D,PC]
Supongo eventualmente vas a estudiar el tema de maquinas de estado (lo usual para desarrollar tu programa). Llevas la materia de teoria de compiladores, ¿Correcto?

Una última pregunta, una vez que ya tengo concatenadas todas las letras que quiero en la cadena(con ayuda del strcat), tengo que agregarle al final el carácter de fin de cadena '\0'? para que no almacene basura
No ya que al utilizar sprintf y strcat son esas funciones las que agregan el '\0'. Lo que si debes hacer es incrementar el tamaño del bloque de memoria para almacenar ese caracter.

Y no deberias utilizar sprintf y strcat ya que puedes agregar los caracteres y el '\0' con un simple bucle.

----

Por ultimo en un caso tan limitado se puede utilizar la funcion sscanf para verificar si la cadena cumple con el formato esperado, de nuevo lo mejor es una maquina de estado pero si se trata de matar tiempo:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int fn(char *p);
  5.  
  6. int main(void)
  7. {
  8.   char pal[][4] = {
  9.      "X]",
  10.      "X}",
  11.      "Y]",
  12.      "Z]",
  13.      "SP]",
  14.      "XY]",
  15.      "PC]",
  16.      "PC)"
  17.   };
  18.   int i;
  19.   int num_pals = (int) (sizeof pal / sizeof pal[0]);
  20.  
  21.   for (i = 0; i < num_pals; i++)
  22.      printf("%s ==> %s\n", pal[i], fn(pal[i]) ? "OK" : "ERROR");
  23.  
  24.   return EXIT_SUCCESS;
  25. }
  26.  
  27. int fn(char *p)
  28. {
  29.   char a[2];
  30.   char b[2];
  31.  
  32.   return sscanf(p, "%1[XY]%1[]]", a, b) == 2 || sscanf(p, "SP%1[]]", b) == 1 || sscanf(p, "PC%1[]]", b) == 1;
  33. }

Y la salida es:
Código:
$ ./main.exe
X] ==> OK
X} ==> ERROR
Y] ==> OK
Z] ==> ERROR
SP] ==> OK
XY] ==> ERROR
PC] ==> OK
PC) ==> ERROR

Un saludo


Título: Re: modos de direccionamiento
Publicado por: m@o_614 en 24 Febrero 2014, 02:50 am
Saludos rir3760 no es para la materia de compiladores, esto es basicamente para crear un ensamblador para la materia de Programacion de sistemas, que es la antesala para compiladores, y el codigo sirve para verificar los diferentes modos de direccionamiento que puede tener, en este caso estoy verificando los indexados, los que estan entre corchetes, pero me queda una ultima duda, si por ejemplo tengo [D,SP   , aqui el operando esta todo bien excepto porque no tiene un corchete al final ']'. ¿Cómo puedo hacer que me verifique este error si en la función direccionamientoIndexado tengo que el for va a seguir iterando hasta que encuentre el ], pero en este caso no hay ningun corchete:

Código
  1. void direccionamientoIndexado(char *operando)
  2. {
  3.    int i;
  4.    char *cadena = NULL,c[2];
  5.    cadena = calloc(2,sizeof(char));
  6.    for(i = 3;operando[i] != ']';i++)
  7.    {
  8.        sprintf(c,"%c",operando[i]);
  9.        strcat(cadena,c);
  10.        printf("%s",cadena);
  11.    }
  12. }

de antemano gracias