| Author |
Message |
|
|
Posted: Jun 02, 2012 - 02:20 AM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
And I don't mean http://en.wikipedia.org/wiki/File:Miche ... ce2836.jpg
Want to display an integer in a 5 character space, so I put:
Code:
char s[6];
itoa(x, s, 10);
while (strlen(s) < 5)
s = strcat(" ", s);
LCDWrites(s);
But naturally I can't find the combination needed to put a " " before the contents of s in s.
I guess I could do:
Code:
int i = strlen(s);
while (i>=0){
s[i+1] = s[i];
i -= 1;
}
s[0] = ' ';
inside my outer while, but you guys would laugh at such a solution (you have my permission). |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 02:29 AM |
|

Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA
|
|
|
Torby wrote:
Code:
s = strcat(" ", s);
Try
Code:
strcat(s, " ");
The C string and memory functions generally take the destination as the first parameter.
EDIT: Thinking about it, it seems like you try to use this to allocate a string. You can't do that. What you were doing, was appending the contents of s to whatever memory location contained your space. While the outcome is undefined, it will clearly lead to problems. See below for the easiest way to right align stuff in a string. |
Last edited by ChaunceyGardiner on Jun 02, 2012 - 02:40 AM; edited 2 times in total
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 02:33 AM |
|

Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA
|
|
|
Torby wrote:
Code:
char s[6];
itoa(x, s, 10);
while (strlen(s) < 5)
s = strcat(" ", s);
LCDWrites(s);
But naturally I can't find the combination needed to put a " " before the contents of s in s.
If you have sprintf() you can do this:
Code:
char s[6];
sprintf(s, "%5d", x);
LCDWrites(s);
|
Last edited by ChaunceyGardiner on Jun 02, 2012 - 02:43 AM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 02:40 AM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
Don't have sprintf.
Wouldn't strcat(s, " ") put the space behind the s? I want it in front, rather like s = " " + s, if you could add strings.
I understand these aren't C++'s string class. Don't know how to use that either |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 02:47 AM |
|

Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA
|
|
A bit of "post as you think of it" here - I edited my first answer before you responded.
If you don't have sprintf(), you probably have to do it manually after using itoa(). That shouldn't be too hard, though.
BTW, how do you know you don't have sprintf() ? |
|
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 02:57 AM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
Oh. Now I have sprintf, but now I'm at 132% of memory. Without sprintf, I'm at 51%.
Maybe I'll loop and write out spaces first, then s. |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 08:44 AM |
|


Joined: Jul 23, 2001
Posts: 2438
Location: Osnabrueck, Germany
|
|
|
Code:
char s[6] = " ";
char n[6];
itoa(x,n,10);
strcpy(s+5-strlen(n),n);
Code:
char n[9] = " ";
char *s;
itoa(x,n+4,10);
s = n + strlen(n) - 5;
|
_________________ Stefan Ernst
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 12:12 PM |
|


Joined: Jul 18, 2005
Posts: 62299
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| I'd follow Stefan's suggestion but if you wanted to persevere with sprintf then explore using libprintf_min.a perhaps. |
_________________
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 07:46 PM |
|

Joined: Oct 29, 2006
Posts: 2651
|
|
|
Torby wrote:
And I don't mean http://en.wikipedia.org/wiki/File:Miche ... ce2836.jpg
Want to display an integer in a 5 character space, so I put:
Code:
char s[6];
itoa(x, s, 10);
while (strlen(s) < 5)
s = strcat(" ", s);
LCDWrites(s);
Code:
char s[7]; // -23456\0
itoa(x, s, 10);
unsigned char j=strlen(s), delta=sizeof(s)-1-j;
// atoa(x, s+delta, 10);
do {
s[j+delta]=s[j];
} while(j--);
while(delta) s[--delta]=' ';
Tidier:
Code:
char s[7]; // -23456\0
itoa(x, s, 10);
unsigned sz=1+strlen(s), delta=sizeof(s)-sz;
memmove(s+delta, s, sz);
memset(s, ' ', delta);
|
_________________ Michael Hennebry
Iluvatar is the better part of Valar.
|
| |
|
|
|
|
|
Posted: Jun 03, 2012 - 02:12 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
Tidier:
The approaches above are "straightforward", but "tidier" may be in the eye of the beholder.
Digest the approaches here: http://www.avrfreaks.net/index.php?name ... torder=asc Some indeed have right-justification and leading-zero-supression. (I know mine does.) Most (all?) will be smaller than full-blown printf() (if it isn't already justified for other purposes) as size seems to matter. |
|
|
| |
|
|
|
|
|
Posted: Jun 03, 2012 - 10:56 PM |
|

Joined: Oct 29, 2006
Posts: 2651
|
|
|
theusch wrote:
Quote:
Tidier:
The approaches above are "straightforward", but "tidier" may be in the eye of the beholder.
The OP used strlen in a loop, so efficiency was not a criterion.
The smaller the source, the smaller the room for mess.
My tidy code also avoided explicit loops.
It is readily seen to be correct.
Since, OP didn't use it, I'd taken sprintf as unavailable.
With that limitation, the only real competitors are sternst's SRAM-wasters.
Quote:
Digest the approaches here: http://www.avrfreaks.net/index.php?name ... torder=asc Some indeed have right-justification and leading-zero-suppression. (I know mine does.) Most (all?) will be smaller than full-blown printf() (if it isn't already justified for other purposes) as size seems to matter.
At least in the current case, the job to be done is fairly clear.
BCD does not have blanks. Zero-suppression shouldn't be possible. |
_________________ Michael Hennebry
Iluvatar is the better part of Valar.
Last edited by skeeve on Jun 03, 2012 - 11:46 PM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Jun 03, 2012 - 11:26 PM |
|

Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA
|
|
|
skeeve wrote:
With that limitation, the only real competitors are sternst's SRAM-wasters.
While I think your solution is better suited for creating flexible reusable code (i.e. a function), you can barely claim that sternst is wasting SRAM. His variable is 4 bytes bigger than yours (if he expands it to account for a possible minus sign and another character), and you generate more code than he does.
Even if you do care about those four bytes, that only lasts until the variable goes out of scope anyway - and that is something you can control if you care about it. |
|
|
| |
|
|
|
|
|
Posted: Jun 04, 2012 - 12:05 AM |
|

