Autor Tema: formateo con printf  (Leído 5676 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
formateo con printf
« 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.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: formateo con printf
« Respuesta #1 en: 03 de Enero de 2009, 17:04:00 »
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.
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: formateo con printf
« Respuesta #2 en: 03 de Enero de 2009, 17:13:52 »
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.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Re: formateo con printf
« Respuesta #3 en: 03 de Enero de 2009, 18:00:53 »
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.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: formateo con printf
« Respuesta #4 en: 03 de Enero de 2009, 18:43:40 »
Hola

Una pregunta, ¿cómo declaraste el tipo de variable cadena?

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Re: formateo con printf
« Respuesta #5 en: 03 de Enero de 2009, 20:26:01 »
La declaracion es:

char *cadena[30];

¿esta mal? estoy utilizando este mismo array para otros propositos y no me da problemas de ningun tipo.

Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: formateo con printf
« Respuesta #6 en: 03 de Enero de 2009, 22:33:39 »
umm yo lo declararía así sabiendo que solo usaré 29 bytes más el null char:

Código: [Seleccionar]
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?

Desconectado jfh900

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: formateo con printf
« Respuesta #7 en: 03 de Enero de 2009, 22:50:00 »
Yo probaría:

sprintf(*cadena,"Vel: %03f        Alt: %04f ", atof(velocidad_km),atof(altitud));

Un saludo
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Re: formateo con printf
« Respuesta #8 en: 04 de Enero de 2009, 08:04:28 »
umm yo lo declararía así sabiendo que solo usaré 29 bytes más el null char:

Código: [Seleccionar]
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.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado jgpeiro06

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 276
Re: formateo con printf
« Respuesta #9 en: 04 de Enero de 2009, 09:16:08 »
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?
Código: C
  1. char *pcadena[30];
  2. char cadena[30];
  3. pcadena[0] = cadena;
  4. sprintf(*pcadena,"Vel: %03.0f    #: %2u    Alt: %04.0f ", atof(velocidad_km),atoi(satelite),atof(altitud));
  5.  
  6. //o directamente:
  7. char cadena[30];
  8. sprintf(cadena,"Vel: %03.0f    #: %2u    Alt: %04.0f ", atof(velocidad_km),atoi(satelite),atof(altitud));

saludos

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Re: formateo con printf
« Respuesta #10 en: 04 de Enero de 2009, 10:27:01 »
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?
Código: C
  1. char *pcadena[30];
  2. char cadena[30];
  3. pcadena[0] = cadena;
  4. sprintf(*pcadena,"Vel: %03.0f    #: %2u    Alt: %04.0f ", atof(velocidad_km),atoi(satelite),atof(altitud));
  5.  
  6. //o directamente:
  7. char cadena[30];
  8. 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.



Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: formateo con printf
« Respuesta #11 en: 04 de Enero de 2009, 13:57:48 »
Ahora entiendo porqué declaraste un arreglo de punteros, pero pienso que hay una mejor manera de hacerlo.

Código: [Seleccionar]
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:

Código: [Seleccionar]
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

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Re: formateo con printf
« Respuesta #12 en: 04 de Enero de 2009, 17:10:28 »
  :)

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.





Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: formateo con printf
« Respuesta #13 en: 04 de Enero de 2009, 23:33:04 »
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 ' '?

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
Re: formateo con printf
« Respuesta #14 en: 05 de Enero de 2009, 06:54:16 »
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.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P