Thread: Creating a printf function

  1. #16
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by christop View Post
    Copying the format string multiple times? That seems to be a complicated and (from a performance standpoint) wasteful approach. Why not just iterate through the format string, character by character? (The format string should be const char *, by the way.) If the character is the null terminator, finish. If it's a percent sign, read and handle the format specifier. Otherwise, it's a literal character, so just print it out.

    Code:
    const char *s = format;
    while (*s != '\0') {
        if (*s == '%') {
            // read and handle a format specifier
        } else {
            // print out a literal character
        }
        ++s;
    }
    I DID say indices are faster, I simply gave an example a newb would have an easier time understanding, in my actual implementation I just used one wide string handler that I pass converted strings into to reduce complexity and then just record the next index after processing an argument as the new starting position of the next segment to print, the part I was saying is possibly faster than my own code was the handling of the arguments themselves with the shared temporary string to print into before sending to the actual print handler, I have something similar already but it's staged so that all arguments are read before they are printed, naturally that requires a fair bit of memory to do and a few extra instructions to pass go through when switching from the reading loop to the printing loop, that's the part I want to remove if I can so that I can just print straight away instead of waiting until another loop to do so.

  2. #17
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by awsdert View Post
    I simply gave an example a newb would have an easier time understanding
    I don't follow. Don't you still need to do the same or similar work with your method of copying the format string? I.e., searching through the format string character-by-character to find a format specifier? So I don't see how doing the same work (searching for format specifier) plus more work (allocating memory, copying a string) is easier to understand than less, and simpler, work.

  3. #18
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by christop View Post
    I don't follow. Don't you still need to do the same or similar work with your method of copying the format string? I.e., searching through the format string character-by-character to find a format specifier? So I don't see how doing the same work (searching for format specifier) plus more work (allocating memory, copying a string) is easier to understand than less, and simpler, work.
    Because from what I've seen here, newbs have the tendency to confuse even the most basic of pointer math so, coping everything they want to print 1 character at a time to another array seems simpler to those types, at least that's what I think they view of it, for the smarter they'll understand how to use the indices & pointer math without much help, if any, since OP seemed to struggle to understand how to get started on his own printf function I strongly suspect they are of the former kind, the kind that confuses basic pointer math & indices so telling them to just copy it seemed a sensible suggestion for them for the time being.

  4. #19
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    It's beginning to look like the OP is waiting for an answer on a silver plate.
    It's been a week, and all they've managed to do is restate the question.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #20
    Banned
    Join Date
    Jul 2022
    Posts
    112
    The int (or appropriate variant)
    Is Int Signed or Unsigned ?

    I strongly doubt that this is an assignment,
    Seriously, is that what a tutor expects from a novice..
    OP is playing us..

  6. #21
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by kodax View Post
    Is Int Signed or Unsigned ?

    I strongly doubt that this is an assignment,
    Seriously, is that what a tutor expects from a novice..
    OP is playing us..
    Or they want to re-implement it for their own library but are too lazy to think about how to do so, I know the feeling but I still put in the effort before bringing my problems here (assuming I didn't manage to fix 'em myself)

  7. #22
    Registered User
    Join Date
    Oct 2022
    Posts
    11
    Thanks, guys for your advice and teaching I finally arrived at this,
    copied from local text editor.
    Code:
    #include <stdarg.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int my_putchr(char);
    int print_base(size_t, int);
    int print_decimal(va_list, char);
    int print_string(va_list);
    int print_number(va_list, int);
    int print_char(va_list);
    int print_formatted(va_list, char);
    int my_printf(char* restrict, ...);
    
    int my_putchr(char c)
    {
        return write(STDOUT_FILENO, &c, 1);
    }
    
    int print_base(size_t unslong, int base)
    {
        char* c_array = (char*)malloc(sizeof(char));
        int index = 0, count = 0;
        do
        {
            int modulus = unslong % base;
            if (modulus >= 0 && modulus < 10)
                c_array[index] = modulus + '0';
            else
                c_array[index] = 'a' + modulus - 10;
            c_array = realloc(c_array, sizeof(char) + (sizeof(char) * ++index));
            unslong /= base;
        } while (unslong > 0);
    
        do
        {
            index--;
            count += my_putchr(c_array[index]);
        } while (index);
        free(c_array);
        return count;
    }
    
    int print_decimal(va_list ap, char format)
    {
        int current = va_arg(ap, int);
        int count = 0;
        if (current < 0)
        {
            current = -current;
            if (format == 'd') count += my_putchr('-');
        }
        count += print_base(current, 10);
        return count;
    }
    
    int print_string(va_list ap)
    {
        char* string = va_arg(ap, char*);
        int count = 0;
        while (*string != '\0')
        {
            char c = *string;
            count += my_putchr(c);
            string++;
        }
        return count;
    }
    
    int print_number(va_list ap, int base)
    {
        size_t current = va_arg(ap, size_t);
        return print_base(current, base);
    }
    
    int print_char(va_list ap)
    {
        char current = va_arg(ap, int);
        return my_putchr(current);
    }
    
    int print_formatted(va_list ap, char format)
    {
        switch (format)
        {
            case 'd':
            case 'u':
                return print_decimal(ap, format);
            case 'o':
                return print_number(ap, 8);
            case 'p':
            case 'x':
                return print_number(ap, 16);
            case 'c':
                return print_char(ap);
            case 's':
                return print_string(ap);
        }
        return 0;
    }
    
    int my_printf(char* format, ...)
    {
        int total_print = 0;
        va_list ap;
        va_start(ap, format);
    
        while (*format != '\0')
        {
            if (*format == '%' && *(++format) != '\0')
                total_print += print_formatted(ap, *format);
            else
                total_print += my_putchr(*format);
    
            if (*format != '\0') format++;
        }
    
        va_end(ap);
        return total_print;
    }

  8. #23
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Well that's certainly different from my implementation, while that will serve you for now (didn't test it so I'm assuming it works) I'd advise you to at least keep a notepad nearby to jot down ideas on how to improve the flexibility of your implementation for when you actually need the flexibility, otherwise you'll be rebuilding all the projects using it every time you want to add just one thing, even if you put it in a dll, sooner or later it will reach a point where it takes to long to rebuild just for one addition that's only needed by one project

  9. #24
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > char* c_array = (char*)malloc(sizeof(char));
    1. There is no need to cast the result of malloc in a C program.

    2. You can calculate the max number of characters you would need, without needing to call realloc every time (this is expensive to do).
    Code:
    #include <stdio.h>
    #include <stdint.h>
    #include <math.h>
    #include <limits.h>
    
    int getwidth(int base) {
        double bits_per_char = log(base) / log(2);
        int bits_in_type = sizeof(int) * CHAR_BIT;
        return ceil(bits_in_type / bits_per_char);
    }
    
    int main()
    {
        printf("Hex %d\n", getwidth(16));
        printf("Dec %d\n", getwidth(10));
        printf("Oct %d\n", getwidth(8));
        printf("Bin %d\n", getwidth(2));
    }
    > int print_base(size_t unslong, int base)
    You're mis-using the purpose of size_t
    Use unsigned long instead.

    > current = -current;
    Beware that the largest negative number doesn't have a positive counterpart (for two's complement arithmetic, which is the most common today).
    Numeric limits - cppreference.com
    Code:
    SHRT_MIN       = -32768
    SHRT_MAX       = +32767
    USHRT_MAX      = 65535
     
    INT_MIN        = -2147483648
    INT_MAX        = +2147483647
    UINT_MAX       = 4294967295
    > int my_printf(char* format, ...)
    format should be a const char *
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to printf a function
    By SquareDance in forum C Programming
    Replies: 6
    Last Post: 11-19-2017, 12:04 PM
  2. printf-like function ?
    By Algar in forum C Programming
    Replies: 3
    Last Post: 01-02-2013, 01:35 PM
  3. creating new lines with 1 printf
    By Irony in forum C Programming
    Replies: 2
    Last Post: 09-08-2009, 08:51 AM
  4. printf like function
    By tyouk in forum C Programming
    Replies: 5
    Last Post: 11-17-2003, 07:26 PM
  5. printf like function
    By argon in forum C Programming
    Replies: 2
    Last Post: 10-07-2003, 03:12 PM

Tags for this Thread