Pages: 1 [2] 3   Go Down
Author Topic: Problems on serial.read()  (Read 1473 times)
0 Members and 1 Guest are viewing this topic.
California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3384
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What suggestion you give me with String class??
Don't use it.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And use what?? You didnt tell me the suggestion!!! smiley
Array of bytes, char... ???
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And the reason to not use it.
Can you explain me and give me a tip about how to use what do you think is better in my code?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 616
Posts: 49444
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
And use what?
Isn't that obvious? What are you storing in the String? Hint: It's not doubles, floats, longs, booleans, bytes, or instances of classes.

Quote
And the reason to not use it.
Because it has a destructor. Now, normally having a destructor is a good thing. But, the destructor calls free() to return the memory that it has allocated, and free() has a bug that causes the destruction of memory.

Code:
String Service::converteBeaconParaString(Beacon beacon) {
char buf[10];
sprintf(buf, "%d#%d#%d#", beacon.getDhost(), beacon.getShost(), beacon.getSALTO());
return buf;
}
buf is NOT a String.

buf is a local variable that is going out of scope as soon as the function ends. Returning buf by any means is a bad idea.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The String class suffers from memory management problems and memory leaks.

Use 'C' strings instead i.e. null terminated char arrays. There is a rich library of functions in the C runtime library for dealing with strings, and you can also manipulate them simply by accessing the array elements directly.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok guys, I'll work on it!!!
I would search for C String and choose one wich fits better.

thanks a lot
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4808
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 :0Augusto, before C++ is C which handles text in byte or char arrays longer than the text will be. Always the way the text ends is with a character '\0' which = 0, also called NULL.

So you could have

char hello[ 16 ] = "Hello World";

hello[ 16 ] would be 16 chars == 'H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd' '\0' '\0' '\0' '\0' '\0' '\0'
'H' is also '\72'... here is an ASCII Table:

Once you understand that, spend time learning and getting used to C string functions. You might want to get a book (an old one, at deep discount) on just C language or look online for C tutorials and find the part(s) that deal with strings.
Please note that C strings are *not* C++ String Class Objects. Do not confuse string with String!

Here is the site where Arduino gets C++, link is to the libraries page:
http://www.nongnu.org/avr-libc/user-manual/modules.html

Most C string functions and defines are in the string library. Some are automatic, others you must #include <string.h> to get:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

strcpy() lets you copy strings. You can use it to load a string constant into an array.

char buffer[ 20 ]; // you can cut & paste these lines into a test sketch if you want
strcpy( buffer, "Hello" ); // but you will have to fill in the rest  smiley-twist
Serial.println( buffer );

strcat() lets you add a string to a string.

strcat( buffer, " World" );
Serial.println( buffer );

There are too many for this post, for many uses.

I think of sprintf() as a string command though it is not, but it lets you format text and variables with fine control into a C string. You don't need to include a library but working out how to make the format string, you will want a guide! sprintf() is in stdio (standard in/out):
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

You might want to find a tutorial page depending on your current coding skills, here below is the section from the stdio.h page. Even if you do learn elsewhere, the short tight layout makes a good memory helper for later that fits on a page or screen.  smiley-cool Always keep references for quick check if you have the slightest doubt. To misspell a word or get things out of order means time spent bug hunting, it would be a shame to spend 1 hour finding out you should have spent 1 minute looking up syntax!