Joined: Oct 29, 2006
Posts: 2651
|
|
|
ChaunceyGardiner wrote:
skeeve wrote:
With that limitation, the only real competitors are sternst's SRAM-wasters.
While I think your solution is better suited for creating flexible reusable code (i.e. a function), you can barely claim that sternst is wasting SRAM. His variable is 4 bytes bigger than yours (if he expands it to account for a possible minus sign and another character), and you generate more code than he does.
More importantly, sternst's methods are more obviously correct than mine.
I don't know why they would be any less useful in a function.
Quote:
Even if you do care about those four bytes, that only lasts until the variable goes out of scope anyway - and that is something you can control if you care about it.
|
_________________ Michael Hennebry
Iluvatar is the better part of Valar.
|
| |
|
|
|
|
|
Posted: Jun 04, 2012 - 12:16 AM |
|

Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA
|
|
|
skeeve wrote:
More importantly, sternst's methods are more obviously correct than mine.
I don't agree with that - you both have bugs in your suggestions, but those are easy to fix and you got your ideas out there. That's the main thing.
skeeve wrote:
I don't know why they would be any less useful in a function.
I think your suggestion would be easier to implement as a function that takes the field width as an additional parameter. |
|
|
| |
|
|
|
|
|
Posted: Jun 04, 2012 - 04:22 PM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
Working on my own before Church, I came up with
Code:
void WriteFt(long f)
{
char s[6];
itoa(f, s, 10);
uint8_t i = 5 - strlen(s);
while (i > 0) {
LCDWritesP(Space);
i -= 1;
}
LCDWrites(s);
}
But I like sternst's solution. It eats an extra variable, but that would be on the stack and vanish when the procedure exits.
Correct on efficiency. It only needs to display a few times a second, but a graceful solution is nicer to a mess.
I think I see how skeeve's solution works.
Similar puzzle is this:
x contains the answer * 10, so I want to insert a decimal point just ahead of the last character. If the decimal point lands in the first character, then insert a zero ahead of it.
Maybe:
Code:
char s[6] ;
itoa(x,s,10);
uint8_t l = strlen(s);
if (l == 1){
s[2] = s[1];
s[1] = s[0];
s[0] = '0';
l += 1;
};
s[l] = s[l-1] ; // Move the null
s[l-1] = s[l-2] ; // Move the last digit
s[l-2] = '.'; // add the .
(I typed this into the message rather than copying it from a correct program.) |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Jun 04, 2012 - 04:28 PM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
| (Shouldn't have used small L for the variable. Can't tell it from a one.) |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Jun 04, 2012 - 04:30 PM |
|


Joined: Feb 19, 2001
Posts: 25912
Location: Wisconsin USA
|
|
|
Quote:
At least in the current case, the job to be done is fairly clear.
BCD does not have blanks. Zero-suppression shouldn't be possible.
Huh? Didja actually read the thread? I thought it was fairly exhaustive in exploring different approaches.
danni's solution is most elegant, if the input range is limited. My utoa() is straightforward, doesn't waste any SRAM that I know of, and does both right-justification and leading-zero suppression. The latter two features are my norm when building LCD display panels.
Often I have a variant for inserting the implied decimal point. I find the above to be "better" in the long run versus a post-processing pass on the string.
All that said, if itoa() and strlen() and strcpy()/memcpy() are used elsewhere in the app, the the code footprint for this purpose is essentially 0 and itoa() is usually fairly efficient. So for a uint16_t with max value of 50000 are you going to do ltoa()? |
|
|
| |
|
|
|
|
|
Posted: Jun 04, 2012 - 07:25 PM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
Of course size matters: It's in a Tiny 2313 |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|
Posted: Jun 05, 2012 - 12:00 AM |
|

Joined: Nov 09, 2011
Posts: 399
|
|
If you're not using itoa elsewhere, just open code it.
- S
ps: exercise left for the reader: instead of returning the string, print the integer using "putchar()". Rewrite the code to avoid the allocatation of the "s" variable on the stack.
Code:
char s[6];
int x = blah;
s[5] = '\0';
for (int i = 4; i >= 0; i--) {
if (x == 0) {
s[i] = ' ';
} else {
s[i] = x % 10 + '0';
x = x / 10;
}
}
|
|
|
| |
|
|
|
|
|
Posted: Jun 07, 2012 - 01:40 AM |
|


Joined: Nov 11, 2003
Posts: 3885
Location: Chicago Illinois USA
|
|
| Oh wow. After a busy weekend when I had no time to spend on it... The whole silly project almost works! Somehow, my "16 character lines" are a character too long. |
_________________ Discursive design,
Torby
Some days, it's just not worth chewing through the restraints.
|
| |
|
|
|
|
|