Pages: [1]   Go Down
Author Topic: How do we copy a section of a char array that doesn't start at the beginning?  (Read 1658 times)
0 Members and 1 Guest are viewing this topic.
Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If I want to split a 140 char array into chars of 21 length  for display on an LCD screen, what command/s do I need to do so?



Logged

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have looked through http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html but I can't seem to find anything that will copy from a certain point within the array.
Logged

Offline Offline
God Member
*****
Karma: 19
Posts: 785
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Make a pointer to the element you want to start with and use it as an array name.  It will work just like an array that starts where you pointed to.
Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2732
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

IF the goal is really line wrapping there are other ways to handle this.

--- bill
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1728
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you are trying to text wrap with the gLCD library, that feature will be built into v3.1 which should be ready tonight or tomorrow.
Logged

~Tom~

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

IF the goal is really line wrapping there are other ways to handle this.

--- bill

Care to elaborate? I have a 140 word tweet that regularly changes. I need to draw it across 6 21 character lines at the bottom of a sparkfun color LCD shield.

Any method you have of doing this will be an education to me.

If you are trying to text wrap with the gLCD library, that feature will be built into v3.1 which should be ready tonight or tomorrow.

That's great news Tom. I'll keep an eye out for it. The more methods I learn, the quicker I'll stop asking questions and be able to help more.
Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2732
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

IF the goal is really line wrapping there are other ways to handle this.

--- bill

Care to elaborate? I have a 140 word tweet that regularly changes. I need to draw it across 6 21 character lines at the bottom of a sparkfun color LCD shield.

Any method you have of doing this will be an education to me.
A simplistic way would be printing a single character a time from your string.
When you have printed the number of characters
on a line (21 in this case) drop to the next line

The current gLCD code looks like it support newline processing so when ready to drop to the next line
simply send a newline '\n' before continuing to print the remaining characters.

--- bill

Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2732
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you are trying to text wrap with the gLCD library, that feature will be built into v3.1 which should be ready tonight or tomorrow.

I'm curious how you will handle this.
There are many little issues and options related to wrapping, newline vs <CR> processing, and how
to handle things when you reach the very last character of a line and the bottom line of a text area.
For example, does <CR> wrap back to column 0?  To allow easy over writing of the line.
If so, you can can't drop the cursor position to the next line until you print the next character *after*
the wrap point.
Otherwise you won't be able to draw a full line of text and overwrite it by using <CR>.

Does the full line of text on the line being wrapped to get fully erased when an auto wrap/newline occurs?

Then there is the issue of how to handle wrapping of the very last line.
Does the text area scroll after that, does the text wrap to the top line or does it just start
throwing away the text.

The most painful to deal with is supporting a single line text area.
Users want and expect to be able to do this:
lcd.println("my new line");
And have each line show up erasing the previous line.
But technically if you process the newline as you see it, and support scrolling, or automatically
erasing a line that is wrapped to, you end up scrolling out the very line that they just printed.

In the big picture, handling this single line case is the same as having to deal with allowing
printing of a full line when you support erasing the line wrapped to.
You have to defer the wrap and newline processing until *after* the next character after the wrap
point is printed.

Lots of little details to think about.

--- bill
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1857
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If I want to split a 140 char array into chars of 21 length  for display on an LCD screen, what command/s do I need to do so?
Memcpy is your friend:

Code:
#include <string.h>

static const int lcd_width = 20;

void print_large_array (const char *array, size_t len)
{
    char small_array[lcd_width+1];

    if (len == 0)
        len = strlen (array);                // figure out length if not passed

    while (len > 0) {
        // only print 20 characters per line
        size_t len2 = (len > lcd_width) ? lcd_width : len;
        memcpy ((void *)&small_array[0], (void *)array, len2);
        small_array[len2] = '\0';          // add terminating null for println
        lcd.println (small_array);
        array += len2;                        // reset pointer/len for next iteration
        len -= len2;
    }
}

Note, that memcpy assumes the source and destination do not overlap.  If they do overlap, you should use memmove instead.

Alternatively if you are using the raw array and not a pointer to it, you could do it as:

Code:
#include <string.h>

static const int lcd_width = 20;

void print_large_array (const char *array, size_t len)
{
    char small_array[lcd_width+1];
    size_t start = 0;

    if (len == 0)
        len = strlen (array);                // figure out length if not passed

    while (len > 0) {
        // only print 20 characters per line
        size_t len2 = (len > lcd_width) ? lcd_width : len;
        memcpy ((void *)&small_array[0], (void *)&array[start], len2);
        small_array[len2] = '\0';          // add terminating null for println
        lcd.println (small_array);
        start += len2;                        // reset pointer/len for next iteration
        len -= len2;
    }
}

