Implementando Printf

Software e Hardware para ATMEL

Moderadores: 51, guest2003, brasilma

Implementando Printf

Mensagempor brasilma » 06 Ago 2008 22:40

Sei que isto para quem é iniciado em C deve ser de uma imbecilidade tremenda, mas para mim é ???; resolvendo essas dúvidas vou aprendendo muitas coisas que depois consigo aplicar de várias formas, então vamos lá.

Não entrem na minha achando que o que estou perguntando é dificil, sou ZERO em C mesmo, ok?

Como fazer para passar para uma função uma string com tamanho variável?

Tendo sido recebida esta string pela função, como calculo o comprimento da mesma?

Como posso pegar cada uma das letras?

Como determino o código ascii de cada uma destas letras?

Desde já obrigado pela paciência!!!

Abraços.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor msamsoniuk » 06 Ago 2008 23:50

dah um zoio no que eu uso:

http://framework.sourceforge.net/hc908s ... ll/shell.c

tem um e outro bug ou deficiencia, claro, mas jah quebra o galho neh ?

essas rotinas jah foram testadas nos hc908 com sdcc, pic com sdcc, x86 e 68k com gcc e 320lf2402 com code composer. no dsp, por sinal, a stack eh ao contrario, acho que tem q inverter os *p++ lah.
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Re: Implementando Printf

Mensagempor Maurício » 07 Ago 2008 00:51

Ufa! Pensei, pelo título, que vc queria CRIAR a sua própria função PRINTF! ehehehehehe

brasilma escreveu:Como fazer para passar para uma função uma string com tamanho variável?


Pelo ponteiro. Passa o ponteiro da string pra função.

Código: Selecionar todos
void trata_string (char *string)


Tendo sido recebida esta string pela função, como calculo o comprimento da mesma?


Utilizando a função STRLEN, da biblioteca STRING.H

Código: Selecionar todos
#include <string.h>

void main ( void )
{
    char mensagem[] = "Minha String";
    int comprimento = 0;

    comprimento = strlen ( mensagem );    //atribui à "comprimento", o tamanho da string MENSAGEM
     while ( 1 );
}


Como posso pegar cada uma das letras?


Não existe string em C! O que existe é um vetor de caracteres (bytes). Se é um vetor, cada elemento desse vetor pode ser endereçado diretamente, assim:

Código: Selecionar todos
#include <string.h>

void main ( void )
{
    char mensagem[] = "Minha String";
    char caractere_string;

    caractere_string = mensagem[4];    // caractere "a"
    caractere_string = mensagem[0];    // caractere "M"
    caractere_string = mensagem[8];    // caractere "r"
    caractere_string = mensagem[11];    // caractere "g"

     while ( 1 );
}


Como determino o código ascii de cada uma destas letras?


Se vc pegar o caractere no vetor, como acima, sendo uma STRING, ele já devolve o valor ASCII.

Desde já obrigado pela paciência!!!


Não por isso! Tú vai ver o tamanho da conta, depois! eheheheheh

