Searching \ for ' CCS - printing strings' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=ccs+printing+strings
Search entire site for: 'CCS - printing strings'.

No exact or substring matches. trying for part
PICList Thread
'[PICLIST] CCS - printing strings'
2000\10\19@182652 by Lawrence Lile

flavicon
face
I am trying to printf a series of strings in a program in CCS C on a
PIC16C715  (my circuit prints to a serial LCD)  something like this:

Switch (state){
   Case 0:
           Printf("Pancakes");
           Break();
   Case 1:
           Printf("Eggs");
           break();
   Case 3:
           Printf("Bacon");
           break();
   Case 4:
           Printf ("Biscuits");
           Break;
   etc. etc. etc.
}

(actually it is about a dozen cases - you get the idea.)

The entire Switch Case Printf routine takes up a whopping 700 bytes in my
program.  I thought it might be less memory intensive to do something like
this, but I can't figure out the correct syntax:


char Stuff[16];

Switch (state){
   Case 0:
           Stuff ="Pancakes";   // this is not the proper syntax - won't
compile
           Break();
   Case 1:
           Stuff="Eggs";
           break();
   Case 3:
           Stuff = "Bacon";
           break();
   Case 4:
           Stuff = "Biscuits";
           Break;
}
printf("%C", stuff);   // this is not the proper syntax  - won't compile



You get the idea - set up a variable with the proper text string, then call
ONE printf statement at the end.   What is the correct way to achieve this
result?

This is actually two questions:

1.  How do you set an array to a string?

and

2. How do you print a variable that is an array of characters?

-- Lawrence Lile



-- Lawrence Lile
Sr. Project Engineer
Salton inc. Toastmaster Div.
573-446-5661 Voice
573-446-5676 Fax

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
"[PIC]:","[SX]:","[AVR]:" =uP ONLY! "[EE]:","[OT]:" =Other "[BUY]:","[AD]:" =Ads




2000\10\20@005226 by Dale Botkin

flavicon
face
On Thu, 19 Oct 2000, Lawrence Lile wrote:

{Quote hidden}

Yeah, that will take a LOT of space.  I just finished a project with a lot
of string handling, and it's a beastly size.

{Quote hidden}

Switch (state){
   Case 0:
           strcpy(Stuff,"Pancakes");
           Break();
   Case 1:
           strcpy(Stuff,"Eggs");
           break();
   Case 3:
           strcpy(Stuff,"Bacon");
           break();
   Case 4:
           strcpy(Stuff,"Biscuits");
           Break;
}
puts(stuff);

You can do puts(Stuff) or use printf(Stuff).  puts() is samller in this
case; sometimes it's not.  It will put a CR/LF after the output though.
By the way -- in my quick test, strcpy() in the switch/case bit will save
you 2 bytes of code space per case over printf().  Oddly, though, if I
used all puts() calls it was larger than using printf()!  Go figure.  A
lot of the time I find I can do something one of several ways; I usually
try all of them and see which one the compiler likes best, as evidenced by
the smallest code.  Yeah, I know, that may not be fastest; sue me, I
usually don't care.

Dale
---
The most exciting phrase to hear in science, the one that heralds new
discoveries, is not "Eureka!" (I found it!) but "That's funny ..."
               -- Isaac Asimov

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\20@012122 by Brett Testerman

flavicon
face
Here is a solution if your strings are fairly close in length.

Given your example below, do this:

declare a 2 dimensional array,[number_of_strings] [max_string_length+1], and have
the compiler initialize it. Remember, when declaring a string constant to not forget
the hidden NULL that trails it.

char strings[4][9] = {"Pancakes","Eggs","Bacon","Buscuits"};

then always check to make sure your index is in range, and print if it is:

if ( (state >=0) && (state <=3) )
   printf("%s",strings[state]);

The problem with this method is there are nine bytes of storage allocated for "Eggs"
and "Bacon", but only 5 and 6 bytes, repectivly, of those entries are used and there
is no way of recovering the lost bytes. Since a case statement requires the compiler
to generate a series of tests they tend to generate a lot of code, so even with the
lost bytes, this way can be much more efficient.


I have been a lurker on this list for a while now and want to thank everyone for all
the wonderful hints and advice. You are all a bunch of professionals, and it shows.
I hope I can contribute more in the future.

