usare le strutture di dati ..

Salve ... un caro saluto a tutti ....

all'inizio delle skech definisco questa struttura

struct righe {
char sql[5] = "0000";
char ptt[5] = "0000";
char rit[5]  = "0000";
char mat[21] = "00000000000000000000";
char aux[5] = "0000";};

poi in uns funzione, richiamata dal loop, defiinisco una'altra struttura così:

void faiPagina(int pg, int su, int az)

 struct nn {
 char nome;
 righe riga[4];} modoN;

... quindi il mio raggrupamento di variabili modoN, che al suo interno contiene riga [4], che à a sua volta definito in una struttura, è composta da tutte le seguenti variabili che compongono la struttura medesima:

modoN.nome,
modoN.riga[0].sql, modoN.riga[0].ptt, modoN.riga[0].rit, modoN.riga[0].mat, modoN.riga[0].aux,
modoN.riga[1].sql, modoN.riga[1].ptt, modoN.riga[1].rit, modoN.riga[1].mat, modoN.riga[1].aux,
modoN.riga[2].sql, modoN.riga[2].ptt, modoN.riga[2].rit, modoN.riga[2].mat, modoN.riga[2].aux,
modoN.riga[3].sql, modoN.riga[3].ptt, modoN.riga[3].rit, modoN.riga[3].mat, modoN.riga[3].aux,

ancora:
fuori da questa funzione definisco anche un'altra funzione

void leggiModo(int n) {

al cui interno c'è la seguente struttura

struct  mm {char nome; righe riga[4];} N;

cioe esattamente uguale all'altra ma di nome N ...
che poi termina con il classico

return N;

La domanda è:
perchè se dentro la prima funzione voglio fare la seguente assegnazione, cioè assegnando alla struttura modoN la risposta della fuzione leggiModo, in questo modo ...

 modoN = leggiModo(repeaterModeChange);

non funge e mi dà il seguente errore

no match for 'operator=' (operand types are 'faiPagina(int, int, int)::nn' and 'void')

pekkè .. pekkè???
non riesco a capire ... direi che deve funzionare .. o no???

ho anche provato così:

... all'inizio definisco queste strutture:

  struct r {
char sql[5] = "0000";
 char ptt[5] = "0000";
 char rit[5] = "0000";
 char mat[21] = "00000000000000000000";
 char aux[5] = "0000";};

struct righe {
char nome;
 r riga[4];};

poi in una fuznione definisco le mie variabili

       righe modoN;

........
........ e faccio questa assegnazione

 modoN = leggiModo(repeaterModeChange);

mentre nella seconda funzione faccio

void leggiModo(int n) {
 righe N;
........
.......
return N;

ma non funziona pekkè????

Il problema è il void... Se definisci la funzione così non puoi ritornare un valore.
Ti conviene passare alla funzione un puntatore alla struttura invece di ritornare il valore con return.

Inoltre non puoi sperare che il compilatore sappia come assegnare ad una struct nn una struct mm.

Definisci solo una delle due come tipo:

struct nn {
// campi vari
};

Poi dichiara modoN di tipo nn:

nn modoN;

Anche la tua funzione dovrà ritornare un tipo nn, ovviamente.

@frat
ho tolto il void ed ho definito anche la funzione con "righe" .... ma non funge lo stesso ...

@sukko
quello che mi suggerisci l'ho già provato .... scritto nel secondo post ... dove ho definito la struct "righe"

adesso faccio così, dichirando la funzione leggiModo di tipo righe

righe leggiModo(int n) {
righe N;
.......
.......
return N;}

naturalmente anche dentro la funzione che chiama leggiModo faccio così:

......
......
righe modoN;
modoN = leggiModo(repeaterModeChange);
.......
.......

ma mi da comunque errore
'righe' does not name a type .. riferendosi alla dichiarazione della fuznione righe leggiModo(int n);

.... mi date una dritta su come usare i * e i & ..... perchè mi sono sempre rimasti indigesti????

Posta lo sketch intero in cui fai come ho detto io, perché evidentemente sbagli qualcosa.

@sukko .... lo sketch e grosso ... si puo allegare un file qui?

Certo, oppure mettilo su pastebin o simili.

ho caricato tutto lo sketc … e diviso in diversi fogli
dagli un’occhiata

come scheda metti la mega … con il 328 non si puo…

nel foglio variabili definisco le strutture

nel foglio e_pagine c’è la funzione void faiPagina(int pg, int su, int az){

all’interno della quale c’è

    case 5: // pg 5  ********************************************************************************************
    
 .......
       righe modoN;
  
       modoN = leggiModo(repeaterModeChange);

[/code]
mentre nel foglio funzioni c’è

righe leggiModo(int n) {

  righe N;
  
  .....
return N;
};

… aspetto suggerimenti :slight_smile:

LAN_test_28_09_2017.ino.zip (7.54 KB)

Dovrebbe funzionare. Forse devi #includere il file variabili in quello funzioni. Non so di preciso come Arduino gestisca molteplici file .ino.

Non oserei mai contraddire Sukko che è evidentemente più ferrato di me sul c...
Ma provare con qualcosa tipo

void leggiModo(righe* N, int n) {
}

Anch'io ho sempre fatto casino con * e & ma dovrebbe funzionare...

Funziona sicuro, ed è pure meglio, ma non c'è motivo per cui non debba funzionare nell'altro modo!

@sukko … nel nuovo allegato ho rimesso in ordine i vari fogli.ino … il compilatore li compila esattamente nell’ordine in cui appaiono …
sostanzialmente equivalgono ad un unico file.ino che li raccoglie tutti in sequenza naturale …
naturalmente il file che devi aprire (per caricarli tutti) e quello che ha lo stesso neome della cartella … ok ???
cio detto e premesso che:
nella parte variabili ho:

struct r {char sql[5] = "0000"; char ptt[5] = "0000"; char rit[5] = "0000"; char mat[21] = "00000000000000000000"; char aux[5] = "0000";};
struct righe {char nome; r riga[4];};

nella parte funzioni ho:

struct righe leggiModo(int n) {
  righe N;
 
.....
.....
return N;
 
};

nella parte pagina d2 ho:

void faiPagina(int pg, int su, int az){

................
...............

    case 5: // pg 5  ********************************************************************************************
    
...........
...........
       righe modoN;
       modoN = leggiModo(repeaterModeChange);

............
............

ma non funge lo stesso, adesso mi da questo errore …

Arduino:1.8.4 (Windows 7), Scheda:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"
D:\0_ARDUINO\Arduino_script\LAN test\LAN_test_28_2_09_2017.ino\d2_pagine.ino: In function 'void faiPagina(int, int, int)':
d2_pagine:154: error: crosses initialization of 'righe modoN'
        righe modoN;
              ^
d2_pagine:154: error: crosses initialization of 'righe modoN'
d2_pagine:154: error: crosses initialization of 'righe modoN'
d2_pagine:154: error: crosses initialization of 'righe modoN'
xit status 1
crosses initialization of 'righe modoN'
Questo report potrebbe essere più ricco di informazioni abilitando l'opzione
"Mostra un output dettagliato durante la compilazione"
in "File -> Impostazioni"

@fratt… e @sukko quindi se passo alla funzione faiPagina sia l’indice che la struttura da riempire poi posso rileggere la struttura riempita dopo la chiamata a faiPagina ??? … sto capendo bene???

LAN_test_28_2_09_2017.ino.zip (7.79 KB)

ma prima devo dichiarare un puntatore alla struttura???

@sukko
@fratt

... help me!!!!

Aspetta conferma anche da sukko...
Nella definizione della funzione toglierei struct (lascia solo righe leggiModo...)

Con l'altra soluzione, tu crei la variabile N di tipo righe fuori dalla funzione leggiModo. Quando passi N come parametro il * dopo righe nella definizione della funzione fa in modo che non venga creata una copia di N interna alla funzione, ma venga usato un puntatore alla variabile passata. Così se modifichi N dentro la funzione te la ritrovi modificata anche fuori.

Spero si capisca... E spero anche sia tutto corretto...

... risolto

ho studiachiato un po ieri notte ..

quando devo modificare più di un dato (in una strutture e sempre così) conviene passare i dati alla funzione per puntatore anzichè per valori.. passando i valori, deve duplicare ogni byte e se abbiamo poche risorse, come nei nostri microcontrollori puo essere rilevante un metodo o un altro .. questo dicono i testi sacri ....

quindi creo la struttura laddove mi serve, allocandogli lo spazio in memoria, invoco la funzione che deve agire sulla struttura passandogli il puntatore (tra gli altri parametri), quindi la funzione agisce sulla strttura raggiunta tramite il puntatore e la puo aggiornare. La struttura aggiornata è utilizzabile dal punto in cui ho chiamato la funzione per modificarla ....
riassumendo

  1. nella parte variabili (prima del setup) definisco le strutture

struct r {char sql[5] = "0000"; char ptt[5] = "0000"; char rit[5] = "0000"; char mat[21] = "00000000000000000000"; char aux[5] = "0000";}; // definisco un tipo di struttura r
struct righe {char nome; r riga[4];}; // definisco un tipo di struttura righe .... che contiene anche la precedente

  1. dove mi occorre la struttura faccio:
    righe modoN; // definisco la mia variabile di tipo struct righe.. quindi viene allocata la memoria. da questo momento esiste la mia variabile ..
    struct righe *pt_righe; // definisco un puntatore per il tipo di variabile struct righe
    pt_righe = &modoN; // associo il puntatore che ho creato alla mia variabile modoN. da questo momento il puntatore contiene l'indirizzo di memoria del primo byte della struttura ....

  2. quando mi serve che la struttura sia aggiornata invoco la funzione per la modifica cosi:
    leggiModo(pt_righe, repeaterModeChange); // il primo parametro è il puntatore alla mia variabile di tipo struct righe.. necessario affinche dentro la fuznione sia possibile agire sulla mia variabile di tipo struct

  3. la funzione che modifica la struttura è:
    void leggiModo (struct righe *N, int n) { // ricevo il parametro puntatore definendolo di tipo struct righe e lo chiamo *N perchè è un puntatore...
    quindi agisco sulla struttura cos':
    N->nome = etc....
    N->riga[r].sql[3-i] =etc...

non capisco perchè non funzione usando la notazione N.nome .... ma va bene lo stesso

ciò è grosso modo quello che ho capito

bene bene ...

saluti

Bravo! Abbi pazienza ma io non ho più avuto tempo di rispondere :(.

grazie ...
@sukko
@fratt

Curiosità, visto che i puntatori li ho studiati tanti tanti anni fa...
Ma è necessario passare per la variabile pt_righe dichiarata come puntatore o si può evitate usando solo & e *?
Poi dove dichiara il puntatore (sia come variabile che come parametro della funzione) è necessario il struct?
Questi argomenti mi erano indigesti qualche decennio fa e lo sono tutt'ora...

fratt:
Curiosità, visto che i puntatori li ho studiati tanti tanti anni fa...
Ma è necessario passare per la variabile pt_righe dichiarata come puntatore o si può evitate usando solo & e *?

No, non è necessario.

fratt:
Poi dove dichiara il puntatore (sia come variabile che come parametro della funzione) è necessario il struct?

Innanzitutto bisogna fare chiarezza sulla sintassi, che dipende dal linguaggio e che qua è un po mescolata. Se faccio:

struct Antani {
  int a;
};

Allora in C ho definito un tipo che si chiama "struct Antani", quindi se voglio dichiarare una variabile di quel tipo devo fare:

struct Antani a;

In C++, invece, si è definito anche il tipo "Antani", che solitamente è quello che si usa:

Antani a;

In sostanza, in C++ struct funziona esattamente come class, con un'unica differenza sulla visibilità di default dei membri, che è public per struct e private per class.

Infine, anche in C è possibile evitare di dover scrivere struct ogni volta, con un trucchetto del tipo:

typedef struct {
  int a;
} Antani;

Per quanto riguarda i puntatori alle struct, valgono le stesse regole appena citate.