Quote
The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the % character. The arguments must properly correspond (after type promotion) with the conversion specifier. After the %, the following appear in sequence:

    Zero or more of the following flags:
        # The value should be converted to an "alternate form". For c, d, i, s, and u conversions, this option has no effect. For o conversions, the precision of the number is increased to force the first character of the output string to a zero (except if a zero value is printed with an explicit precision of zero). For x and X conversions, a non-zero result has the string `0x' (or `0X' for X conversions) prepended to it.
        0 (zero) Zero padding. For all conversions, the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion (d, i, o, u, i, x, and X), the 0 flag is ignored.
        - A negative field width flag; the converted value is to be left adjusted on the field boundary. The converted value is padded on the right with blanks, rather than on the left with blanks or zeros. A - overrides a 0 if both are given.
        ' ' (space) A blank should be left before a positive number produced by a signed conversion (d, or i).
        + A sign must always be placed before a number produced by a signed conversion. A + overrides a space if both are used.

    An optional decimal digit string specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given) to fill out the field width.
    An optional precision, in the form of a period . followed by an optional digit string. If the digit string is omitted, the precision is taken as zero. This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions, or the maximum number of characters to be printed from a string for s conversions.
    An optional l or h length modifier, that specifies that the argument for the d, i, o, u, x, or X conversion is a "long int" rather than int. The h is ignored, as "short int" is equivalent to int.
    A character that specifies the type of conversion to be applied.

The conversion specifiers and their meanings are:

    diouxX The int (or appropriate variant) argument is converted to signed decimal (d and i), unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation. The letters "abcdef" are used for x conversions; the letters "ABCDEF" are used for X conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros.
    p The void * argument is taken as an unsigned integer, and converted similarly as a %#x command would do.
    c The int argument is converted to an "unsigned char", and the resulting character is written.
    s The "char *" argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating NUL character; if a precision is specified, no more than the number specified are written. If a precision is given, no null character need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating NUL character.
    % A % is written. No argument is converted. The complete conversion specification is "%%".
    eE The double argument is rounded and converted in the format "[-]d.ddde±dd" where there is one digit before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the letter 'E' (rather than 'e') to introduce the exponent. The exponent always contains two digits; if the value is zero, the exponent is 00.
    fF The double argument is rounded and converted to decimal notation in the format "[-]ddd.ddd", where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.
    gG The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.
    S Similar to the s format, except the pointer is expected to point to a program-memory (ROM) string instead of a RAM string.

In no case does a non-existent or small field width cause truncation of a numeric field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.

This might be enough to get you started. Hey, I never said this would be a snap but it is something you should learn if you're going to write tight C code for small machines like UNO.

BTW, Good Luck and Good Future to You.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Rio de Janeiro, Brazil
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Augusto,

I think that PaulS response is the probable solution for your problem. The method return is not a String type as declared. Is a array to char. And buf[] is out of scope, because is a local pointer to char. Did you try fix it?

Code:
String Service::converteBeaconParaString(Beacon beacon) {
char buf[10];
sprintf(buf, "%d#%d#%d#", beacon.getDhost(), beacon.getShost(), beacon.getSALTO());
return buf;
}
buf is NOT a String.

buf is a local variable that is going out of scope as soon as the function ends. Returning buf by any means is a bad idea.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys, I've been really diligent to solve this problem and I have to appreciate your help. A good news is that 50% of the problem was solved. In the code I changed what you suggested below on methods "converteBeaconParaString", "enviaBeacon" and "converteStringParaBeacon". Look that in the last now I looking for the "#" ah hand an
Code:
#include "Service.h"

#include "Beacon.h"
#include <stdio.h>
#include <string.h>


short meu_id; //identificação do no raiz

//Estrutura do pacote de controle
Service::Service() {
}

Service::~Service() {/*nothing to destruct*/
}

void Service::enviaBeacon(Beacon beacon) {
if(beacon.getDhost() != 0){
  converteBeaconParaString(beacon);
}
}

Beacon Service::recebeBeacon(short id) {

Beacon beacon;
String msg;

while(Serial.available() > 0) {
byte temp = Serial.read();
if (temp != 255){
msg = msg + (char) temp;
}

}
if (msg.length() > 0) {
  beacon = converteStringParaBeacon(msg);
  delay(1000);
  Serial.flush();

if (verificaMensagemBeacon(beacon,id)) {
return beacon;
}
}
return beacon;
}


void Service::converteBeaconParaString(Beacon beacon){

Serial.print(beacon.getDhost());
Serial.print("#");
Serial.print(beacon.getShost());
Serial.print("#");
Serial.println(beacon.getSALTO());
}


Beacon Service::converteStringParaBeacon(String msg) {
int c=0;
int i=0;
short vet[3];
Beacon beacon;

while (msg[i] == '\0') {
if (msg[i] != '#') {
vet[c] = vet[c] * 10 + (msg[i] - '0');
}
else {
c = c + 1;
}
i = i + 1;
}

beacon.setDhost(vet[0]);
beacon.setShost(vet[1]);
beacon.setSALTO(vet[2]);

return beacon;
}


bool Service::verificaMensagemBeacon(Beacon beacon, short id) {

if (beacon.getDhost() == id) {
  return true;
}

return false;
}

Now, when I send the information from ard_8 -> ard_5, I get what I wanted (2#1#0+1). 50% of the problem solved!!!!
HOWEVER, when I get this information (2#1#0+1) and change de destination for ard_x, the thrird arduino, I get like this (76656#56663#88877)
Really, annoying!!!

Any suggestion?

Thanks a lot folks.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 616
Posts: 49444
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Hi guys, I've been really diligent to solve this problem and I have to appreciate your help.
But, you are ignoring our advice. "Get rid of the String class!". It's still there. "Do not return local variables!" You're still doing it.

You want more help? Fix the problems you currently have, then we'll talk.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey buddy!! Calm down, I'm not ignoring your suggestion. You can note that I am having difficult to solve it!! Could you be a little bit humble and pacient??? I am new here, ok?
I'm being humble, I am always being grateful four your help!!! So, calm down!! If you do not want to help, ok? I think it would have more people wanting to help.
However, I am grateful for your attention to solve my problem.
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3384
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey buddy!! Calm down, I'm not ignoring your suggestion. You can note that I am having difficult to solve it!! Could you be a little bit humble and pacient??? I am new here, ok?
I'm being humble, I am always being grateful four your help!!! So, calm down!! If you do not want to help, ok? I think it would have more people wanting to help.
However, I am grateful for your attention to solve my problem.

You tell him to calm down twice, but you're the one that sounds wound up about this; there was nothing "uncalm" about his post.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4808
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey buddy!! Calm down, I'm not ignoring your suggestion. You can note that I am having difficult to solve it!! Could you be a little bit humble and pacient??? I am new here, ok?
I'm being humble, I am always being grateful four your help!!! So, calm down!! If you do not want to help, ok? I think it would have more people wanting to help.
However, I am grateful for your attention to solve my problem.

Understood by someone, that is me.

But make the changes pointed out in your code before asking for help with it again. This time you left too many undone.

Replace -all- use of C++ Strings with C strings, not just some. You may want to work out the replacement code in other small test sketches that you can test the results before trying to jam it into your problem sketch that you cannot test anything with the way it is now.

There is also problem pointed out of returning the address to buf[] array that goes out of scope when the function it is made in ends. Do you understand what is scope?
Easy fix is to make the buffer global. Global never goes out of scope.

If there is some step you are stuck on then present -only that-, not the whole program.

Best thing I think you can do is write small test sketches to work out one thing at a time. It is far easier than trying to make everything work at once when one problem prevents you from testing the new parts.

Why so many people feel confident to write a mass of code they understand little of and then expect to debug it all together is beyond my understanding.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

0
Offline Offline
Tesla Member
***
Karma: 145
Posts: 9636
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But I really do not know what is happening.
Until you do, you shouldn't be shooting yourself in the foot with the String class.

By the way, snippets-r-us.com is down the internet a ways. Here, we expect to see ALL of your code.

The String class psychic at work! String class causing the issue without seeing all the code!
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4808
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

LOL! Troubleshooting is about simplifying and one way to do that is get rid of needless crap.
Annnnd check the posts, he did post the whole thing on Nov. 16.
 
OTOH he can have both Strings and strings. Surely (cough) there must be space for both?

You can drive a car down the sidewalk, that doesn't make it a good idea.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Pages: 1 [2] 3   Go Up
Jump to: