Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - rir3760

#961
Algunos comentarios sobre la función actualizada para obtener la representación en cadena:
void Test1(BYTE* array_de_bytes, char* cadena_de_bytes_en_formato_string){ //Cadena de bytes a string
for(int i=0; i<(int)strlen( (char*)array_de_bytes); i++)
strcat(cadena_de_bytes_en_formato_string,hextabla[(int)array_de_bytes[i]]);
printf(cadena_de_bytes_en_formato_string);
printf("\n");
}

Las recomendaciones sobre lo subjetivo (estilo): dale un nombre descriptivo a la función y unos mas cortos a las variables.

Lo objetivo: no es necesario utilizar la función strlen ya que puedes conocer donde termina el array de bytes comparando contra '\0', si te preocupa que alguno de los bytes tenga ese valor entonces debes cambiar de aproximación ya que strlen tendrá el mismo problema. Lo mejor en ese escenario seria pasar el numero de bytes a procesar como un parámetro adicional.

Y si piensas utilizar la función strcat deberías colocar a cero el primer elemento del array "cadena_de_bytes_en_formato_string" (programación defensiva).

Considerando que la posición a procesar de un array define la posición en el otro una alternativa (mas) es utilizar la función sprintf mas aritmética de punteros:
void to_str(const unsigned char *byte, char *str)
{
   int i;
   
   for (i = 0; byte[i] != '\0'; i++)
      sprintf(str + i * 2, "%02X", byte[i]);
}


De nuevo espero se tome de forma constructiva.

Un saludo
#962
Cita de: 85 en 21 Febrero 2013, 01:46 AM
Hola, estaba mirando casualmente dos temas, uno que se refiere al operador ternario y otro sobre como obtener el mayor de 3 números..
Algunas observaciones.

Cuando se busca el máximo de tres números si no es uno de los dos primeros debe ser el ultimo. La primera función se puede reducir a:
int max_valor_de_tres_1(int a,int b,int c)
{
   if (a > b && a > c)
      return a;
   if (b > a && b > c)
      return b;
   
   return c;
}


En la segunda función primero se comparan las variables a y b, el menor de estos debe ignorarse en las siguientes comparaciones ya que no es posible que sea el máximo. Se reduce a:
int max_valor_de_tres_2(int a,int b,int c)
{
   return a > b ? (a > c ? a : c) : (b > c ? b : c);
}


En la tercera función se debe evitar el uso de expresiones como "a - b" porque en el lenguaje C si el resultado de la resta sale del rango valido del tipo int se genera comportamiento no definido, esto es, no hay garantías sobre el comportamiento del programa. Mejor utilizar las comparaciones "a > b", "a > c", etc. ya que son directas y su resultado esta garantizado (1 o 0, dependiendo del resultado de la comparación).

Por ultimo otra opción es combinar el uso de una sentencia condicional y el operador ternario:
int max_tres(int a, int b, int c)
{
   if (a < c)
      a = c;
   
   return a > b ? a : b;
}


Un saludo
#963
Algunos comentarios que espero se tomen como una critica constructiva.

Cuando se utilizan tablas de valores es por eficiencia, para obtener (que mas) un valor en tiempo constante en lugar de realizar una búsqueda.

Dos problemas en tu programa son: en la primera función la tabla no es necesaria porque el byte se puede descomponer utilizando los operadores de división y modulo. En la segunda función la tabla si es necesaria pero no realizas un "lookup", es su lugar realizas una búsqueda secuencial y esta es la de mayor costo (en comparación con otras).

En base a lo anterior el programa se puede reducir a:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

void to_str(void);
void to_char(void);

int main(void)
{
   to_str();
   to_char();
   
   return EXIT_SUCCESS;
}

void to_str(void)
{
   const unsigned char *in = "\x68\x68\x68\x68\x68\x68\xFF\xFF\xFF\xFF\x69";
   int i;

   for (i = 0; in[i] != '\0'; i++){
      putchar("0123456789ABCDEF"[in[i] / 16]);
      putchar("0123456789ABCDEF"[in[i] % 16]);
   }
   putchar('\n');
}

void to_char(void)
{
   unsigned char val[UCHAR_MAX] = {0};
   char digit[] = "0123456789ABCDEF";
   
   char in[] = "686868686868FFFFFFFF69";
   unsigned char out[sizeof in / 2];
   int i;
   
   for (i = 1; digit[i] != '\0'; i++)
      val[digit[i]] = i;
   
   for (i = 0; in[i] != '\0'; i += 2){
      out[i / 2] = val[in[i]] * 16 + val[in[i + 1]];
   }
   
   for (i = 0; i < (int) sizeof out; i++)
      printf("%X", out[i]);
   putchar('\n');
}