Brett




Lawrence Lile wrote:

{Quote hidden}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\20@092132 by Lawrence Lile

flavicon
face
I've been avoiding PUTS() because (in CCS at least) it adds a CR/LF tot he
end of my string.  This doesn't work on my serial LCD - prints two chars of
garbage.

Maybe I'll have to figure out how to hack the PUTS() routine to delete this
feature.  [Looks up the STDIO.H file....]

Uh oh..  In CCS C puts() is defined as:

#define puts(s) {printf(s); putchar(13); putchar(10);}

This is definitely not more efficient!

Lawrence



{Original Message removed}

2000\10\20@094241 by Lawrence Lile

flavicon
face
Wow!  Brett, that looks reqally efficient - I'm going to race it against
some other ideas right now and see how they all work.

-- Lawrence

{Original Message removed}

2000\10\20@102902 by Lawrence Lile

flavicon
face
Alas, CCS has no idea what to do with the statement Printf(+ACIAJQ-S+ACI-....
Although this works in ANSI C, (sparking the tiresomne CCS C vs ANSI C
debate..)
it isn't an option in CCS.

On the other hand,
Printf(+ACIAJQ-C+ACI-, stuff+AFs-state+AF0-)+ADs-
Just prints a garbage character or two, so this isn't it either.

-- Lawrence



{Original Message removed}

2000\10\20@111729 by Brett Testerman

flavicon
face
Lawrence,

I have noticed that you want a carraige return/line feed after the string. To do
that, just change the printf to:

printf("%s\r\n",strings[state]);

Also, someone else may have pointed this out already, but to copy one NULL
terminated char buffer to another you use the strcpy() function, and to
concatenate one buffer to another use the strcat() funtion. Make sure your
destination buffers are big enough! If your buffers are not NULL terminated or
contain NULL's, use the mem...() functions, which include a length parameter.
These are all part of the standard C library.

You don't get to use the "=" and "+" operators on char arrays until you move to
C++. That's when you get the string class.

Brett



Lawrence Lile wrote:

> Wow!  Brett, that looks reqally efficient - I'm going to race it against
> some other ideas right now and see how they all work.
>
> -- Lawrence
>
> {Original Message removed}

2000\10\20@133346 by rich+piclist
flavicon
face
> char strings[4][9] = {"Pancakes","Eggs","Bacon","Buscuits"};
>
> The problem with this method is there are nine bytes of storage allocated for "Eggs"
> and "Bacon", but only 5 and 6 bytes, repectivly, of those entries are used and there
> is no way of recovering the lost bytes. Since a case statement requires the compiler
> to generate a series of tests they tend to generate a lot of code, so even with the
> lost bytes, this way can be much more efficient.
So how about:

const char *strings[] = {"Pancakes","Eggs","Bacon","Biscuits"};

No wasted ROM that way.

== Rich

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\20@133559 by mike

flavicon
face
On Fri, 20 Oct 2000 08:20:59 -0500, you wrote:

>I've been avoiding PUTS() because (in CCS at least) it adds a CR/LF tot he
>end of my string.  This doesn't work on my serial LCD - prints two chars of
>garbage.
>
>Maybe I'll have to figure out how to hack the PUTS() routine to delete this
>feature.  [Looks up the STDIO.H file....]
>
>Uh oh..  In CCS C puts() is defined as:
>
>#define puts(s) {printf(s); putchar(13); putchar(10);}
>
>This is definitely not more efficient!
>
>Lawrence
Printf is sufficiently general-purpose that for most small embedded
apps it is overkill and uses way too much memory for the parts of it
you're likely to need, and you'd usually be a lot better off using
your own code  to provide just  the functions you need.
e.g. for strings
void dispstring(char *sptr)
{ do  dispchar(*sptr++);   while (*sptr != 0x00); }
numerics and fixed-point decomals are also pretty straightforward and
can be coded with a lot less code than printf. Again you can limit the
numeric code to just the functionality you need.
--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




'[PIC]: CCS - printing strings THANKS'
2000\10\20@160621 by Lawrence Lile

flavicon
face
Thanks folks! I've got a handle on efficient pritning of strings now in CCS:

I wrote a program with 3 writes of a string to the serial port (and some
other activity) , and raced them:

with printf("Some Text")        396 bytes ROM
using strcpy(array, "Some Text"); printf(array);   370 Bytes ROM
using strcpy(array, "Some Text"); putstring(array)  339 bytes ROM.

Each additional instance of PrintF("text") seems to add a massive amount of
wasted memory as compared to printf(array) or putstring(array).


Conclusions:

1. Printf is not very efficient.
2. strcpy(array,"text") is a handy way of stuffing a line of text into an
array for later printing and
3. The following routines putstring() and PutLCD are more efficient than
Printf at sending a string to an RS232 port.


I added these two routines to my string.H file for future reference
putstring() and PutLCD()

// Putstring is much more efficient than printf  (with thanks to Bob
Ammerman!!)
// for  printing text strings to a serial LCD for example.
// You must declare an array of characters like this:
// char array[16];
// or whatever size then call by stating
//   strcpy(array,"This Text!");
//        putstring(array);

