TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: xerex en 03 de Enero de 2009, 16:44:28
-
Buenas,
Tengo el siguiente problema, y esta en este codigo:
sprintf(*cadena,"Vel: %3.0f Alt: %4.0f ", atof(velocidad_km),atof(altitud));
El problema se crea porque en altitud cuando paso de 4 a 3 digitos (idem 3 a 2) , sprintf me formatea a la izquierda y me deja un digito a la derecha. Comentaros que da igual pasarlo como string, como integer o como lo que este, da lo mismo el paso de estas variables, siempre hace lo mismo.
Mi pregunta es:
Segun C para formarear a la derecha deberia de poner Alt: %-4.0f , poner el "-" pero....¿como se hace en ccs?
Muchas gracias .
Saludos.
-
No es exactamente lo que preguntas pero puedes hacer que se alineen a la derecha añadiendo ceros no significativos por la izquierda, al menos podrás tener siempre los mismos dígitos en las mismas posiciones relativas en el resultado *cadena
sprintf(*cadena,"Vel: %03.0f Alt: %04.0f ", atof(velocidad_km),atof(altitud));
Prueba con esto a ver si te funciona.
-
No debería alinear los números por la izquierda si haces esto
Vel: %3.0f Alt: %4.0f
Algo raro está pasando porque eso fuerza a que Vel ocupe 3 dígitos alineados por la derecha y Alt 4 igualmente.
-
hola,
Gracias por la rapida respuesta,
la utilizacion de %04f ya lo he hecho (he leido otro post de un compañero de aqui) pero sigue igual, he probado todo lo que se me ha ocurrido y he leido por ahi, por eso ha sido mi ultima opcion el ponerlo como post.
Si finalmente no hay otra opcion, tendre que tratar los datos manualmente.
Saludos.
-
Hola
Una pregunta, ¿cómo declaraste el tipo de variable cadena?
-
La declaracion es:
char *cadena[30];
¿esta mal? estoy utilizando este mismo array para otros propositos y no me da problemas de ningun tipo.
-
umm yo lo declararía así sabiendo que solo usaré 29 bytes más el null char:
char cadena[30];
Y recuerdo que había detalles o problemas con el %f de ccs, ¿puedes poner ejemplos de cómo entran y salen los datos?
-
Yo probaría:
sprintf(*cadena,"Vel: %03f Alt: %04f ", atof(velocidad_km),atof(altitud));
Un saludo
-
umm yo lo declararía así sabiendo que solo usaré 29 bytes más el null char:
char cadena[30];
Y recuerdo que había detalles o problemas con el %f de ccs, ¿puedes poner ejemplos de cómo entran y salen los datos?
Bueno lo he solucionado de una manera un poco "chapuza" pero me funciona y no consumo mucho codigo, lo que hago es ademas de indicar a sprintf %04.0f que es lo que me habiais indicado (que esto no me funciona :shock:), borro el string velocidad y altitud (dejo todo a ' '), asi siempre lo construyo desde un array limpio (podria tener que ver con estos strings el problema, pero se construyen siempre de la misma manera ya que recogo los datos de otro dispositivo via RS232 y solo me da error la variable altitud ¿?)
El codigo de sprintf queda asi (perdonar por añadir una variable que no estaba, al solucionarlo, he continuado picando codigo):
sprintf(*cadena,"Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km),atoi(satelite),atof(altitud));
MIGsantiago, necesito que cadena sea un array de punteros a char, por eso esa definicion, ese string lo utilizo en multitud de funciones y no puedo modificarlo porque me daria problemas. Realmente utilizo los 30 caracteres, osea todo el array, por ahi no viene el problema, ya que he probado tambien a modificar la posicion del array altitud dentro del string cadena con el mismo resultado, y ademas cadena siempre entra limpia a sprintf porque como comentaba lo utilizo como "comodin" en otras funciones. ¿que necesitas saber? ¿el string que recogo y como lo añado a las variables altitud y velocidad?
jfh900, lo use y no me funciono...... no se el porque.
Gracias, Saludos.
-
A mi no me cuadra lo de declarar char *cadena[30], de esta manera tienes 30 PUNTEROS a variables tipo char. cada puntero ocupa 2 bytes en memoria.
la funcion sprintf tiene la forma int sprintf(char *cadena, const char *formato, ...); asi que si le pasas *cadena, creo que le estas pasando *cadena[0]. Si cadena[0] == &cadena[0], el mensaje formateado se escribirá sobre los punteros y esto puede suponer algun error.
en tu codigo, ¿que valor almacenas en cadena[0] antes de llamar a la funcion sprintf?
¿Has probado a hacer lo siguiente?
char *pcadena[30];
char cadena[30];
pcadena[0] = cadena;
sprintf(*pcadena
,"Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km
),atoi(satelite
),atof(altitud
));
//o directamente:
char cadena[30];
sprintf(cadena
,"Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km
),atoi(satelite
),atof(altitud
));
saludos
-
A mi no me cuadra lo de declarar char *cadena[30], de esta manera tienes 30 PUNTEROS a variables tipo char. cada puntero ocupa 2 bytes en memoria.
la funcion sprintf tiene la forma int sprintf(char *cadena, const char *formato, ...); asi que si le pasas *cadena, creo que le estas pasando *cadena[0]. Si cadena[0] == &cadena[0], el mensaje formateado se escribirá sobre los punteros y esto puede suponer algun error.
en tu codigo, ¿que valor almacenas en cadena[0] antes de llamar a la funcion sprintf?
¿Has probado a hacer lo siguiente?
char *pcadena[30];
char cadena[30];
pcadena[0] = cadena;
sprintf(*pcadena
,"Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km
),atoi(satelite
),atof(altitud
));
//o directamente:
char cadena[30];
sprintf(cadena
,"Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km
),atoi(satelite
),atof(altitud
));
saludos
¿2 bytes ocupa? pensaba que ocupaba 1 byte cada char y que el puntero apunta a la direccion de memoria del char que se le asigna, ademas si hiciera mal la asignacion, me saldria todo el array mal, y solo tengo problemas con las variables de entrada...... seguramente lleves razon, no soy muy amigo de los punteros :? , con respecto a la cantidad de memoria, no me preocupa de momento , ya que estoy al 50% del micro y no creo que suba mucho mas.
cadena[0] a cadena[29] esta todo a ' '. A eso me refiero cuando "limpio" el array.
Si no recuerdo mal, sprintf escribe hasta el ultimo caracter que le indiquemos en el segundo parametro, en este caso:
"Vel: %03.0f #: %2u Alt: %04.0f "
el segundo parametro construido para que no pase mas de 30 caracteres, por lo que no escribire en ningun otro lado.
Saludos.
-
Ahora entiendo porqué declaraste un arreglo de punteros, pero pienso que hay una mejor manera de hacerlo.
char cadena[30]; //declara una cadena de 29 caracteres más su null char
char variable;
int8 pos_ram;
sprintf(cadena, "Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km), atoi(satelite), atof(altitud));
//El sprintf arma la cadena normalmente sin usar puntero a cadena (ya que cadena sin índice ya es puntero)
//Para acceder a cada char de la cadena solo hay que apuntarlo con un índice
variable=cadena[0]; //primer char de la cadena
variable=cadena[15]; //char en la posición 16 de la cadena
//Para obtener la dirección ram de un char contenido en la cadena
pos_ram=&cadena[0]; //dir. ram del primer char de la cadena
pos_ram=&cadena[15]; //dir. ram del char 16 de la cadena
Para limpiar una cadena solo hay que poner su primer char con un NULL char:
cadena[0]=NULL;
De esa forma cualquier función que manipule cadenas se detendrá al encontrar el NULL char desde el principio.
El poner el código ' ' significa insertar un Espacio en ese char, lo que se interpreta como un ascii 0x20. Debes ser cuidadoso al armar cadenas; siempre deben llevar un NULL char (0x00) para indicar dónde termina la cadena.
¿Cómo entran y salen los datos? Por ejemplo:
Entran:
velocidad="5.1";
satelite="3";
altitud="0.9";
Después del sprintf salen:
Vel: 005.1 #:3 Alt:0000.9
¿En qué formato tienes problemas? :o
-
:)
Veamos, el tema es que no es una aplicacion estandar, entonces el declarar un limpio como null, no me vale tampoco.
la informacion que recogo y que formateo con sprintf la envio a un OSD que tiene su propio juego de caracteres y el "null" no es uno de los que tiene, sin embargo ' ' si lo tiene implementado.
sprintf formatea segun lo que le pongamos y hasta el final del const char *formato, por eso esta variable de entrada a sprintf se formatea (en mi caso) siempre de la misma manera y con la misma longitud. Recordando el comenatario de jgpeiro06.... int sprintf(char *cadena, const char *formato, ...)
En cuanto a los datos, entran y salen como pones Migsantiago, de esa manera, incluso ese es el formato.
Pero cuando pasa altitud de 1000 a 999, la cadena indica "Vel: 005.1 #:3 Alt: 9990".
El tema es que ahora antes de decodificar la informacion que me llega via rs232, "limpio" las variables y asigno la informacion correspondiente, de esta manera me esta funcionando... en principio, no seria necesario. ... :)
No se si alguna funcion por debajo me estaria haciendo estragos pero con el "trapi" que he hecho parece que funciona en todos los casos :)
Gracias a todos.
Saludos.
-
Qué bien que ya tienes resuelto el problema. Otra pregunta, ¿no será que el cero de 9990 es mal interpretado ya que dices que no existe el NULL char? La cadena de sprintf termina en
... 999NULL
Al usar sprintf se inyecta un NULL al final de la cadena, borrando el ' ' que habías puesto. ¿Vuelves a llenar los char del final de cadena con ' '?
-
hola Migsantiago,
Pues... no creo, tendria el mismo problema en velocidad, supongo.
El formato que llega via serie es XXXX.X, aplicando el decimal no deberia de tener ese problema que observas, ademas formateo con 0 decimales. De todas formas lo comprobare y revisare las tramas de llegada por si fuera un bug de alguna funcion de decodificacion.
Saludos.
-
....
char cadena[30]; //declara una cadena de 29 caracteres más su null char
char variable;
int8 pos_ram;
sprintf(cadena, "Vel: %03.0f #: %2u Alt: %04.0f ", atof(velocidad_km), atoi(satelite), atof(altitud));
//El sprintf arma la cadena normalmente sin usar puntero a cadena (ya que cadena sin índice ya es puntero)
//Para acceder a cada char de la cadena solo hay que apuntarlo con un índice
variable=cadena[0]; //primer char de la cadena
variable=cadena[15]; //char en la posición 16 de la cadena
//Para obtener la dirección ram de un char contenido en la cadena
pos_ram=&cadena[0]; //dir. ram del primer char de la cadena
pos_ram=&cadena[15]; //dir. ram del char 16 de la cadena
Para limpiar una cadena solo hay que poner su primer char con un NULL char:
cadena[0]=NULL;
De esa forma cualquier función que manipule cadenas se detendrá al encontrar el NULL char desde el principio.
El poner el código ' ' significa insertar un Espacio en ese char, lo que se interpreta como un ascii 0x20. Debes ser cuidadoso al armar cadenas; siempre deben llevar un NULL char (0x00) para indicar dónde termina la cadena.
....
el uso de NULL me ha sido útil para resolver una problema que se me venía presentando al imprimir arrays
en mi ejemplo declaraba un arreglo tipo char
char variable[15];
...
printf("%s\r\n", variable);
...
el resultado de printf era impredecible, puesto que la cadena resultante pasaba de 15. La solución fue añadir el NULL
char variable[16];
variable[15]=NULL;
...
printf("%s\r\n", variable);
...
...
printf("%s\r\n", variable);
...