Author Topic: C function like printf but not sending to stdout? (XC8)  (Read 32123 times)

0 Members and 1 Guest are viewing this topic.

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #75 on: May 11, 2013, 03:34:54 am »
An additional useful technique is comma which continues the calculation statement.  When comma is used, the last statement has the final value and that is used.
ii = 1, 2, 3, 4 ;   // ii is assigned 4, the last evaluation done

Actually, that's not the result. Assignment has higher precedence than the comma operator, so this is the same as doing:

(ii = 1), 2, 3, 4 ;

which has the result that ii is assigned the value of 1, whereafter the expressions 2, 3 and 4 are evaluated with the results being thrown away, essentially becoming no-ops. The compiler might give you a warning that you have expressions without side effects if compiling this code.

However, if you write

ii = (1, 2, 3, 4) ;

you get the result claimed before.

Yup, you are right...  Forgot about the () there.
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #76 on: May 11, 2013, 03:37:14 am »
void lcd_outstr(const char *buffer)
{
int   ii=0;
int   maxSize=100;  // hard coded max, but can be parameter driven
   while(*buffer && ++ii<maxSize)   // Write upto terminator or maxSize bytes of data to LCD
   {
       lcd_char(*buffer);       // Write character to LCD
       buffer++;               // Increment buffer
   }
}

A good practice when writing code is to replay the code in your mind and see if it does what you think it ought to do.

In the above example, suppose the buffer has size 1 (a thought experiment). What will happen?

First pass through the loop: buffer points to the one and only character so the while() test is successful and the character is printed.

Second pass through the loop: buffer was incremented and now points beyond the end of the buffer. It will print some unknown character to the LCD.

Note how the ++ii<maxSize test will not save it, since the && operator short circuits and if the first condition is true the second condition will never be evaluated. If this logic fails with a buffer of size 1, it will fail with a buffer of size 100.


Good pick.  Goes to show, a quick line of code merely to show a point should still be carefully reviewed.

Edit:
Edited the quote to just keep the part my "Good pick" was referring to.  The other point I did not agreed (which is in another comment that I just made).
« Last Edit: May 11, 2013, 04:10:03 am by Rick Law »
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2094
Re: C function like printf but not sending to stdout? (XC8)
« Reply #77 on: May 11, 2013, 03:43:44 am »
void lcd_outstr(const char *buffer)
{
int   ii=0;
int   maxSize=100;  // hard coded max, but can be parameter driven
   while(*buffer && ++ii<maxSize)   // Write upto terminator or maxSize bytes of data to LCD
   {
       lcd_char(*buffer);       // Write character to LCD
       buffer++;               // Increment buffer
   }
}

A good practice when writing code is to replay the code in your mind and see if it does what you think it ought to do.

In the above example, suppose the buffer has size 1 (a thought experiment). What will happen?

Like most string functions it is intended to output zero terminated strings. The buffer has no size. The string size is from the start of the buffer to where ever the zero terminator is. The maxSize check is to prevent overflow of the LCD (which may or may not be required).
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #78 on: May 11, 2013, 03:51:40 am »
As for for loops they are just shorthand for a commonly used form of while statement, kludging less common forms of while into them with comma operators is more confusing than just using while.

I've always seen a "for" loop as being iterative over a sequence, and a "while" loop as being repetitive conditional on an external state - for example, while the input given is invalid, continue giving an error message and requesting it again. I'd rather use a "for" loop to loop over some sort of container, even if the top of the loop is a little bit ugly, as it makes the intention clear.

I use for over while out of habit.  Prior to optimization compilers, I read that for( ; ; ) is far more efficient over while(1).  After confirming it by looking at the op codes actually generated, I confirmed that for my compiler do indeed generate much better code with for( ; ; ) over while(1).

Where I am doing a single task within the loop, I found the comma-inside-for much easier to read.  Single (or very simple) looped task such as scanning for a particular case.

for (cp=startOfSomething,kp=endOfSomething;TestForEnd(cp);callthis(),prepareToReLoop) ;