This program logically does:

Code:
static const int lcd_width = 20;

void print_large_array (const char *array, size_t len)
{
    size_t i;
    char small_array[21];

    if (len == 0)
        len = strlen (array);                // figure out length if not passed

    while (len > 0) {
        size_t len2 = (len > lcd_width) ? lcd_width : len;
        for (i = 0; i < len2; i++)
            small_array[i] = array[i];

        small_array[len2] = '\0';
        lcd.println (small_array);
        array += len2;                        // reset pointer/len for next iteration
        len -= len2;
    }
}
« Last Edit: October 12, 2012, 12:45:43 pm by MichaelMeissner » Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1728
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you are trying to text wrap with the gLCD library, that feature will be built into v3.1 which should be ready tonight or tomorrow.

I'm curious how you will handle this.
There are many little issues and options related to wrapping, newline vs <CR> processing, and how
to handle things when you reach the very last character of a line and the bottom line of a text area.
For example, does <CR> wrap back to column 0?  To allow easy over writing of the line.
If so, you can can't drop the cursor position to the next line until you print the next character *after*
the wrap point.
Otherwise you won't be able to draw a full line of text and overwrite it by using <CR>.

Does the full line of text on the line being wrapped to get fully erased when an auto wrap/newline occurs?

Then there is the issue of how to handle wrapping of the very last line.
Does the text area scroll after that, does the text wrap to the top line or does it just start
throwing away the text.

The most painful to deal with is supporting a single line text area.
Users want and expect to be able to do this:
lcd.println("my new line");
And have each line show up erasing the previous line.
But technically if you process the newline as you see it, and support scrolling, or automatically
erasing a line that is wrapped to, you end up scrolling out the very line that they just printed.

In the big picture, handling this single line case is the same as having to deal with allowing
printing of a full line when you support erasing the line wrapped to.
You have to defer the wrap and newline processing until *after* the next character after the wrap
point is printed.

Lots of little details to think about.

--- bill

Basically text wrapping is part of the font. In order to have compatibility with older programs that don't expect wrapping:
setFont(someFont);
prints the font with text wrapping disabled.

To turn it on, you would use this:
setFont(someFont, WrapText);
Where wrapText is a #defined constant. It will automatically turn off again next time you set the font.


If the text goes beyond the bottom of the screen, in the current version it is just truncated. The size returned from the write() function in arduino 1.0+ is reduced to the number of characters actually printed.
When the end of a line is reached, if there is not enough space on the line for another character, the rest of the line from the end of the prior character to the edge of the screen is filled with the background colour (unless the background is transparent), and the character is printed just below on the next line.
Conversely if a '\n' is used to drop to a new line, the end of the line (from the end of the last character on the line to the edge of the screen) is not filled in the background colour.

At the moment it doesn't account for whole words, so it just chops the string mid word. In future versions I may add the ability to wrap in a way which keeps whole words together, but to keep printing as fast as possible, this is not yet implemented.

Furthermore, the last line of a wrapped string does not currently blank the full line, only what is needed. I might add an option to allow the bounding box of the printed text to be set to the background colour.
Logged

~Tom~

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1728
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm afraid you may have to wait until Monday or Tuesday for version 3.1 as I had to work Saturday, so didn't get a chance to finish writing the new examples.
Logged

~Tom~

Reading, Berkshire
Offline Offline
Full Member
***
Karma: 2
Posts: 132
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If I want to split a 140 char array into chars of 21 length  for display on an LCD screen, what command/s do I need to do so?

This program logically does:

Code:
static const int lcd_width = 20;

void print_large_array (const char *array, size_t len)
{
    size_t i;
    char small_array[21];

    if (len == 0)
        len = strlen (array);                // figure out length if not passed

    while (len > 0) {
        size_t len2 = (len > lcd_width) ? lcd_width : len;
        for (i = 0; i < len2; i++)
            small_array[i] = array[i];

        small_array[len2] = '\0';
        lcd.println (small_array);
        array += len2;                        // reset pointer/len for next iteration
        len -= len2;
    }
}

Thanks. I found this works, although due to having to draw a graphic.box to the screen before each line of code, I can't have it scrolling very fast. This seems to be interfering with my Ethernet connection as it's holding up my loop();
Logged

Pages: [1]   Go Up
Jump to: