smartes printf

OP Persönliche Seite #426509
Lesenswert?

Hi Leutz,

wen's interessiert, ich hab ein minimales printf geschrieben.

Aufruf und Parameterliste wie printf, im Moment werden aber nur:

%i (6 Stellen, kann jeder selber erweitern)
%c
%s

sowie

\n
\t

unterstützt.

Mein Projekt ist damit um ca. 5k kleiner geworden, mein printf braucht 
(keil-compiler) <300k

Bleibt nur noch der retarget auf welches IO auch immer. Ich habe fürs 
retargeting an der fputc angesetzt, diese schreibt auf den UART. Für 
dieses printf hab ich die einfach weiterverwendet, man kann aber auch 
was eigenes statt der fputc einbauen, was z.B. auf den uart schreibt.



Viel Spass damit!

Anregungen und konstruktive Kritik erwünscht ;-)
Anmerkung: Dies ist die erste Version g


---------------
Header:

#ifndef _THPRINTF_H_
#define _THPRINTF_H_


int thprintf(char *string, ...);

#endif



C-File:



// Th printf

/*
Author: Thorsten de Buhr
mail: thorsten@lasertechnix.de

Use:
Use is free, could run or not ;-)

U may change every printf in cour code to thprintf, the rest is the 
same.

U may use:
%i, %s, %c
\n, \t

More is not implemented now.

Have fun with this very small print-function, it uses ~300 bytes of code 
(printf uses >5k!)

*/

#include <stdarg.h>
#include "../src/main.h"
#include "../src/thprintf.h"





int thprintf(char *string, ...)
{
  va_list tag;
  int pointer=0, num_avaiable=0,  i=0, j=0;
  char char_parse=0, *char_pointer=0;
  signed int int_tmp=0, int_tmp2=0;

  va_start(tag, string);

  do
  {
    char_parse = string[pointer];    // get char


    if(char_parse == '%')
    {
      pointer++;
      char_parse = string[pointer];

      switch(char_parse)
      {
        case 'i':
        {
          int_tmp = va_arg(tag, int);
          num_avaiable=0;
          j=1000000;

          if(int_tmp <0)
          {
            fputc('-', 0);
            int_tmp*=(-1);
          }

          for(i=6; i>0; i--)
          {
            j/=10;
            int_tmp2 = int_tmp / j;
            if((int_tmp2) || (num_avaiable))
            {
              num_avaiable=1;
              fputc(((int_tmp2))+48, 0);
              int_tmp%=j;
            }
          }
          if(!num_avaiable) fputc('0', 0);    // Null ausgeben


        } break;

        case 'c':
        {
          fputc((char)va_arg(tag, int), 0);

        }break;

        case 's':
        {
          char_pointer = va_arg(tag, char*);

          while(*char_pointer)
          {
            fputc(*char_pointer, 0);
            char_pointer++;
          }
          break;

        }
      }
    } // end if '%'

    else if(char_parse == '\\')
    {
      pointer++;
      char_parse = string[pointer];

      switch(char_parse)
      {
        case 'n': fputc('\n', 0);
          break;

        case 't': fputc('\t', 0);
          break;
      }
    } // end if '\'


    else fputc(char_parse, 0);
    pointer++;

  } while(char_parse);

  va_end(tag);

  return(0);
}

OP Persönliche Seite #427008
Lesenswert?

Hi Leutz,

mittlerweile bin ich auf 256 Bytes runter...

#include <stdarg.h>
#include "../src/main.h"
#include "../src/thprintf.h"

int thprintf(char *string, ...)
{
  va_list tag;
  int i=0;
  char *pointer=0;
  signed int int_tmp=0;

  va_start(tag, string);

  do
  {
    if(*string == '%')
    {
      switch(*(++string))
      {
        case 'i':
        {
          int_tmp = va_arg(tag, int);
          pointer=(void*)0;  //Pointer as marker

          if(int_tmp <0)
          {
            fputc('-', 0);
            int_tmp*=(-1);
          }

          for(i=MAX_NUM_DEC; i; i/=10)
          {
            if((int_tmp/i) || (pointer))
            {
              pointer=(void*)1;
              fputc((int_tmp/i)+48, 0);
              int_tmp%=i;
            }
          }
          if(!(pointer)) fputc('0', 0);    // Null ausgeben (Zahl = 0)

        } break;

        case 'c':
        {
          fputc((char)va_arg(tag, int), 0);
        } break;

        case 's':
        {
          pointer = va_arg(tag, char*);

          do
          {
            fputc(*pointer, 0);
          } while(*pointer++);
          break;
        }
      }
    } // end if '%'

    else if(*string == '\\')
    {
      switch(*(++string))
      {
        case 'n': fputc('\n', 0);
          break;

        case 't': fputc('\t', 0);
          break;
      }
    } // end if '\'

    else fputc(*string, 0);

  } while(*(++string));

  va_end(tag);

  return(0);
}


