Thread: printf

  1. #1
    Registered User
    Join Date
    Nov 2003
    Posts
    5

    printf

    how do i go about writing my own printf function, so that i do not have to include
    stdio.h
    Last edited by orthanc; 06-22-2004 at 02:54 AM.

  2. #2
    Registered User
    Join Date
    Jun 2004
    Posts
    42

    Smile

    Why do you want to re-write printf? For funny?

  3. #3
    Obsessed with C chrismiceli's Avatar
    Join Date
    Jan 2003
    Posts
    501
    All you need to do is fopen() stdout and once you have the string the way you want it, you write it to that file.
    Help populate a c/c++ help irc channel
    server: irc://irc.efnet.net
    channel: #c

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >how do i go about writing my own printf function
    You first learn how to write a function that takes a variable number of arguments, then you learn how to convert various supported types into strings and write those strings using a lower level function, putchar as one possible option. Then you learn how to process the formatting flags so that your printf will handle more complex formatting than just type conversion. Here's a quick and dirty example, it can be made to be more compact and elegant with a little effort:
    Code:
    #include <ctype.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    void fprint(const char *format, ...);
    
    int
    main(void)
    {
      fprint("|%12d|\n", 45);
      fprint("|%012d|\n", 45);
      fprint("|% 012d|\n", 45);
      fprint("|%+12d|\n", 45);
      fprint("|%+012d|\n", 45);
      fprint("|%-12d|\n", 45);
      fprint("|%- 12d|\n", 45);
      fprint("|%-+12d|\n", 45);
      fprint("|%12.4d|\n", 45);
      fprint("|%-12.4d|\n\n", 45);
    
      fprint("|%12d|\n", -45);
      fprint("|%012d|\n", -45);
      fprint("|% 012d|\n", -45);
      fprint("|%+12d|\n", -45);
      fprint("|%+012d|\n", -45);
      fprint("|%-12d|\n", -45);
      fprint("|%- 12d|\n", -45);
      fprint("|%-+12d|\n", -45);
      fprint("|%12.4d|\n", -45);
      fprint("|%-12.4d|\n", -45);
    
      return 0;
    }
    
    static int
    length(
      int value
      )
    {
      int n = 0;
    
      if (value == 0) {
        return 1;
      }
      while (value) {
        ++n;
        value /= 10;
      }
    
      return n;
    }
    
    static void
    r_write_value(
      int value,
      int n
      )
    {
      /* Assume positive value */
      if (n) {
        r_write_value(value / 10, n - 1);
        if (value) {
          putchar(value % 10 + '0');
        }
        else {
          putchar('0');
        }
      }
    }
    
    static void
    write_value(
      int value,
      int n
      )
    {
      if (value == 0) {
        putchar('0');
      }
      else {
        r_write_value(value, n);
      }
    }
    
    void
    fprint(
      const char *format,
      ...
      )
    {
      va_list     args;
      const char *it;
      int         value;
      int         i;
    
      va_start(args, format);
      for (it = format; *it; it++) {
        if (*it == '%') {
          int left = 0;  /* Left justify */
          int plus = 0;  /* Print sign */
          int zero = 0;  /* Zero padding */
          int space = 0; /* Whitespace sign replacement */
          int field_width = 0; /* Precision before decimal */
          int precision = 0; /* Precision after decimal */
    
          while (*(++it) != 'd') {
            /* Specific flags */
            switch (*it) {
              case ' ': space = 1; break;
              case '+': plus = 1; break;
              case '0': zero = 1; break;
              case '-': left = 1; break;
            }
            /* Precision */
            if (isdigit(*it)) {
              char *save;
              field_width = (int)strtol(it, &save, 10);
              it = save;
              if (*it == '.') {
                precision = (int)strtol(it + 1, &save, 10);
              }
              it = save;
              break;
            }
          }
          value = va_arg(args, int);
          /* Print formatting */
          if (!precision) {
            precision = length(value);
          }
          field_width -= precision;
          if (space || plus || value < 0) {
            --field_width;
          }
          if (!left) {
            if (value < 0) {
              if (!zero) {
                for (i = 0; i < field_width; i++) {
                  putchar(' ');
                }
                putchar('-');
              }
              else {
                putchar('-');
                for (i = 0; i < field_width; i++) {
                  putchar('0');
                }
              }
            }
            else {
              if (space) {
                putchar(' ');
              }
              if (!zero) {
                for (i = 0; i < field_width; i++) {
                  putchar(' ');
                }
                if (plus) {
                  putchar('+');
                }
              }
              else {
                if (plus) {
                  putchar('+');
                }
                for (i = 0; i < field_width; i++) {
                  putchar('0');
                }
              }
            }
            write_value(abs(value), precision);
          }
          else {
            if (value < 0) {
              putchar('-');
            }
            else {
              if (plus) {
                putchar('+');
              }
              else if (space) {
                putchar(' ');
              }
            }
            write_value(abs(value), precision);
            for (i = 0; i < field_width; i++) {
              putchar(' ');
            }
          }
        }
        else {
          putchar(*it);
        }
      }
      va_end(args);
    }
    Also note that this only implements the %d flag, and even then it's not fully functional.

    >so that i do not have to include stdio.h
    That's not really a good reason to write your own printf. If you really don't want to include stdio.h you can declare a prototype for printf:
    Code:
    int printf(const char *format, ...);
    
    int
    main(void)
    {
      printf("Hello, world!\n");
      return 0;
    }
    In the end, providing declarations is all stdio.h does for you. If you provide your own (correct!) prototype then the effect is the same.
    Last edited by Prelude; 06-22-2004 at 09:39 AM.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. making it portable.....?
    By ShadeS_07 in forum C Programming
    Replies: 11
    Last Post: 12-24-2008, 09:38 AM
  2. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  3. segmentation fault upon reload
    By yabud in forum C Programming
    Replies: 8
    Last Post: 12-18-2006, 06:54 AM
  4. Simple C question: user input to repeat a loop
    By evernaut in forum C Programming
    Replies: 2
    Last Post: 11-18-2006, 09:23 AM
  5. Drawing tables in C
    By stanoman in forum C Programming
    Replies: 5
    Last Post: 10-09-2003, 10:14 AM