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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.