modos de direccionamiento

Iniciado por m@o_614, 16 Febrero 2014, 21:18 PM

0 Miembros y 1 Visitante están viendo este tema.

m@o_614

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INMEDIATO '#'
#define DIRECTO '$'
#define INDEXADO '['

void modoDireccionamiento(char *operando);
void direccionamientoIndexado(char *operando);
int esNumeroBase16(char caracter);
int esLetraBase16(char caracter);
int esOctal(char caracter);
int esBinario(char caracter);

int main()
{
   char *operando = "[D,PC]";
   modoDireccionamiento(operando);
   return 0;
}

void modoDireccionamiento(char *operando)
{
   int car,esInmediato,esDirecto,esIndexado,tam,i;
   tam = strlen(operando);
   car = operando[0];
   switch(car)
   {
       case INMEDIATO:
          esInmediato = 1;
          car = operando[1];
          switch(car)
          {
              case '\0':
                 printf("Es un formato invalido para un modo de direccionamiento inmediato\n");
                 break;
              case '$':
                 for(i = 2;((i < tam)&&(esInmediato));i++)
                 {
                     if((!esNumeroBase16(operando[i]))&&(!esLetraBase16(operando[i])))
                        esInmediato = 0;
                 }
                 if(!esInmediato)
                    printf("Se encontro un digito invalido para un numero de base 16");
                 break;
              case '@':
                 for(i = 2;((i < tam)&&(esInmediato));i++)
                 {
                     if(!esOctal(operando[i]))
                        esInmediato = 0;
                 }
                 if(!esInmediato)
                    printf("Se encontro un digito invalido para un numero de base 8");
                 break;
              case '%':
                 for(i = 2;((i < tam)&&(esInmediato));i++)
                 {
                     if(!esBinario(operando[i]))
                        esInmediato = 0;
                 }
                 if(!esInmediato)
                    printf("Se encontro un digito invalido para un numero de base 2");
                 break;
              default:
                 printf("Error");
          }
          break;
       case DIRECTO:
          esDirecto = 1;
          if(operando[1] == '\0')
             printf("Es un formato invalido para un modo de direccionamiento directo\n");
          else
          {
              for(i = 2;((i < tam)&&(esDirecto));i++)
              {
                  if((!esNumeroBase16(operando[i]))&&(!esLetraBase16(operando[i])))
                     esDirecto = 0;
              }
              if(!esDirecto)
                 printf("Se encontro un digito invalido para un numero de base 16");
          }
          break;
       case INDEXADO:
          esIndexado = 1;
          car = operando[1];
          switch(car)
          {
              case '\0':
                 printf("Es un formato invalido para un modo de direccionamiento indexado\n");
                 break;
              case ',':
                 printf("No puede haber una instruccion vacia antes de la coma");
                 break;
              case 'd':
              case 'D':
                 if(operando[2] == ',')
                 {
                     direccionamientoIndexado(operando);
                        //esIndexado = 0;
                 }
                 //if(!esIndexado)
                    //printf("Es un formato invalido para direccionamiento indexado");
                 break;
              default:
                 printf("Error");
          }
          break;
       default:
          printf("Error: es un formato invalido para los modos de direccionamiento inmediato\n");
   }
}

int esNumeroBase16(char caracter)
{
   if(caracter >= '0' && caracter <= '9')
      return 1;
   else
      return 0;
}

int esLetraBase16(char caracter)
{
   if((caracter >= 'A' && caracter <= 'F')||(caracter >= 'a' && caracter <= 'f'))
      return 1;
   else
      return 0;
}

int esOctal(char caracter)
{
   if(caracter >= '0' && caracter <= '7')
      return 1;
   else
      return 0;
}

int esBinario(char caracter)
{
   if(caracter == '1' || caracter == '0')
      return 1;
   else
      return 0;
}

void direccionamientoIndexado(char *operando)
{
   int i;
   char *cadena = NULL,c[2];
   cadena = calloc(2,sizeof(char));
   for(i = 3;operando[i] != ']';i++)
   {
       sprintf(c,"%c",operando[i]);
       strcat(cadena,c);
       printf("%s",cadena);
   }
}


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

erest0r

#1
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.
Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.

m@o_614

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??:

int direccionamientoIndexado(char *operando)
{
    int i;
    char *cadena = NULL,c[2];
    cadena = calloc(2,sizeof(char));
    for(i = 3;operando[i] != ']';i++)
    {
        sprintf(c,"%c",operando[i]);
        strcat(cadena,c);
    }
    printf("%s",cadena);
    if((strcmp(cadena,"X") == 0)||(strcmp(cadena,"Y") == 0)||(strcmp(cadena,"SP") == 0)||(strcmp(cadena,"PC") == 0))
       return 1;
    else
       return 0;
}


gracias

erest0r

Hola, ¿que te parece esta manera?

Código (cpp) [Seleccionar]

int direccionamientoIndexado(char *operando)
{
    int i;
    char *cadena = NULL,c[2];
    char index[4][3] = { "X", "Y", "SP", "PC" };
    cadena = (char *)calloc(2,sizeof(char));
    for(i = 3;operando[i] != ']';i++)
    {
        sprintf(c,"%c",operando[i]);
        strcat(cadena,c);
    }
    printf("%s",cadena);

    for( i = 0; i < 4; i++ )
    {
        if( strcmp(cadena, index[i]) == 0 )
            return 1;
    }
       return 0;
}


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.
Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.

m@o_614

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

erest0r

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.
Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.

rir3760

Cita de: m@o_614 en 16 Febrero 2014, 21:18 PMestoy 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?

Cita de: m@o_614 en 18 Febrero 2014, 16:12 PMUna ú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:
#include <stdio.h>
#include <stdlib.h>

int fn(char *p);

int main(void)
{
   char pal[][4] = {
      "X]",
      "X}",
      "Y]",
      "Z]",
      "SP]",
      "XY]",
      "PC]",
      "PC)"
   };
   int i;
   int num_pals = (int) (sizeof pal / sizeof pal[0]);
   
   for (i = 0; i < num_pals; i++)
      printf("%s ==> %s\n", pal[i], fn(pal[i]) ? "OK" : "ERROR");
   
   return EXIT_SUCCESS;
}

int fn(char *p)
{
   char a[2];
   char b[2];

   return sscanf(p, "%1[XY]%1[]]", a, b) == 2 || sscanf(p, "SP%1[]]", b) == 1 || sscanf(p, "PC%1[]]", b) == 1;
}


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


Un saludo
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

m@o_614

#7
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:

void direccionamientoIndexado(char *operando)
{
   int i;
   char *cadena = NULL,c[2];
   cadena = calloc(2,sizeof(char));
   for(i = 3;operando[i] != ']';i++)
   {
       sprintf(c,"%c",operando[i]);
       strcat(cadena,c);
       printf("%s",cadena);
   }
}


de antemano gracias