Go Down

Topic: Help with reading string from serial (Read 3626 times) previous topic - next topic

AWOL

'Better' is a tricky concept.
Given a processor with large amounts of memory and a well written String class, String objects would be much simpler for most people to use.
We don't have the luxury of large amounts of memory on the AVR, so Strings can be problematical.
IMHO, it is better to get used to C strings and their methods.

But that's just my opinion.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Nick Gammon


Also by adding '\0' to the char[] and then casting, will it make it a legit String?


No. That simply makes a valid null-terminated C string. You might be able to pass that to a String class constructor however.

Quote
I need the string methods for later on.


Can you demonstrate how exactly?

Quote
I don't quite understand why everyone says char arrays are better than Strings.


Let's say you stick with Strings (not C strings). Then we can pretty confidently predict that in a week or two you will make a post along the lines of "my program hangs after it has been running for a few days". This may not necessarily be due to an underlying bug in the system, but due to memory fragmentation.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nate711

How can I return a char array in a method? For example:
Code: [Select]

loop() {
   char[50] foo;
   foo = aMethod();
}

char[] aMethod() {
   char[50] rar = {'a','b','c','d'};
   return rar;
}

GoForSmoke

string.h for C strings, as opposed to String.h for C++ strings, has a nice set of string-manipulation routines.

http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

All a C string is is a byte array with a 0 (byte=0, not character '0') on the end. Only 1 byte overhead.
It's very simple and direct, easy to manipulate with or without a set of special functions. Very hands-on.

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

PaulS

Quote
How can I return a char array in a method? For example:

You can't. In that example, rar is a local variable, allocated on the heap. When the function ends, the heap can be overwritten at any time. Having a pointer to that memory is not a useful thing to have. It is what you would have, though, if you returned rar from the function.

What you need to do is pass a pointer to an array to the function, and have the function populate the pointed to array.

Code: [Select]
void aMethod(char *arrayToPopulate)
{
  arrayToPopulate[0] = 'a';
  arrayToPopulate[1] = 'b';
  arrayToPopulate[2] = 'c';
  arrayToPopulate[3] = 'd';
}


Then call it:
Code: [Select]
   char[50] foo;
   aMethod(foo);

GoForSmoke

Once again, beat to the draw!

Nate, do you know about scope and about pointers?

Here's another version of what Paul wrote:
You're going to have a problem with that. aMethod() is allocating an array that will go out of scope when aMethod() ends. Even if you pass a pointer back it will be worthless.

What you can do:
It would be better if you set up your buffer as a global. That way it's allocated once, stays where you put it and visible to the rest of your sketch.

char  foo[50]; // here is the array, foo is the pointer


Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Nate711

Thanks. I have limited knowledge of pointers, but I can understand this. In another part of my program, I use the String method indexOf. What is the equivalent for c strings? On the link goforsmoke posted, it has a method strchr which returns a pointer to that character or null if it isn't found. How can use the pointer to find the index? I can always make a for loop,  but as long as the method's there I might as well use it. Thanks!

Nick Gammon

You know the start of the string, you know where it was found, the difference is the index.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

PaulS

Quote
How can use the pointer to find the index?

Why do you need the index? What will you do with it, if you have it?

There are a number of ways to get it. You have a pointer to the character at some location. You have a pointer to the start of the string. Pointer arithmetic is possible, resulting in the index.

If you are trying to parse the string, skip the indexOf mess, and use strtok() to parse it.

Nick Gammon

Hey what a guess! Looking at the source for the String class:

Code: [Select]
int String::indexOf( char ch, unsigned int fromIndex ) const
{
  if ( fromIndex >= _length )
    return -1;

  const char* temp = strchr( &_buffer[fromIndex], ch );
  if ( temp == NULL )
    return -1;

  return temp - _buffer;
}

Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

GoForSmoke

#40
Nov 13, 2011, 01:54 am Last Edit: Nov 13, 2011, 02:08 am by GoForSmoke Reason: 1

Thanks. I have limited knowledge of pointers, but I can understand this. In another part of my program, I use the String method indexOf. What is the equivalent for c strings? On the link goforsmoke posted, it has a method strchr which returns a pointer to that character or null if it isn't found. How can use the pointer to find the index? I can always make a for loop,  but as long as the method's there I might as well use it. Thanks!


Hi Nate.

With an array the indexes don't need a function to get at.

char foo[] = "bar";

foo[0] is 'b', foo[1] is 'a', foo[2] is 'r' ---- the 0,1 and 2 are indexes.

Notice I can get to the data directly. I know where foo[0] is, foo points to it. foo + 1 points to foo[1]
you can simply add to a pointer to offset but be aware you add bytes, with ints you need to add by 2's.

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Nate711

Ah, that makes sense. Goes to show how much I know about pointers ;) Thanks!

GoForSmoke

int idx; // my variable
int *pidx; // a pointer to integer.  with no value set = NULL, you can check, if (pidx == NULL) .....
pidx = &idx; // setting pidx to point at idx, &idx returns the address of idx
*pidx = 4; // assigns 4 to what pidx points to so now idx == 4

Be aware that a pointer as a variable (pidx) may take more bytes than the variable it points to!
Some time I must look in Arduino code. I think that sizeof(pidx) would do. I expect it's 2 bytes.

Here's a nice page on C pointers with a lot more useful info:
http://publications.gbdirect.co.uk/c_book/chapter5/pointers.html

I really like this part:
Quote
If you understand what addresses are, then you will probably have more trouble than those who don't: thinking about pointers as if they were addresses generally leads to grief. What seems a perfectly reasonable address manipulation on processor X can almost always be shown to be impossible on manufacturer Y's washing machine controller which uses 17-bit addressing when it's on the spin cycle, and reverses the order of odd and even bits when it's out of bleach. (Admittedly, it's unlikely that anyone could get C to work an an architecture like that. But you should see some of the ones it does work on; they aren't much better.)


Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

PaulS

Quote
you can simply add to a pointer to offset but be aware you add bytes, with ints you need to add by 2's.

No, this is not true. Adding n to a pointer makes it point to the nth element farther along the array, regardless of the size of the elements pointed to. As long, of course, as the pointer type and the type pointed to are the same.

Go Up