'Serial.HardwareSerial::read' does not have class type

I am trying to create a script that gets a value from the Serial table and if the data starts with a c (to separate the different types of data) then it sets an int to that value. Here is my script:

void loop()
{
if (Serial.available() > 0)
{
if(Serial.read.startsWith("C"))
{
lockPos = Serial.read();
}
}
}

It keeps giving me an error saying that Serial.read is not a class type. Please let me know if you have an idea of what I am doing wrong. Thanks!

Serial.read is a function, so you need to use

Serial.read()

that returns a character, not a String (capital S), so your way of trying to check if the received data starts with a "C" will not work.

Read Serial Input Bascis to get ideas how to properly use the serial input.

Notes:
1)
If you're using AVR based boards, do not use Sttring (capital S); it can leave holes in your memory where you can hide an elephant in.
2)
Also, in future, do not post snippets.
3)
Lastly, use code tags when posting code.

If you're using AVR based boards, do not use Sttring (capital S); it can leave holes in your memory where you can hide an elephant in.

It has been said in this Forum for many many times that the use of String object in AVR Board might create 'holes inside the memory (RAM/Flash)' and 'memory corruption'; unfortunately, we don't see much examples/clarifications in this regards -- how it can happen?.

I have used the following codes using String object to concatenate few strings. I have still 1826 bytes RAM and 29298 bytes flash left unused!

void setup() 
{
  Serial.begin(9600);
  String str = "";
  str +="Happy";
  str +=" New Year";
  str += " : 2019";
  Serial.println(str);
}

void loop() 
{
  
}

When using c's string function (strcat();), one has to write the following codes; these codes are apparently cumbersome compare to the codes using String. Therefore, many users feel comfort of using String instead of strcat(); particularly, in SD card Programming/data logging. (Unused memory in this example: RAM : 1710 bytes; flash : 30464 bytes.)

void setup() 
{
  Serial.begin(9600);
  char str1[50] = "Happy";
  char str2[50] = " New Year";
  char str3[50] = " : 2019";

  strcat(str1, str2);
  strcat(str1, str3);
  
  Serial.println(str1);
}

void loop() 
{
  
}

I have used the following codes using String object to concatenate few strings. I have still 1826 bytes RAM and 29298 bytes flash left unused!

But is the space contiguous ?
My understanding is as follows :

  String str = "";
  str +="Happy";  //creates a new String holding "Happy"
  str +=" New Year";  //creates a new String holding "Happy New Year" and leaves a hole in memory where "Happy" was stored
  str += " : 2019";  //creates new String holding "Happy New Year 2019" and leaves a hole in memory where "Happy New Year" was

There is no garbage collection so previously used memory is left unused.

GolamMostafa:
When using c's string function (strcat();), one has to write the following codes; these codes are apparently cumbersome compare to the codes using String. ... (Unused memory in this example: RAM : 1710 bytes; flash : 30464 bytes.)

void setup() 

{
  Serial.begin(9600);
  char str1[50] = "Happy";
  char str2[50] = " New Year";
  char str3[50] = " : 2019";

strcat(str1, str2);
  strcat(str1, str3);
 
  Serial.println(str1);
}

void loop()
{
 
}

That is not true.

void setup() {
  Serial.begin(9600);
  char str1[] = "Happy";
  char str2[] = " New Year";
  char str3[] = " : 2019";

  Serial.print(str1);
  Serial.print(str2);
  Serial.println(str3);
}
void loop() {}

Unused  memory in this example: RAM : 1836 bytes; Flash : 30720 bytes.

@Whandall

You have not used the strcat(); function; you have transferred the message directly in the Serial Monitor; the message is not in the memory, and it is not available for further processing?

GolamMostafa:
You have not used the strcat(); function;
you have transferred the message directly in the Serial Monitor;
the message is not in the memory, and it is not available for further processing?

Yes, no strcat and no Strings, but the program is functional identical to your example.
It is the smallest and fastest version of the examples.

Most often there is no need for concatenating things in memory at all to send them together.
In serial communication sending the parts one after another automatically concatentates them,
I see no reason to create an additional copy, wasting memory and code.

Yes, the message is not in memory (besides the copy in the tx ring buffer),
why should it, nobody is using it again.

GolamMostafa:
It has been said in this Forum for many many times that the use of String object in AVR Board might create ‘holes inside the memory (RAM/Flash)’ and ‘memory corruption’; unfortunately, we don’t see much examples/clarifications in this regards – how it can happen?.

You can modify WString.h and WString.cpp

WString.cpp; after

#include "WString.h"

add the below

#include <Arduino.h>
void String::printMemory()
{
  char b[64];
  sprintf(b, "buffer @ %p, len = %u, capacity = %u", buffer, len, capacity);
  Serial.println(b);
}

which will print the 3 important parameters of the String class.

Add the below to WString.h

    void printMemory();

after

// The string class
class String
{
	// use a function pointer to allow for "if (s)" without the
	// complications of an operator bool(). for more information, see:
	// http://www.artima.com/cppsource/safebool.html
	typedef void (String::*StringIfHelperType)() const;
	void StringIfHelper() const {}

public:

You now have a new method that you can use to see what is happening internally in the string class. The below demonstrates

// two strings
String happyNewYear;
String happyEaster;

// a pointer for some dynamic memory allocation;
char *someCharPointer;

// a print buffer
char buffer[64];

void setup()
{
  Serial.begin(57600);

  Serial.print("happyNewyear: "); happyNewYear.printMemory();
  Serial.print("happyEaster:  "); happyEaster.printMemory();

  happyNewYear = "Happy new year";
  happyEaster  = "Happy easter";

  Serial.print("happyNewyear: "); happyNewYear.printMemory();
  Serial.print("happyEaster:  "); happyEaster.printMemory();

  happyNewYear += "Happy new year";
  happyEaster  += "Happy easter";

  Serial.print("happyNewyear: "); happyNewYear.printMemory();
  Serial.print("happyEaster:  "); happyEaster.printMemory();

  someCharPointer = (char*)malloc(16);
  if (someCharPointer == NULL)
  {
    Serial.println("first malloc() failed");
  }
  else
  {
    strcpy(someCharPointer, "xyz");
    sprintf(buffer, "someCharPointer points to %p which contains %s", someCharPointer, someCharPointer);
    Serial.println(buffer);
    free(someCharPointer);
  }

  someCharPointer = (char*)malloc(36);
  if (someCharPointer == NULL)
  {
    Serial.println("second malloc() failed");
  }
  else
  {
    strcpy(someCharPointer, "abc");
    sprintf(buffer, "someCharPointer points to %p which contains %s", someCharPointer, someCharPointer);
    Serial.println(buffer);
    free(someCharPointer);
  }

  happyNewYear = "";
  happyEaster  = "";

  Serial.print("happyNewyear: "); happyNewYear.printMemory();
  Serial.print("happyEaster:  "); happyEaster.printMemory();


}

void loop()
{
}

Output of the first two printMemory calls

happyNewyear: buffer @ 0x2d8, len = 0, capacity = 0
happyEaster:  buffer @ 0x2dc, len = 0, capacity = 0

A buffer (to store text) for each String is allocated at 0x2d8 and 0x2dc respectively.

Next we assign some values to the Strings and printMemory now shows

happyNewyear: buffer @ 0x2e0, len = 14, capacity = 14
happyEaster:  buffer @ 0x2f1, len = 12, capacity = 12

As can be seen, the buffers have moved.

Add something more to the Strings and the result is that the buffers have moved again.

happyNewyear: buffer @ 0x300, len = 28, capacity = 28
happyEaster:  buffer @ 0x31f, len = 24, capacity = 24

So we now have a hole in our memory from 0x2d8 to 0x2ff.

The whole can be filled as shown by the next two malloc statements.

someCharPointer points to 0x2ee which contains xyz
someCharPointer points to 0x2d8 which contains abc

And in the last two lines we can see that even if we ‘reset’ the Strings to empty Strings, the buffers do not move back to their original memory locations.

Play with it, it’s fun. And thanks for asking, I have been planning to study / demonstrate this for a while so this was a good reason.

Yes, the message is not in memory (besides the copy in the tx ring buffer),
why should it, nobody is using it again.

Very very convincing arguments. Thanks+ gladly.

@UKHeliBob

//creates a new String holding "Happy New Year" and leaves a hole in memory where "Happy" was stored

@sterretje
The above quote due to @UKHeliBob has been analytically and elaborately established by @sterretje. I have just gone at a glance through Post#7, and I have found it very thought provoking. I will certainly take more time to make my own note out-of-it so that next time I can present it with confidence that -- I understand the difference between String and string.

If I have followed both of you to some extent, I would like to present my understanding on the concept of 'memory hole' due to String usage by this diagram:

Thanks+ to both @UKHeliBob and @sterretje.

BTW:

Description
Combines, or concatenates two strings into one new String. The second string is appended to the first, and the result is placed in a new String. Works the same as string.concat().

Syntax
string3 = string1 + string 2; string3 += string2;

...and the result is placed in a new String -- is this new String the shifted string?

Run my code with only one String object; I don't think (can't test now) that it demonstrates the behaviour. The code was specifically designed to create a hole.

Inside a String (capital S) is a dynamically allocated c-string (lowercase s).

The reason for the hole is that happyEaster's c-string prevents happyNewYear's c-string to grow; so happyNewYear needs to find space for its c-string somewhere else and it finds that after happyEaster's c-string. But now happyNewYear's new c-string prevents happyEaster's c-string to grow so happyEaster has to find a new space for its c-string and finds that after the new happyNewYear's c-string. And so on.

I've removed happyEaster from my code; the result

happyNewyear: buffer @ 0x2b6, len = 0, capacity = 0
happyNewyear: buffer @ 0x2b6, len = 14, capacity = 14
happyNewyear: buffer @ 0x2b6, len = 28, capacity = 28
someCharPointer points to 0x2d5 which contains xyz
someCharPointer points to 0x2d5 which contains abc
happyNewyear: buffer @ 0x2b6, len = 0, capacity = 28

As I expected and explained above, the c-string in happyNewYear stays at the same place as there is space for the dynamically allocated c-string to grow.