[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor brasilma » 07 Ago 2008 09:06

Obrigado mais uma vez pela ajuda Marcelo e Maurício, vou "digerir" e testar estas informações e qualquer coisa grito de novo.

(Putz já pensou desenvolver uma função Printf de verdade, ainda mais quem (eu), rs, rs)

Pôe na conta do Dantas, que esse tem "bala na agulha", rs, rs

Valeuzzzzzzzzzzzzzzzzzzzzzzzzz!!!
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor barboza » 08 Ago 2008 12:58

Só um complemento e minha opinião sobre o printf.

Em C uma string é definida como sendo um seqüencia de caracteres (vetor) que termina ao encontrar um caracter nulo ('\0' = 0x00).

Sobre o uso do printf, eu já fiz uma para escrever em em LCD.
Sei que poderia alterar a função putchar para o enviar ao LCD, ou usar o sprintf para converter e enviar os dados convertidos.

A diferença que dependendo do compilador que você usa, ao incluir e fazer uso da biblioteca padrão e a função printf por exemplo, será alocado memória para todas as opções previstas, como impressão de inteiros, números hexadecimais, float, ......, sendo que você quer muitas vezes só imprimir uma data e hora e alguma medida que são decimais simples.

Neste caso, como foi o meu, vale muito a pena construir sua função printf e deixa-la de acordo a sua necessidade.

Mas claro, tudo isso é a velha estória do custo x beneficio.
Se o problema é espaço em ROM, faça a sua, se for tempo, usa o padrão quando puder.

Só para ficar a dica e a informação, segue uma função que fiz a uns 3 anos para rodar no 8051.




Código: Selecionar todos
/*************************************************************************
   FUNCAO:      MsgTemp
   PARAMETROS: msg, e valores dos parâmetros
   RETORNO:   NENHUM
   DESCRICAO:   MOSTRA MENSAGEM TEMPORIZADA COM O TEMPO TEMPO_MSG_TMP
   OBS:      PARAMETROS ACEITOS:
   '\f'   -   LIMPA TODA A TELA;
   '%d'   -   IMPRIME O NUMERO PASSADO EM DECIMAL, COM 2 OU 3 CASAS;
            IMPRIME COM 3 CASAS SE O NUMERO FOR MAIOR QUE 99;
   '%s'   -   IMPRIME A STRING PASSADA ATÉ ENCONTRAR UM CARACTER NULO;
   '%'      -   IMPRIME O CARACTER '%'.
**************************************************************************/
void   MsgTemp   (byte code *msg, ...)
{
va_list   param;         // Lista de parâmetros
byte   byte_temp;

   va_start(param, msg);             // Inicia o ponteiro da lista de parâmetros
   
   while (*msg)
   {
      if (*msg == '\f')
         wrLCDcom ( CLRDSP );                                 // Limpa a tela
      else
      if (*msg == '%')
      {
          msg++;
         if (*msg == 'd')
         {
            byte_temp = va_arg(param, byte);
            if (byte_temp / 100) wrLCDdata( HexaAscii(byte_temp / 100) );      // Se numero maior de 100 escreva com 3 casas.
            wrLCDdata( HexaAscii( (byte_temp % 100) / 10) );             // Senão escreva com 2.
            wrLCDdata( HexaAscii(byte_temp % 10) );                  // Senão escreva com 2.
              }
         else
         if (*msg == 's')
         {
         byte   *ptr_str = va_arg(param, byte *);               // Defina um ponteiro para acesso a string

            while (*ptr_str)
               wrLCDdata(*ptr_str++);
              }
         else
            wrLCDdata('%');                                 // % sozinho
      }
      else
         wrLCDdata(*msg);                                 // Imprima o caracter

      msg++;
   }

   va_end (param);                // Finaliza o ponteiro da lista de parâmetros

   tmp_tela_tmp = TEMPO_MSG_TMP;
   flag_espera_tela = TRUE;
}
Os homens mentiriam muito menos se as mulheres fizessem menos perguntas.
Avatar do usuário
barboza
Word
 
Mensagens: 948
Registrado em: 17 Out 2006 13:42
Localização: Longe de onde gostaria de estar

Mensagempor RobL » 08 Ago 2008 13:31

Complementando o complemento do Barbosa, para quem está praticando C, cabe lembrar que em um microcontrolador nossa escrita será quase sempre em cima de bits e uma memoriazinha, e quase nunca sobre um CRT, HD, arquivos, etc.
Por exemplo, ao usar essa função printf em um excelente compilador como o AVR-GCC, de forma descuidada, podemos ocupar mais de 1500 linhas de programa para escrever nada. Outros compiladores para micro limitam as possibilidades dessas funções.
Isto é válido tabém para o uso indiscriminado de structs que devem sermpre que possível usar union e outras, ou novamente, escrever sua função para cada caso.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor brasilma » 08 Ago 2008 19:11

Beleza Barboza,

A rotina que estou fazendo é para um GLCD e precisa mesmo ser personalizada de acordo com o meu projeto.

Este detalhe do consumo de memória tbem conta muito.

Abraços.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor Maurício » 08 Ago 2008 20:06

Uau!!!!

Os caras tão criando suas próprias funções, e com entrada de parâmetros variáveis!!! :shock: :shock:

Muito bom!!!!

[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor msamsoniuk » 09 Ago 2008 00:26

pois eh, na implementacao inicial que eu postei nao uso buffers de saida, portanto printf nao usa memoria, mas locka a execucao em funcao da disponibilidade e velocidade da uart.

essa mesma implementacao eu usei com um buffer de saida de 1KB no 68328 (com frame buffer), 4KB no 68340 e 8KB no 5207, simplesmente reimplementando a funcao putchar para imprimir no buffer de um lado (sem delay) enquanto outra rotina ativada por interrupcao esvaziava o buffer pelo outro lado (cadenciada pela velocidade da uart). um colega mais tarde fez uma variacao dessa implementacao com um buffer de 32 bytes no hc908 e outro colega fez uma implementacao realmente incrivel no 5207, usando canais de dma e ring buffers para tx e rx.

exceto por pequenas correcoes e melhorias, a implementacao de printf e outras funcoes de alto nivel ficou identica em todos os casos, apenas putchar e getchar alteradas!
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor brasilma » 12 Ago 2008 11:57

Putz, rs, rs

Estou aprendendo sobre matrizes e ponteiros, a "coisa" é muito poderosa e versátil, ainda falta bastante coisa pra entender.

Com alguns testes consegui chegar na estrutura abaixo, que funciona legalzinha, como o C é poderoso...

uint8_t char_tot;
char_tot = 0;

while(texto[char_tot] != '\0') ++char_tot;

Abraços.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor msamsoniuk » 12 Ago 2008 12:57

opa brasilma!

assim fica mais style:

unsigned char count;

for(count=0;texto[count];count++);
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor brasilma » 12 Ago 2008 13:28

Bom mesmo Marcelo, se continuar assim logo nem vou precisar escrever mais nada, rs, rs
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor RobL » 12 Ago 2008 18:21

É interessante observar que as pessoas que aprendem C, após um bom conhecimento de assembler, ficam fascinadas com o poder de uma linguagem de mais alto nível. Outras nem notam isso.
O curioso é que observa-se que as pessoas não tem problema com endereçamento indireto, em assembler, mas apresentam alguma dificuldade ao lidar com ponteiros em C.
Apesar de se ter um completo domínio da máquina em assembler, a sensação passada por uma linguagem de alto nível é de se escrever em uma linha, várias linhas, passando uma impressão de poder danado.
O outro lado, é que para se ter algum domínio, em C, é necessário não só o domínio da linguagem. Talvez esse seja o lado mais fácil, mas sim ter o domíno do compilador e aí nem sempre é tão fácil, pois nem sempre está disponível para ser estudado.
C para microcontrolador é uma "subclasse do C". Por não terem um OS, Bios, etc, o bicho começa a pegar nas funções de alto nível como printf() que para o iniciante acaba não escrevendo nada, de jeito nenhum, pois cabe ao usuário identificar e escrever a rotina para um certo device.
Como tudo que é bom, tem o seu preço, mas C é fundamental hoje. Só resta estudar.
Nada melhor, para entender o core do funcionamento do C para microcontrolador, como o AVR-GCC.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor brasilma » 12 Ago 2008 19:04

Quando falo "poder" do C em relação ao Assembly, estou querendo dizer: "facilidade", o C é um "facilitador".
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor RobL » 12 Ago 2008 20:01

Apesar de se ter um completo domínio da máquina em assembler, a sensação passada por uma linguagem de alto nível é de se escrever em uma linha, várias linhas, passando uma impressão de poder danado.


Quando escreví acima a palavra impressão, escreví mal, pois não quiz dizer que era só impressão. A melhor palavra seria sensação, com com sentido de sentir algo real, concreto. C é um poder danado sim e também facilitador, após se "pagar pelo preço".

Acima está um exemplo dos piores erros de português, quando a idéia não é comunicada com exatidão.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Próximo

Voltar para AVR

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x