------------------------------------------------------------------------

Hab versucht, das noch weiter zu schrumpfen, bin dabei aber leider 
wieder auf 292 bytes gekommen.
Aber ich find die Lösung so böse-lustig, dass ich sie hier 
veröffentlichen möchte:

#include <stdarg.h>
#include "../src/main.h"
#include "../src/thprintf.h"

int thprintf(char *string, ...)
{
  va_list tag;
  int i=0;
  int *pointer=0;

  va_start(tag, string);

  do
  {
    if(*string == '%')
    {
      switch(*(++string))
      {
        case 'i':
        {
          //int_tmp = va_arg(tag, int);
          *pointer = va_arg(tag, int);

          if(*pointer <0)
          {
            fputc('-', 0);
            (*pointer)*=(-1);
          }

          // führende Nullen abtrennen
          for(i=MAX_NUM_DEC; i; i/=10)
            if(*pointer/i) break;


          for(; i;)
          {
            if((*pointer/i))
            {
              fputc((*pointer/i)+48, 0);
              *pointer%=i;
            }
            else fputc('0', 0);
            i/=10;
          }

        } break;

        case 'c':
        {
          fputc((char)va_arg(tag, int), 0);
        } break;

        case 's':
        {
          pointer = (int*) va_arg(tag, char*);

          do
          {
            fputc(*pointer, 0);
          } while(*pointer++);
          break;
        }
      }
    } // end if '%'

    else if(*string == '\\')
    {
      switch(*(++string))
      {
        case 'n': fputc('\n', 0);
          break;

        case 't': fputc('\t', 0);
          break;
      }
    } // end if '\'

    else fputc(*string, 0);

  } while(*(++string));

  va_end(tag);

  return(0);
}


Vllt sind für den ein oder anderen ein paar anregungen drin.


Greetz,
Th.

PS: Ich liebe solche spielchen mit C ;-)
Nu bin ich erst mal am ende ... hat jemand lust, weiterzumachen ? Her 
damit grins
OP Persönliche Seite #427189
Lesenswert?

So,

vorläufige Endversion.
180Byte ROM und 4Byte RAM mit Keil (-O3, oben war -O0).


// Th printf

/*
Author: Thorsten de Buhr
mail: thorsten@lasertechnix.de

Use:
Use is free, could run or not  ;-)

U may change every printf in cour code to thprintf, the rest is the 
same.

U may use:
%i, %s, %c
\n, \t

More is not implemented now.

*/

#include <stdarg.h>
#include "../src/main.h"
#include "../src/thprintf.h"





int thprintf(char *string, ...)
{
  va_list tag;
  int i=0;
  int *pointer=0;
  signed int int_tmp=0;


  va_start(tag, string);

  do
  {
    if(*string == '%')
    {
      switch(*(++string))
      {
        case 'i':
        {
          int_tmp = va_arg(tag, int);

          if(int_tmp <0)
          {
            fputc('-', 0);
            int_tmp=-int_tmp;
          }


          pointer = (int*)int_tmp;
          for(i=MAX_NUM_DEC; i; i/=10)
          {

            if((int)pointer/i)
            {
              fputc((int_tmp/i)+48, 0);
              int_tmp%=i;
            }
          }
        } break;

        case 'c':
        {
          fputc((char)va_arg(tag, int), 0);
        } break;

        case 's':
        {
          pointer = (int*)va_arg(tag, char*);

          do
          {
            fputc(*pointer, 0);
          } while(*pointer++);
        } break;
      }
    } // end if '%'

    else if(*string == '\\')
    {
      switch(*(++string))
      {
        case 'n': fputc('\n', 0);
          break;

        case 't': fputc('\t', 0);
          break;
      }
    } // end if '\'

    else fputc(*string, 0);

  } while(*(++string));

  va_end(tag);

  return(0);
}


Greetz,
th.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren