Thread: Creating a printf function

  1. #1
    Registered User
    Join Date
    Oct 2022
    Posts
    11

    Creating a printf function

    Hello guys,
    Please i need guidelines on working on this assignment

    The my_printf() function produce output according to a format as described below. The my_printf() functions write output to stdout, the standard output stream;
    This function writes the output under the control of a format string that specifies how subsequent arguments (or arguments accessed via the variable-length argument facilities of stdarg(3)) are converted for output.
    The format string is composed of zero or more directives: ordinary characters (not PERCENT), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments.
    Each conversion specification is introduced by the PERCENT character. The arguments must correspond properly (after type promotion) with the conversion specifier. After the PERCENT, the following appear in sequence:

    • doux The int (or appropriate variant) argument is converted to signed decimal (d). unsigned octal (o), unsigned decimal (u), unsigned hexadecimal (x).
    • c The int argument is converted to an unsigned char, and the resulting character is written.
    • s The char * argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating NUL character.
    • p The void * pointer argument is printed in hexadecimal.


    Authorized function(s)

    • • write(2)
    • • malloc
    • • free
    • • va_start, va_arg, va_copy, va_end (see man 3 stdarg)

    (Obvious) Unauthorized functions

    • printf and co. (fprintf, sprintf, snprintf, asprintf, dprintf, vprintf, vfprintf, vsprintf, vsnprintf, vasprintf, vdprintf)

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I guess the first thing to do is start by being able to do
    my_printf("hello world");

    Then you attempt douxcsp ONE letter at a time, testing as you go.

    See also Variadic functions - cppreference.com
    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.

  3. #3
    Registered User
    Join Date
    Apr 2021
    Posts
    139
    Quote Originally Posted by dailysflash View Post
    Hello guys,
    Please i need guidelines on working on this assignment
    Printf and friends work by parsing the fmt string one character at a time. Someone has already pointed out that your starting point should be to handle a string that has no percent characters, only basic text.

    I would suggest that step 1 is a non-variadic function taking only one argument.

    Then step 2 could be a variadic function that ignores the extra arguments.

    Finally, step 3 could be a function that understands how to do "%s" only, because %s is dead easy, and makes a good introduction to processing the %-escape sequences.

    Step 4 can be %c and %%, just to add some other easy-to-implement cases to the code that deals with % handling. This way you don't have to think too hard about formatting, only about structuring your code so it's simple to add different %-escape characters.

    At this point, you'll have the processing of the format string down, and your code will be structured to handle various different kinds of %-escapes, so the only remaining complexity will be converting the parameters for output.

    Step 5 can be the "integer" cases, which should include the %p pointer escape (because you're treating the pointer as an integer).

    Then step 6 can be floating-point, because it will be all that's left!

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I might test this near the beginning.

    Code:
    my_printf("hello world\n");
    It should work by default; but, I would test it because if it does not work then weird things might happen.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I think I might need to brush up on using "va_start, va_arg, va_copy, va_end"; I think this would be a simple project doing that.

    Anyone disagree?

    I learned C back in K & R days; back then there was two ways that were fighting to be the correct way. And, I forgot which way I learned. Never really wrote variable arguments functions in my embedded projects I worked on. But, my new embedded project will be embedded Linux project that might need that skill. It will need things that I have not used since school.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I am guessing the poster is allowed to use itoa() from stdlib.h or a recent assignment had them write a replacement user defined function for it.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I am guessing the original poster is allowed to use fwrite function.

    fwrite - cppreference.com
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  8. #8
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by stahta01 View Post
    I am guessing the original poster is allowed to use fwrite function.

    fwrite - cppreference.com
    Decided fwrite was not needed; it was easier to use putc() standard function instead.

    fputc, putc - cppreference.com

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  9. #9
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Code:
    int main (void){
      my_printf("hello world\n");
      my_printf("%d%o%x%s%c", 16, 16, 16, "hello world\n", 'z');
      my_printf("The value is %d\n", 16);
    }
    The above is my current test code; still have work to do.
    I am using printf calls for testing and for some functionality.
    I still need to remove that; also, need to support 'u' and 'p' specifications.

    'u' should be easy; but, I have no idea about 'p'.

    It took me a while to find a good website to lookup the functions.
    It has been several months or maybe even a year since I did any C coding other than very minor code correction/addition.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    It looks like my complier "itoa" does a poor job of handling unsigned number and "itoa" is not a standard function so the poster likely can not use it.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  11. #11
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by stahta01 View Post
    I think I might need to brush up on using "va_start, va_arg, va_copy, va_end"; I think this would be a simple project doing that.

    Anyone disagree?
    Agreed. That's how I would do it.

    Quote Originally Posted by stahta01 View Post
    I learned C back in K & R days; back then there was two ways that were fighting to be the correct way.
    It might have been varargs vs stdarg. They are very similar but from what I remember have slightly different usage.

  12. #12
    Registered User
    Join Date
    Oct 2022
    Posts
    11
    Quote Originally Posted by stahta01 View Post
    I think I might need to brush up on using "va_start, va_arg, va_copy, va_end"; I think this would be a simple project doing that.

    Anyone disagree?

    I learned C back in K & R days; back then there was two ways that were fighting to be the correct way. And, I forgot which way I learned. Never really wrote variable arguments functions in my embedded projects I worked on. But, my new embedded project will be embedded Linux project that might need that skill. It will need things that I have not used since school.

    Tim S.
    these are the authorized function for the assignment

    Authorized function(s)


    • • write(2)
    • • malloc
    • • free
    • • va_start, va_arg, va_copy, va_end (see man 3 stdarg)



    Unauthorized functions


    • printf and co. (fprintf, sprintf, snprintf, asprintf, dprintf, vprintf, vfprintf, vsprintf, vsnprintf, vasprintf, vdprintf)

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Yeah, we know what your requirements are.

    You've also had 5 days to think about it and make an attempt.

    We're not going to do all the work for you, just so you have something to hand in with zero effort.

    You wanted guidelines, and you have them - what's stopping you?

    If you want to simplify further, then start with
    Code:
    void my_printf(const char *fmt, ... ) {
        char buffer[1000];  // to be replaced by malloc
        // do stuff
    }
    Make an effort, and post your code when you're actually stuck.
    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.

  14. #14
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    The others have already said a fair bit themselves of where you're going wrong so I won't repeat what they've said, instead I'll give you my insights from coding my own replacement for printf, wprintf etc. First off when recording the text to be printed as is it's faster to use indices, on the other hand since you're clearly new to C programming & probably programming in general you're better off allocating an additional string of equal length to the format string (plus the additional character for the terminating \0 character) and just clearing & copying to it at the start of each top level loop that searches for %, after which you can just print that then clear & re-use the allocation to stringify the given argument, print it, then return to the start of the top level loop, here's a rough code view, no detailed function etc given since you haven't posted anything to garner help of that detail.

    Code:
    my_printf(char *format, ...)
    {
    	// allocate string of equal length or more to format, the more being to allow room for conversion of various % arguments that aren't already strings
    	for ( ... )
    	{
    		// clear contents of allocated string
    		for ( ... )
    		{
    			// if not % then copy into next slot of allocation, otherwise end the loop
    		}
    		// print copied string
    		// add on the length of printed string to total printed
    		// clear allocation's contents
    		// check what came after the %, generate string and print accordingly
    		// again add on length of printed string to total printed
    	}
    	// return total printed
    }
    ...thinking about it, this might actually be faster than my current method, eh, I 'll try it later when I'm done with unimplemented stuff

  15. #15
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by awsdert View Post
    The others have already said a fair bit themselves of where you're going wrong so I won't repeat what they've said, instead I'll give you my insights from coding my own replacement for printf, wprintf etc. First off when recording the text to be printed as is it's faster to use indices, on the other hand since you're clearly new to C programming & probably programming in general you're better off allocating an additional string of equal length to the format string (plus the additional character for the terminating \0 character) and just clearing & copying to it at the start of each top level loop that searches for %, after which you can just print that then clear & re-use the allocation to stringify the given argument, print it, then return to the start of the top level loop, here's a rough code view, no detailed function etc given since you haven't posted anything to garner help of that detail.

    Code:
    my_printf(char *format, ...)
    {
        // allocate string of equal length or more to format, the more being to allow room for conversion of various % arguments that aren't already strings
        for ( ... )
        {
            // clear contents of allocated string
            for ( ... )
            {
                // if not % then copy into next slot of allocation, otherwise end the loop
            }
            // print copied string
            // add on the length of printed string to total printed
            // clear allocation's contents
            // check what came after the %, generate string and print accordingly
            // again add on length of printed string to total printed
        }
        // return total printed
    }
    ...thinking about it, this might actually be faster than my current method, eh, I 'll try it later when I'm done with unimplemented stuff
    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;
    }
    Last edited by christop; 11-02-2022 at 03:18 PM. Reason: add code example

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