Otra opción es utilizar las funciones de la biblioteca estándar de C como sprintf, sscanf, etc.

Un saludo
#964
Por partes.

Cita de: oblivionxor en 19 Febrero 2013, 17:29 PMPor que en arreglos unidimensionales si puedo compilar con el calificador const
Primero porque las funciones no ven en ningún momento un array, cuando de declara una función en la forma:
int fn(int a[]);

/* O */

int fn(int a[N]);

Esta se procesa como si la declaración fuera:
int fn(int *a);
Es por ello que no puede obtenerse el tamaño del array pasado como argumento y tampoco importa indicar el numero de elementos de este, la función simplemente recibe un puntero: la dirección en memoria de su primer elemento.

Segundo por que a una función que espere como argumento un puntero a objeto constante (tipo "const T *") puede pasarse un puntero sin el calificador const (tipo "T *") sin ningún problema: la conversión implícita de un tipo a otro ("T *" ==> "const T *") se aplica de forma transparente salvo una excepción.

Un ejemplo para explicar de una forma mas clara los dos puntos anteriores:
#include <stdio.h>
#include <stdlib.h>

int suma(const int *valor, size_t num_elem);

int main(void)
{
   int valor[] = {1, 2, 3};
   size_t num_elem = sizeof valor / sizeof valor[0];
   
   printf("Suma == %d\n", suma(valor, num_elem));
   
   return EXIT_SUCCESS;
}

int suma(const int *valor, size_t num_elem)
{
   size_t i;
   int total;
   
   total = 0;
   for (i = 0; i < num_elem; i++)
      total += valor[i];
   
   return total;
}


Cita de: oblivionxor en 19 Febrero 2013, 17:29 PMy en los bidimensionales no?
Porque la excepción son los "arrays bidimensionales".

Aquí un paréntesis: C no tiene punteros "dobles", "triples", etc. como tampoco arrays "unidimensionales", "bidimensionales", etc. solo tiene punteros y arrays. Que el tipo apuntado sea también un puntero o el elemento del array un array es otra historia.

Cuando se pasa un array de arrays como argumento de una función esta recibe la dirección de su primer elemento, si el tipo del array es "T [N][M]" la función recibe un puntero de tipo "T (*)[M]".

Y aquí la conversión implícita "T *" ==> "const T *" falla porque el calificador const no se aplica al array, se aplica a sus elementos. Es por ello que tu compilador genera el mensaje de tipos distintos:
CitarArreglosBidimensionales.c:5:6: note: expected 'const int (*)[3]' but argument is of type 'int (*)[3]'

La única solución es declarar al array utilizando const o bien realizar la conversión explicita en la llamada a función.

Un saludo
#965
Cita de: Stakewinner00 en 21 Febrero 2013, 20:12 PMuna pregunta, por que no cambias esto
using std::cout;
using std::cin;
using std::endl;


por esto
using namespace std;

+

Cita de: Stakewinner00 en 21 Febrero 2013, 20:55 PMya lo sé, por eso digo que es igual. Pero en lo del using namespace no hay otra.
En C++ se evita el conflicto de nombres mediante los namespaces. Al utilizar "using namespace::std;" todo el namespace std se vuelca en el global: lo que quieres y lo que no.

En mi caso prefiero utilizar sentencias "using std::nombre;" por dos razones: 1) como refuerzo al aprender las facilidades cortesía de cada encabezado y 2) porque solo se incluye lo necesario.

Una pagina relacionada (pero en ingles) es: C++ FAQ: [27.5] Should I use using namespace std in my code? .

Un saludo
#966
Programación C/C++ / Re: Variable Char a BYTE
21 Febrero 2013, 17:26 PM
Cita de: Bullweiser en 21 Febrero 2013, 15:57 PM
Ya lo he solucionado usando sscanf   ;)

sscanf (cadena,"%x",strHex);
Esa llamada a funcion no hara lo esperado, el problema es el siguiente: sscanf consumira todos los caracteres de la cadena y en base a ellos almacenara un solo numero en la dirección indicada por "strHex".

Para realizar la operación que mencionas se debe utilizar un bucle y en la llamada a función especificar la anchura de campo, esto es, el máximo de caracteres a procesar con (en tu caso) "%Nx". El ultimo paso en el cuerpo del bucle (y ello depende de tu programa) es almacenar el numero obtenido en el array de bytes.