Another case where I would use comma is to seperate substeps:
   thisOne=(thatOne++,firstFunction(&thatOne));

A matter of style and habit, I suppose.
« Last Edit: May 11, 2013, 05:01:07 am by Rick Law »
 

Offline kfitch42

  • Frequent Contributor
  • **
  • Posts: 300
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #79 on: May 11, 2013, 03:53:24 am »
sprintf will format a string into a buffer. Be very careful of buffer overflow - snprintf prevents this, but is not present in all C libraries.

snprintf helps, but it does not absolve you from buffer related bugs. The biggest problem with snprintf is that it DOES NOT guarantee null-termination. If it ends up truncating (to avoid buffer overflow) the buffer will not be null-terminated. it is the responsibility of the caller of snprintf to check the return value and take appropriate action in case of truncation. In reality, most coders forget this.

P.S. I can't count the number of times I have seen off-by-one-errors when using snprintf and friends...
« Last Edit: May 11, 2013, 03:57:06 am by kfitch42 »
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #80 on: May 11, 2013, 03:59:29 am »
Code: [Select]
void lcd_outstr(const char *buffer, int buflen)
{
const char *endbuf = buffer + buflen;
while(buffer < endbuf && *buffer)
{
    lcd_char(*buffer);
    ++buffer;
}
}

A matter of style and system.  Pointer arithmetic makes the code difficult to port.  I started coding C when pointers could be 12 bits (crazy segment:offset of the 8088/8086), 16 bits, or 32 bits.  Once you do pointer arithmetic, you are relying on certain method of type-conversion.

When I do an int as a counter, int is defined as system default word size.  It was 8 bit signed with my first C compiler, 16 later, then 32.  When I am counting something up to just 100, using an int will cause less portability issues in my experience.
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #81 on: May 11, 2013, 04:06:46 am »
And I would suggest this variant:

Code: [Select]
void lcd_outstr(const char *buffer, size_t buflen)
{
size_t i;
        for (i = 0; i < buflen && buffer[i]; ++i) {
                lcd_char (buffer[i]);
        }
}

Or if you're tight on RAM in a microcontroller application, slightly less readable but saving a variable (that the compiler ought to optimize out anyway, but some compilers suck):
Code: [Select]
void lcd_outstr(const char *buffer, size_t buflen)
{
        for (i = 0; buflen && *buffer; ++buffer, --buflen) {
                lcd_char (*buffer);
        }
}

I wouldn't really recommend the second one, but it's not awful, I suppose.

I generally prefer to use *buffer with buffer++ over buffer with i++.  Another style and taste thing.

I think we are either going to scare David_AVD from coding C pretty soon showing him a million way to skin a cat, or he is going to get very excited to try coming up with his million&1 way to skin the cat.
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2094
Re: C function like printf but not sending to stdout? (XC8)
« Reply #82 on: May 11, 2013, 04:11:20 am »
Code: [Select]
void lcd_outstr(const char *buffer, int buflen)
{
const char *endbuf = buffer + buflen;
while(buffer < endbuf && *buffer)
{
    lcd_char(*buffer);
    ++buffer;
}
}

A matter of style and system.  Pointer arithmetic makes the code difficult to port.  I started coding C when pointers could be 12 bits (crazy segment:offset of the 8088/8086), 16 bits, or 32 bits.  Once you do pointer arithmetic, you are relying on certain method of type-conversion.

When I do an int as a counter, int is defined as system default word size.  It was 8 bit signed with my first C compiler, 16 later, then 32.  When I am counting something up to just 100, using an int will cause less portability issues in my experience.
This code is more stylish and will run much faster (apparently)...
Code: [Select]
void lcd_outstr(const char *buffer, int buflen) {
   const char *endbuf;
   for(endbuf=buffer+buflen;buffer<endbuf&&*buffer;lcd_char(*buffer),++buffer);
}
 

Offline glatocha

  • Regular Contributor
  • *
  • Posts: 114
