HELP-Assigning data in a struct

Hello all,

I am quite new to Arduino, so forgive my newbieness … but we all have been here.
I used to program in Progress, some SQL, MySQL and php, but C++ (arduino C++ to be exact), is a bit confusing, especially the arrays and pointers, which I cannot get my head around.

I am writing a program to monitor temperature and humidity in different ‘rooms’ with different ‘containers’. Based on some minimum, optimum and maximum values, I need to turn on a heater, fan or cooling. And so on…

I am new to structs and have a lot of problems with arrays and assigning a value into an array, as one might be a char, another a int or String…

#define LOCSENS 4

typedef struct {
 char location[3]; // Value 1
 byte locnumber;   // Value 2
 char senstype[2]; // Value 3
 char roomsens[5]; // STORE HERE THE VALUES 1,2,3 (location+locnumber+sensytpe)
}record_type;

record_type record[LOCSENS] = {
 {"ER",0,"T"},
 {"NR",0,"T"},
 {"GR",0,"T"},
 {"PR",0,"T"}
};

void setup() {
 Serial.begin(9600);
}  
void loop() {
 PrintLocSens(); 
 delay(1000);
}
void PrintLocSens() {
 for (byte y = 0; y < LOCSENS-1; y++) {

   // THIS IS NOT WORKING ... :-( PLEASE HELP !

   record[y].roomsens = String(record[y].location + record[y].locnumber + record[y].senstype);

   // OUTPUT SHOULD BE: ER0T / NR0T / GR0T / PR0T
   Serial.println(record[y].roomsens);
 }
}

I get the following error with this code:
error: invalid operands of types ‘char*’ and ‘char [2]’ to binary ‘operator+’

It seems I cannot use ‘+’ to append these values.
If I take out the "String(…) I get this error (which makes a bit more sense, but still doesn’t point me in the right direction…

error: incompatible types in assignment of ‘char [3]’ to ‘char [5]’

I tried some other things, but most of them generated other errors.
I assume there should be an easy way to do this…

Can anybody give me a hint how to do this?

Thanks guys…

Instead of writing random drivel and hoping it will work, or copying bits of other code with zero understanding of them, study a book or online tutorial. You will save time that way.

There are two methods of representing "text" in C/C++. The original method is an array of type char. This consists of a series of consecutive memory locations, each of which has a char in it. In order for most functions to work, the last element of the array has to have the binary value 0 in it. The variable which is the name of the array is actually a pointer to the first location in the array.

The second method of representing text, is the various implementations of the String class. The actual data storage method is quite similar, but the methods for manipulating the Strings are different. Not all implementations of the String class allow concatenation with the + operator.

You can convert text representations from one type to the other, but you cannot just mix them up randomly.

If you want to print the contents of your record, you would write

Serial.print( record[y].location );
Serial.print( record[y].locnumber );
Serial.print( record[y].senstype );
Serial.print( record[y].roomsens );        // if this actually has a value in it.

If you have implemented the printf( ) function, you could use

record_type* p = &record[y] ;
printf(" %s %d %s %s\n", p->location, p->locnumber, p->senstype, p->roomsens );

which is less typing.

To concatenate your three values into one char array,
you could try something like this

sprintf( record[y].roomsens,"%2s%1d%1s", record[y].location, record[y].locnumber, record[y].senstype );

But be very careful about not writing beyond the end of your char[5] array. And also be careful that the array has a binary 0 in the last element, before you try printing it.

Alternatively, I suggest you learn what strcpy() and strcat() will do for you.

Roskam:
I used to program in Progress, some SQL, MySQL and php, but C++ (arduino C++ to be exact), is a bit confusing, especially the arrays and pointers, which I cannot get my head around.

The short answer is this: LMGTFY - Let Me Google That For You

The slightly longer answer is:

1: C++ is built around the idea that computers have memory which is a long sequence of individual char or byte values, each of which has a memory address. A pointer is a two, or four, or eight-byte quantity whose value is one of these addresses.

2: Every pointer has a type. You don't simply have a "pointer", you have a "pointer to int" or a "pointer to struct mystruct". When you add 1 to a pointer, the value of the pointer (the memory address) gets incremented by the size of the thing that the pointer is pointing at. This size is not stored in memory with the pointer - it's a thing that the compiler keeps track of. Indeed, you can simply tell the compiler to treat a pointer to int as though it were a pointer to char. Of course - the compiler will complain about this. So we use "pointer to void" to mean an untyped pointer.

3: arrays are a contiguous block of N whatevers in memory. When you use the name of an array in an expression, then C treats this as an expression of type "pointer to the zeroth element of the array". So a[3] is exactly the same as *(a+3). Treat 'a' as a pointer to mystruct, add three times the size of mystruct to that memory address, and dereference.

4: the language contains no bounds-checking on arrays or pointer arithmetic. If you declare an array of 20 chars, the libraries will quite happily copy a string of length 20 into it. This will cause whatever happened to be in memory at the locations beyond the lenght of the array to get stomped all over. You - the programmer - have to cope with this situation and prevent it from happenning.

5: It is meaningful to have "a pointer to an array of 10 chars". When you add 1 to this, the memory address is incremented by 10. This is how multidimensional arrays are done. int a[10][10] creates an array of 10 arrays of 10 ints. When you use a in an expression, then its type is "pointer to an array of 10 ints", aka int (*)[0];

6: structs are simply a compile-time template for chopping up a chunk of memory into named subsections. There's nothing in memory to identify a particular chunk of memory as belonging to some specific struct. It's all just bytes.

char a[10][10];
char (*p)[10] = a;

//sizeof(a) is 100.
//sizeof(p) is probably 4.
//sizeof(*a) is 10.
//sizeof(*p) is also 10.

Of course, there's quite a bit more to it. But in C, arrays and pointers aren't opaque handles (although you should treat them like they are). They are a physical offset into addressable RAM with a compile-time type.

Mostly.

7: a pointer to an array of 10 things is not the same as an array of 10 pointers to things.

a; // a is a variable
a[10]; // a is an array of 10 somethings
*(a[10]); // a is an array of 10 pointers to something
int *(a[10]); //  a is an array of 10 pointers to int. This is a legal declaration
int *a[10]; //  because of operator precedence, we can omit the parens
a; // a is a variable
*a; // a is pointer to something
(*a)[10]; // a is a pointer to an array of 10 somethings
int (*a)[10]; // a is a pointer to an array of 10 ints. This is a legal declaration
// because of operator precedence, we cannot omit the parens

Thanks!

I should read a book, I know... and maybe I will.

I read about the printf method, and I am aware that I need to use extra libraries in that case (overhead). Therefore I was hoping to find another solution.

I need to add this information into 1 variable (or array value) to be able to rewrite several if-then-else statements and work more with 'for' loops as it is not only about to print the output...
Maybe I should hard code these values, as I am already putting the all the information into array variables, but of course it is also to learn more about handling these arrays and structs.

The real code where I want to inplement this already is quite extended and with my Arduino UnoR3 I am already running almost out of memory.. (670 lines)
I am rewriting the code, to make better use of the functions and with this struct method I hope to be able to combine several parts of the code and combine them. Instead of asking 'if (location = ER0T) {do this) else {do that}', I want to have more structure in my codeand work with for loops.

As a beginner with Arduino and using relays, RTC, several temp sensors I just began with some code that works and now trying to optimize it...

I will try with printf (with the additional libraries) and let you know how it goes. Also will try the strcpy() and strcat() as I already saw these somewhere, but did try them yet!

And PaulMurrayCbr, also thanks for the info. Will get into it tomorrow...

Keep you posted... !