Un programa de ejemplo:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   char *p = "0011223344556677AABBCCDD";
   unsigned num;
   int nc;
   
   while (sscanf(p, "%2x%n", &num, &nc) == 1){
      printf("%.*s ==> %3u == %2X\n", nc, p, num, num);
      p += nc;
   }
   
   return EXIT_SUCCESS;
}


Y su salida es:
00 ==>   0 ==  0
11 ==>  17 == 11
22 ==>  34 == 22
33 ==>  51 == 33
44 ==>  68 == 44
55 ==>  85 == 55
66 ==> 102 == 66
77 ==> 119 == 77
AA ==> 170 == AA
BB ==> 187 == BB
CC ==> 204 == CC
DD ==> 221 == DD


Un saludo
#967
El primer error es:
Citar1>c:\documents and settings\administrador\mis documentos\visual studio 2010\projects\dellibro\dellibro\librocalificaciones.cpp(27): error C2659: '=' : función como operando izquierdo
Y se debe a que declaras "nombreCurso" como una función:
Código (cpp) [Seleccionar]
private:
string nombreCurso();

Hay que quitar los paréntesis.

Un saludo
#968
Cita de: Khronos14 en 19 Febrero 2013, 14:21 PM
en muchos libros recomiendan no utilizarlo porque hace más confusa la sintaxis del código. Por eso muchos libros tan solo lo mencionan o lo pasan por alto, como el goto.
Si se utiliza con sentido común el operador ternario hace mas fácil el seguimiento del código fuente. Las buenas costumbres recomiendan enfatizar la selección: de un valor con ese operador y de una sentencia o bloque mediante las sentencias condicionales.

Cita de: Miky Gonzalez en 19 Febrero 2013, 17:30 PMCreo que no se necesita mucha programacion con este condicional (ternario), tan solo un poco de practica:
if (Numero > 2) return 0;
else return 1;

Esto es lo mismo que:
(Numero > 2) ? return 0 : return 1;
No. Ese operador requiere de dos expresiones como sus operandos y del mismo tipo o uno compatible, una sentencia de retorno como "return 1" no lo es. Para que sea valida hay que cambiarla a:
return (Numero > 2) ? 0 : 1;

Cita de: bemone en 19 Febrero 2013, 22:07 PM
Yo lo uso mucho para hacer funciones de 1 sola linea.

Por ej:
Código (cpp) [Seleccionar]
bool esPar(int a){
    return a%2 == 0 ? true : false;
}
No es un buen ejemplo ya que el resultado de los operadores relacionales es uno si se cumple la condición y cero en caso contrario. Y cuando se convierte un entero a booleano los valores distintos de cero resultan en true, solo cero resulta en false. Considerando eso la función se reduce a:
Código (cpp) [Seleccionar]
bool esPar(int a){
    return a % 2 == 0;
}


Un saludo
#969
Cita de: BatchianoISpyxolo en 17 Febrero 2013, 20:42 PMAhora lo que no tengo claro es que tú pides el tamaño del array al usuario... y, ¿reservamos la memoria estática en tiempo de ejecución? Supongo que será posible...
Una declaracion similar a esta:
int num_elem;

/* Asignacion de algun valor a num_elem */

int valor[num_elem];

Es valida o no dependiendo del estandar de C utilizado al compilar el programa:

A) En C90 no es posible.
B) En C99 si es valida (Array de longitud variable o VLA).
C) En C11 es (Ouch!) opcional.

Ni modo, asi es la vida ...

Un saludo
#970
Algunos comentarios:

* Los elementos de un array pueden inicializarse mediante una lista de valores, si cada elemento es a su vez un array (como es tu caso) se deben utilizar listas anidadas, de esta forma:
int M[2][12] = {
   {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5},
   {0, 3, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6}
};


* El operador lógico AND tiene mayor prioridad que el operador lógico OR, por ello en esta expresión los paréntesis son superfluos (con o sin ellos el resultado es el mismo):
a%4 ==0 && a%100!=0 ||  (a%400==0)

* El resultado de los mentados operadores es uno si se cumple la condición y cero en caso contrario, en base a ello si revisamos el condicional:
if (a%4 ==0 && a%100!=0 ||  (a%400==0))
   M_=M[1][mes_-1];
else
   M_=M[0][mes_-1];

Este se puede reducir a:
M_ = M[a%4 == 0 && a%100 != 0 || a%400 == 0][mes_-1];
Y (al gusto de cada quien) se puede sustituir el uso del operador "==" por paréntesis y el operador de negación "!".

Un saludo