Re: C function like printf but not sending to stdout? (XC8)
« Reply #83 on: May 11, 2013, 04:14:19 am »
My God. In which way it is more stylish?
That's why I don't like C. The fight for putting as less code as possible.
Somehow it always takes my much more time to think what I want to write then typing itself. So I don't really care how small the source code is. I would rather prefer more easy reading.
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2094
Re: C function like printf but not sending to stdout? (XC8)
« Reply #84 on: May 11, 2013, 04:19:52 am »
My God. In which way it is more stylish?

In the way that it takes the piss out of some of the other posts in this thread :)
 

Offline c4757p

  • Super Contributor
  • ***
  • Posts: 7805
  • Country: us
  • adieu
Re: C function like printf but not sending to stdout? (XC8)
« Reply #85 on: May 11, 2013, 04:22:43 am »
If you want to make a real piss-taking abomination you have to use the unholy combination *buffer++.
No longer active here - try the IRC channel if you just can't be without me :)
 

Offline Rufus

  • Super Contributor
  • ***
  • Posts: 2094
Re: C function like printf but not sending to stdout? (XC8)
« Reply #86 on: May 11, 2013, 04:25:03 am »
If you want to make a real piss-taking abomination you have to use the unholy combination *buffer++.

But then it wouldn't need a comma operator :(
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #87 on: May 11, 2013, 04:28:29 am »
Code: [Select]
void lcd_outstr(const char *buffer, int buflen)
{
const char *endbuf = buffer + buflen;
while(buffer < endbuf && *buffer)
{
    lcd_char(*buffer);
    ++buffer;
}
}

A matter of style and system.  Pointer arithmetic makes the code difficult to port.  I started coding C when pointers could be 12 bits (crazy segment:offset of the 8088/8086), 16 bits, or 32 bits.  Once you do pointer arithmetic, you are relying on certain method of type-conversion.

When I do an int as a counter, int is defined as system default word size.  It was 8 bit signed with my first C compiler, 16 later, then 32.  When I am counting something up to just 100, using an int will cause less portability issues in my experience.
This code is more stylish and will run much faster (apparently)...
Code: [Select]
void lcd_outstr(const char *buffer, int buflen) {
   const char *endbuf;
   for(endbuf=buffer+buflen;buffer<endbuf&&*buffer;lcd_char(*buffer),++buffer);
}

I can see it could run faster.  But I have a habit of avoiding pointer arithmetic unless absolutely necessary.  I hate codes that fail when compiled with different flags.  If memory serves, I think Microsoft C had small, large, and huge memory model.  The char * changes to char FAR * or char HUGE *.  Use the wrong slash parameter and the code goes south because what you assume would fit into an int doesn't fit anymore.  So, I do pointer arithmetic only when there is a meaningful advantage.
 

Offline c4757p

  • Super Contributor
  • ***
  • Posts: 7805
  • Country: us
  • adieu
Re: C function like printf but not sending to stdout? (XC8)
« Reply #88 on: May 11, 2013, 04:30:58 am »
I've actually seen it used in a very unreadable way in code that was called "good" with a straight face. Of course, I'm still trying to figure out whether the circus of coding behind the GNU project is actually a very elaborate Monty Python skit that we programmers are being unknowingly compelled to participate in...
No longer active here - try the IRC channel if you just can't be without me :)
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #89 on: May 11, 2013, 04:37:34 am »
My God. In which way it is more stylish?
That's why I don't like C. The fight for putting as less code as possible.
Somehow it always takes my much more time to think what I want to write then typing itself. So I don't really care how small the source code is. I would rather prefer more easy reading.

Actually, it is not what is more stylish in the sense of what look better.  It is a personal style of work - like if you want your pencils to your left or to your right.

For me personally, I want to fit more code on the screen.  When more code is visible, it helps me grasp what is going on better.  Where I have a loop that does something simple, rather than having it being 4 or 5 lines of empty space with a few words in it.  I rather see it condensed into a single complex line.  My mind can move on to: ok, in this loop, there is this task to scan for tab after comma, and then next is blah blah blah.