void putstring(char  *p)
{
     while (*p){
        putchar(*p++);}
}


///////////////////////////////////////////////////////////////////////////
//// PutLCD will also optionally clear or home the Scott Edwards LCD screen
before printing
// useful defines would be:
//  #define ClearLCD  1
//  #Define ToLine1LCD  2
//  #Define ToLine2LCD 3

// Example:
// char array[16];
//  strcpy(array, "print THIS!");
// putLCD(array, ToLine1LCD);


void putLCD(Char *P, int setting){

putc(0xFE); // escape character
switch setting{
Case 0:
break;
Case 1:
 putc(0x01); // clear screen command
 delay_ms(1); // delay becuase screen is disabled 1 ms
break;
Case 2:

 putc(0x80);  // goto line 1
break;

Case 3:

 putC(0xC0); // Goto line 2
break;

}
     while (*p){
        putchar(*p++);}
}

}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\20@181632 by Blars Blarson

flavicon
face
In article <001301c03a98$967d2dc0$spam_OUT3501010aTakeThisOuTspamtoastmaster.com> you write:

>Uh oh..  In CCS C puts() is defined as:
>
>#define puts(s) {printf(s); putchar(13); putchar(10);}

Not only is this ineffeciant, it's just plain wrong.
It will not work correctly if your string contains a % character.
--
Blars Blarson                                   .....blarsonKILLspamspam@spam@blars.org
                               http://www.blars.org/blars.html
"Text is a way we cheat time." -- Patrick Nielsen Hayden

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\20@204045 by Bill Westfield

face picon face
Pointers.  Pointers are variables that hold the address of an object in
memory, rather than the object itself.  Pointers are an efficient way of
handling large objects.  Pointers are how you usually deal with dynamically
allocated objects (however, this was my first exposure to pointers (in PL/1
and Pascal), and it took be AGES to "get it", because so few of my programs
actually used dynamically allocated objects.)

In C, pointers are important and more common because C does not have any
native "string" data type, nor any defined operations for strings (which
follows, eh?) (However, the compiler has a string CONSTANT type.  Go
figure.)  Pointers are a common and preferred way to deal with text
strings in C.

Now, it's not clear whether pointers make sense (even for strings) on a
PIC processor.  The (low and midrange) PICs don't really have an
architecture that supports pointers very well (at all?)  (arguably, the
PIC does not have 'memory' of the sort that pointers normally point to
at all, just "registers.")  This means that the compiler has to do some
fancy footwork to implement pointers (or even to implement strings, come
to think of it.)  Whether it will do a good job is something you have to
learn by looking at the code that it produces when you try.  (or by
asking people who have done so.)


>> char strings[4][9] = {"Pancakes","Eggs","Bacon","Buscuits"};
>>
>> The problem with this method is there are nine bytes of storage
>> allocated for "Eggs" and "Bacon", but only 5 and 6 bytes, repectivly,
>> of those entries are used and there is no way of recovering the lost bytes.
>
> const char *strings[] = {"Pancakes","Eggs","Bacon","Biscuits"};
>
> No wasted ROM that way.

Um.  The first case "wastes" several bytes of each string that is shorter
than the max.  The second case "wastes" space to store the pointers to the
strings.  Which is worse will depend on circumstances.

I've been known to do things like:

char strings[] = "Pancakes\0Eggs\0Bacon\0Buscuits\0Other\0";
#define STRING_PAN 0
#define STRING_EGG 1
#define STRING_BAC 2
#define STRING_BUS 3

/*
* print the Nth (stringID) null-delimitted substring of the big string.
* Note that the end of the big sting should have a double null.
*/
void printstring (int stringID)
{
   int i=0;
   /*
    * Find the (1st character of) the Nth string.
    */
   while (stringID > 0) {
       while (strings[i] != 0) {       /* Look for separator */
           i++;                        /* Next character */
       }
       i++;                    /* Skip the separator */
       if (strings[i] == 0)
           return;             /* End of big string is an error! */
       stringID--;             /* next substring */
   }
   /*
    * Should be pointing to first character of the desired string.
    * Now output that string...
    */
   while (strings[i] != 0) {
       putchar(strings[i]);
       i++;
   }
   /*
    * Here, we could purchar CRLF if we wanted
    */
}

(This code has not been compiled or tested!!)

This sort of thing can save quite a bit of string space, depending on
assorted unknowns (number of strings, how they compile down, etc.)  (at
the expense of CPU time, of course.  Since strings tend to be human UI
things, and PICs tend to be pretty zippy compared to people, you
probably have the CPU time to spare.)

It looks like a lot of code, but a fair number of those while loops
ought to turn out to be just a couple of PIC instructions each, and
there's likely to be a pretty good match up with the way constants might
actually be stored on a PIC (ie as a series of RETLW instructions.)  In
the worst case, you can write printstring() in assembler...

You can (maybe) do tricks with C syntax that may or may not help the
compiler, like
       while (putchar(strings[i++])) ;
but ... extreme care is advised.  (hint: this short version is not quite
the same as the longer form further up the page.  Also, putchar might be
a macro, and it can be a bad idea to use ++ and similar on macro arguments.)

BillW

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\20@233817 by rich+piclist

flavicon
face
> > const char *strings[] = {"Pancakes","Eggs","Bacon","Biscuits"};
> >
> > No wasted ROM that way.
>
> Um.  The first case "wastes" several bytes of each string that is shorter
> than the max.  The second case "wastes" space to store the pointers to the
> strings.  Which is worse will depend on circumstances.
True. The savings is more obvious if:

const char *strings[] = {"Pancakes","Eggs","Bacon","Biscuits","corned beef
hash with a side of bacon and a pot of black coffee"};

:)

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics




2000\10\21@082237 by Peter L. Peres

picon face
I don't know about CCS but in normal C you can have an array of strings
that is automagically allocated and initialized by the processor like so:

char *strings[] = {
"bananas",
"ananas",
 "foo",
 NULL
};

Depending on the compiler implementation this can make an array of [4][8]
chars, thus wasting a lot of them. You can do this if your strings are
(nearly) the same length.

You can also use an external tool to compile a list of strings efficiently
and generate a vector of pointers into it. This has the advantage of being
capable to merge tail-overlapping strings (bananas and ananas above could
share the same address space). The input to your tool is a list of strings
with a key each (or the key is the position in the list, so it can be
missing) like:

0 "bananas"
1 "ananas"
2 "foo"

and the output is:

/* string 0 made from file ... by toolname */
str_0_0="bananas";
str_0_1=str_0_0+1;
str_0_2="foo";

/* string 0 access array made by toolname */
char *str0[3]={ str_0_0, str_0_1, str_0_2 };

to use this for printing you can do:

puts(str0[2]);

which is what you initially wanted. Note that you can develop using the
array of strings method and then later use the tool to compact. I have
never used the tool on a PIC I wrote it for a Z80 based project that was
very short on EPROM. My tool also mangled the strings for copy protection
enhancement but that is another story. I had 256 bytes string space so I
had an array of uchar as index cast to char* for use.

hope this helps,

Peter

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.




2000\10\23@095821 by Lawrence Lile

flavicon
face
Wait-a-minute+ADs-  Pointers are analgous to using the INDF register on a PIC,
no?  The INDF register is a pointer to other registers, and can be useful in
things like lookup tables, aclulating averages and medians, etc.  (Dim light
beginning to shine in brain)

-- Lawrence Lile


{Original Message removed}

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...