With and empty { on one line, then buffer++ on another...  I can press down arrow 16 times and I am still reading the same conceptual idea whereas with a single complex line I can see many more conceptual task being done on a single screen.
 

Offline David_AVD

  • Super Contributor
  • ***
  • Posts: 2607
  • Country: au
Re: C function like printf but not sending to stdout? (XC8)
« Reply #90 on: May 11, 2013, 05:04:19 am »
Assembler is looking more attractive with every post.   :o
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #91 on: May 11, 2013, 06:12:43 am »
Assembler is looking more attractive with every post.   :o

Ahem, don't let us scare you off.

Once you get a handle of it, you will/can develop your own style and ignore all those comments made.  The wide spread of opinion shows there are so many ways in C to accomplish the tasks and you will find the way best suits you.  We all settle into a mode that fits us best.  To say "this way works for me and should do it this way too" is like saying "can't see? wear my glasses, it works for me well and you too should do just fine with mine."

I am a little rusty with my C.  Arduino is not something I yet played with, so the code segments I show may not fit Arduino well.

If you are familiar with assembler already, C is easy.  I like assembler, but I rather debug C over debugging assembler any day.

Play with it.  Worst case is, you walk off a more knowledgeable man.

Rick
 

Offline Bored@Work

  • Super Contributor
  • ***
  • Posts: 3932
  • Country: 00
Re: C function like printf but not sending to stdout? (XC8)
« Reply #92 on: May 11, 2013, 07:17:45 am »
Once you get a handle of it, you will/can develop your own style and ignore all those comments made.

A good way to make sure you aren't usable in a larger team. A diva with an own style is one of the worst things you can have in a larger team. Either people pull all in the same direction or you quickly end up with a heap of junk of a code base.

My experience with programmers venting their own coding spleen is they often use this, and defend this vigorously, to hide their incompetence. Especially in C there is a huge amount of an existing body of knowledge and conventions. Good, experienced, professional C programmers often don't even need a formal coding convention document. They can agree on one within minutes, or if there is some existing code they can pick up the project's existing conventions by just reading a few pieces of code.

By the way, your statements about pointer arithmetic are simply wrong.
I delete PMs unread. If you have something to say, say it in public.
For all else: Profile->[Modify Profile]Buddies/Ignore List->Edit Ignore List
 

Online amyk

  • Super Contributor
  • ***
  • Posts: 6868
Re: C function like printf but not sending to stdout? (XC8)
« Reply #93 on: May 11, 2013, 12:45:42 pm »
This code is more stylish and will run much faster (apparently)...
Code: [Select]
void lcd_outstr(const char *buffer, int buflen) {
   const char *endbuf;
   for(endbuf=buffer+buflen;buffer<endbuf&&*buffer;lcd_char(*buffer),++buffer);
}
Even with compiler optimisation? That's not unheard of, and is the reason why Asm still has its place.

As an experienced C programmer I'd write this:
Code: [Select]
void lcd_outstr(const char *buffer, int buflen) {
 while(buflen-- && *buffer)
  lcd_char(*buffer++);
}
 

Offline TerminalJack505

  • Super Contributor
  • ***
  • Posts: 1306
  • Country: 00
Re: C function like printf but not sending to stdout? (XC8)
« Reply #94 on: May 11, 2013, 01:02:10 pm »
I am always scared to use library functions.
They might cover much more than I need and cause a high memory usage.
I prepare most of my routines on myself. For example for LCD Integer display:

Code: [Select]
void LCD_Int(int16_t num)
{
    int16_t div;
    uint16_t i;
    if (num <0)
    {
        LCD_SendCHAR_4b('-');
        num = num * -1;
    }
    for (i=10000;i>=10;i=i/10)
    {
        if (num>=i)
        {
            div = num/i;
            num = num%i;
            LCD_SendCHAR_4b(div + '0');
        }
    }
    LCD_SendCHAR_4b(num + '0');
}

Same I have for doubles.
I am also planning to rewrite most of it in asm and maybe get rid of dividing.

I started programming with atmel 2051 with 2kb Flash and 128 RAM bytes. So still have in mind always optimize.
But maybe nowadays much cheaper is to just update the chip with higher memory version of 0,10$.

When you are doing both a division and a modulus of a particular number you should keep the C library function div() in mind.  Especially on lower-end MCUs.  The div() function will calculate both the quotient and remainder so it could save you some clock cycles. 

Of course you'll always want to check the compiler's output in both cases since compilers can be pretty clever.
 

Offline c4757p

  • Super Contributor
  • ***
  • Posts: 7805
  • Country: us
  • adieu
Re: C function like printf but not sending to stdout? (XC8)
« Reply #95 on: May 11, 2013, 01:16:49 pm »
Once you get a handle of it, you will/can develop your own style and ignore all those comments made.

A good way to make sure you aren't usable in a larger team. A diva with an own style is one of the worst things you can have in a larger team. Either people pull all in the same direction or you quickly end up with a heap of junk of a code base.

When you have an existing codebase, the style should always be conformity, and when you are starting one in a team, a style should always be chosen and agreed upon. For hobby stuff, though, it's definitely better to develop your own style and stick with it than to waste hours reading arguments and nerd rage about how every style out there is supposedly objectively wrong.
No longer active here - try the IRC channel if you just can't be without me :)
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #96 on: May 11, 2013, 06:12:04 pm »
Once you get a handle of it, you will/can develop your own style and ignore all those comments made.

A good way to make sure you aren't usable in a larger team. A diva with an own style is one of the worst things you can have in a larger team. Either people pull all in the same direction or you quickly end up with a heap of junk of a code base.

When you have an existing codebase, the style should always be conformity, and when you are starting one in a team, a style should always be chosen and agreed upon. For hobby stuff, though, it's definitely better to develop your own style and stick with it than to waste hours reading arguments and nerd rage about how every style out there is supposedly objectively wrong.

Can't disagree with that.  But David_AVD clearly is not developing profession code in a team.  So he needs to develop style best fit him.
 

Offline Rick Law

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #97 on: May 11, 2013, 06:29:50 pm »
A good way to make sure you aren't usable in a larger team...
...
By the way, your statements about pointer arithmetic are simply wrong.


Board@Work, David_AVD is NOT working in a team.  He is just exploring for his own.
I don't think you are relating to someone who merely is doing it for recreation...


Re: I am incorrect about pointer arithmetic
You are right for the world today but I was not referring to the world today.  What I said was I developed that habit when it was difficult to port pointer arithmetic.

I was working with compilers that ran on a 50k floppy.  I was porting to a different compilers that ran on 360k floppy.  That was a different world then.  Back then, floppies doesn't even interchange.  You have "soft sector floppies" and "hard sector floppies".  Hell, the compiler even has to load to specific memory addresses.  It was a different world then.
« Last Edit: May 11, 2013, 06:45:29 pm by Rick Law »
 

Offline David_AVD

  • Super Contributor
  • ***
  • Posts: 2607
  • Country: au
Re: C function like printf but not sending to stdout? (XC8)
« Reply #98 on: September 30, 2013, 06:27:55 am »
Sorry for reviving my old thread, but thought it better than create a new one as this is related.

I can't seem to work out the code to format a string given more than one variable.

I have minutes and seconds in two uint8_t variables that I want to present as a string in the "mm:ss" format, with zeroes instead of spaces for padding. (eg 00:05 for 5 seconds)

After looking at many C functions, I can't see how to give any of them more than one argument.  A nudge in the right direction would be appreciated.  Thanks.
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 9728
  • Country: us
Re: C function like printf but not sending to stdout? (XC8)
« Reply #99 on: September 30, 2013, 06:34:31 am »
You would want printf (print directly to stdout) or sprintf (write formatted text to a string in memory).

For example, to print your time string you might use something like:

Code: [Select]
printf("%2.2u:%2.2u", (unsigned int)minutes, (insigned int)seconds);
Here % introduces a format specifier, 2.2 specifies a field width of 2 with a precision of 2 (i.e. 2 digits printed), and u specifies an unsigned decimal integer.
« Last Edit: September 30, 2013, 06:40:37 am by IanB »
I'm not an EE--what am I doing here?
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf