passare un vettore ad una funzione (risolto)

Ciao
Volevo migliorare la comprensione di come vengono passati i valori a una funzione
Devo passare i valori contenuti in una matrice ad una funzione che restituisce un vettore.
Questo è un estratto dallo sketch

...
magnetic[0] = magnetic_x;
  magnetic[1] = magnetic_y;
  magnetic[2] = magnetic_z;

   for (int k = 0; k < 3; k++)
    {
      transformation(magnetic);
    }
...

volevo capire se per ogni valore di k una parte della funzione verrebbe a questo punto calcolata 3 volte è corretta?

Questa è la funzione:

void transformation(float uncalibrated_values[3])
{
  // float calibrated_values[3];
  //calibration_matrix[3][3] is the transformation matrix
  //replace M11, M12,..,M33 with your transformation matrix data
  double calibration_matrix[3][3] =
  {
    {1.171, -.035, -.02},
    { -.064, 1.215, -.009},
    {.051, -.058, 1.228}

    //  {M11, M12, M13},
    // {M21, M22, M23},
    // {M31, M32, M33}
  };
  //bias[3] is the bias
  //replace Bx, By, Bz with your bias data
  double bias[3] =
  {
    6.423, 1.096, -14.26

    //  Bx,
    //  By,
    //  Bz
  };

  //calculation
  for (byte i = 0; i < 3; ++i)
  {
    uncalibrated_values[i] = uncalibrated_values[i] - bias[i];
  }

  float result[3] = {0, 0, 0};

  for (byte i = 0; i < 3; ++i)
    for (byte j = 0; j < 3; ++j)
    {
      result[i] += calibration_matrix[i][j] * uncalibrated_values[j];
    }

  for (byte  i = 0; i < 3; ++i)
  {
    calibrated_values[i] = result[i];
  }
}

Gli array sono passati alle funzioni per indirizzo, quando modifichi l'array nella funzione la modifica "si vede anche fuori"!

Nel ciclo for con K richiami la funzione 3 volte, quindi tutto il codice della funzione verrà ripetuto tre volte!
Tu gli passi un array come parametro che viene modificato dalla funzione, lo passi la prima volta e cambiano i suoi valori, lo passi la secondo e la terza con valori sempre diversi, perché ad ogni chiamata a funzione i valori dell'array cambiano.

Cosa esattamente non ti è chiaro ?

nella funzione ci sono dei cicli FOR e volevo purtroppo essere sicuro che questi cicli vengono ripetuti tutti le volte
Ho appena provato a portare fuori parte della funzione e messa nello sketch e i risultati a parità di posizione e orientamento del sensore sono diversi

ho modificato la chiamata in questo modo:

for (int k = 0; k < 3; k++)
  {
    transformation(magnetic_x, magnetic_y, magnetic_z);
  }

ho modificato la funzione in questo modo:

void transformation(uncalibrated_values[0], uncalibrated_values[1], uncalibrated_values[2])
{
...

ma non compila:

Arduino:1.8.5 (Windows 10), Scheda:"Arduino Nano, ATmega328P"

magsensorCAL:235: error: variable or field 'transformation' declared void

 void transformation(uncalibrated_values[0], uncalibrated_values[1], uncalibrated_values[2])

                     ^

D:\Arduino sketches\magsensorCAL\magsensorCAL.ino: In function 'void loop()':

magsensorCAL:138: error: 'transformation' was not declared in this scope

     transformation(magnetic_x, magnetic_y, magnetic_z);

                                                      ^

D:\Arduino sketches\magsensorCAL\magsensorCAL.ino: At global scope:

magsensorCAL:235: error: variable or field 'transformation' declared void

 void transformation(uncalibrated_values[0], uncalibrated_values[1], uncalibrated_values[2])

                     ^

exit status 1
variable or field 'transformation' declared void

Questo report potrebbe essere più ricco di informazioni abilitando l'opzione
"Mostra un output dettagliato durante la compilazione"
in "File -> Impostazioni"

questo è tutto lo sketch:

/*
  I2C comunication
  to read from registers
  magnetic sensor HMC5883L alias gy271

  CS pin 3v3
  SDA pin SDA +10k to 3v3
  SDO pin GND
  SCL pin SCL +10k to 3v3
  3v3 VCC
  GND GND
*/
#include <Wire.h>
#define DEVICE (0x1E)//HMC5883L_ device addressE
#define TO_READ (13)//num of bytes-1 we are going to read each time

byte buff[TO_READ];    //n bytes buffer for saving data read from the device

#define HMC5883L_Configuration_Register_A_    (0x00)  //  Read/Write
#define HMC5883L_Configuration_Register_B_    (0x01)  //  Read/Write
#define HMC5883L_Mode_Register                (0x02)  //  Read/Write
#define HMC5883L_Data_Output_X_MSBRegister    (0x03)  //  Read
#define HMC5883L_Data_Output_X_LSBRegister    (0x04)  //  Read
#define HMC5883L_Data_Output_Z_MSBRegister    (0x05)  //  Read
#define HMC5883L_Data_Output_Z_LSBRegister    (0x06)  //  Read
#define HMC5883L_Data_Output_Y_MSBRegister    (0x07)  //  Read
#define HMC5883L_Data_Output_Y_LSBRegister    (0x08)  //  Read
#define HMC5883L_Status_Register_             (0x09)  //  Read
#define HMC5883L_Identification_Register_A_   (0x0A)  //  Read
#define HMC5883L_Identification_Register_B_   (0x0B)  //  Read
#define HMC5883L_Identification_Register_C_   (0x0C)  //  Read

char* reg[] =
{
  "HMC5883L_Configuration_Register_A_",
  "HMC5883L_Configuration_Register_B_",
  "HMC5883L_Mode_Register",
  "HMC5883L_Data_Output_X_MSBRegister",
  "HMC5883L_Data_Output_X_LSBRegister",
  "HMC5883L_Data_Output_Z_MSBRegister",
  "HMC5883L_Data_Output_Z_LSBRegister",
  "HMC5883L_Data_Output_Y_MSBRegister",
  "HMC5883L_Data_Output_Y_LSBRegister",
  "HMC5883L_Status_Register_",
  "HMC5883L_Identification_Register_A_",
  "HMC5883L_Identification_Register_B_",
  "HMC5883L_Identification_Register_C_"
};

byte reg_[] =
{
  HMC5883L_Configuration_Register_A_,
  HMC5883L_Configuration_Register_B_,
  HMC5883L_Mode_Register,
  HMC5883L_Data_Output_X_MSBRegister,
  HMC5883L_Data_Output_X_LSBRegister,
  HMC5883L_Data_Output_Z_MSBRegister,
  HMC5883L_Data_Output_Z_LSBRegister,
  HMC5883L_Data_Output_Y_MSBRegister,
  HMC5883L_Data_Output_Y_LSBRegister,
  HMC5883L_Status_Register_,
  HMC5883L_Identification_Register_A_,
  HMC5883L_Identification_Register_B_,
  HMC5883L_Identification_Register_C_
};

int _hmc5883_Gauss_LSB_XY;
int _hmc5883_Gauss_LSB_Z;

float _magData_x, magnetic_x;
float _magData_z, magnetic_z;
float _magData_y, magnetic_y;;
float _mag_vector;

float magnetic[3];
float calibrated_values[3];
float uncalibrated_values[3];

byte SENSORS_GAUSS_TO_MICROTESLA;

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  //Turning on the sensor

  _hmc5883_Gauss_LSB_XY = 1100.0;
  _hmc5883_Gauss_LSB_Z = 980.0;

  SENSORS_GAUSS_TO_MICROTESLA = 100;

  writeTo(DEVICE, reg_[0], 0b00010000); //enter register value
  writeTo(DEVICE, reg_[1], 0b00000000); //enter register value
  writeTo(DEVICE, reg_[2], 0b00000000); //enter register value

  for (int k = 0; k < 3; k++)
  {
    readFrom(DEVICE, reg_, TO_READ, buff); //read the acceleration data from the sensor

    Serial.println(reg[k]);
    Serial.print(k);
    Serial.print('\t');
    Serial.print("0x");
    Serial.print(reg_[k], HEX);
    Serial.print('\t');
    Serial.print(buff[k], BIN);
    Serial.println();
    delay(200);//It appears that delay is needed in order not to clog the port
  }
}

void loop()
{
  //  Serial.println("START++++++++++++++++++++++++++++++++++++++++++++++");

  for (int k = 0; k < TO_READ; k++)
  {
    readFrom(DEVICE, reg_, TO_READ, buff); //read the acceleration data from the sensor
    // delay(200);//It appears that delay is needed in order not to clog the port
  }

  _magData_x = buff[4] | (buff[3] << 8);
  //Serial.println(buff[4]);

  _magData_y = buff[8] | (buff[7] << 8);
  //Serial.println(_magData_y);

  _magData_z = buff[6] | (buff[5] << 8);
  //Serial.println(_magData_z);


  magnetic_x = _magData_x / _hmc5883_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
  magnetic_y = _magData_y / _hmc5883_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
  magnetic_z = _magData_z / _hmc5883_Gauss_LSB_Z * SENSORS_GAUSS_TO_MICROTESLA;

  for (int k = 0; k < 3; k++)
  {
    transformation(magnetic_x, magnetic_y, magnetic_z);
  }
  /*
    double calibration_matrix[3][3] =
    {
      {1.171, -.035, -.02},
      { -.064, 1.215, -.009},
      {.051, -.058, 1.228}

      //  {M11, M12, M13},
      // {M21, M22, M23},
      // {M31, M32, M33}
    };
    //bias[3] is the bias
    //replace Bx, By, Bz with your bias data
    double bias[3] =
    {
      6.423, 1.096, -14.26

      //  Bx,
      //  By,
      //  Bz
    };

    //calculation
    for (byte i = 0; i < 3; ++i)
    {
      magnetic[i] = magnetic[i] - bias[i];
    }

    float result[3] = {0, 0, 0};

    for (byte i = 0; i < 3; ++i)
      for (byte j = 0; j < 3; ++j)
      {
        result[i] += calibration_matrix[i][j] * magnetic[j];
      }
    for (byte  i = 0; i < 3; ++i)
    {
      calibrated_values[i] = result[i];
    }
      /



    Serial.print(calibrated_values[0]);
    Serial.print('\t');
    Serial.print(calibrated_values[1]);
    Serial.print('\t');
    Serial.println(calibrated_values[2]);


    // _mag_vector = pow((pow(calibrated_values[0], 2) + pow(calibrated_values[1], 2) + pow(calibrated_values[1], 2)) , 0.5);
    //  Serial.println(_mag_vector);


    /*
      Serial.flush();
      Serial.print(magnetic_x);
      Serial.print(",");
      Serial.print(magnetic_y);
      Serial.print(",");
      Serial.print(magnetic_z);
      Serial.println();
  */
  delay(200);//It appears that delay is needed in order not to clog the port
}//fine loop

///////////////////////////////////////////////////////////////////////////////////
void readFrom(int device, byte reg_address, int num, byte buff[])
{
  Wire.beginTransmission(device); //start transmission to device
  Wire.write(reg_address);        //sends address to read from
  Wire.endTransmission(); //end transmission

  Wire.beginTransmission(device); //start transmission to device (initiate again)
  Wire.requestFrom(device, num);    // request TO_READ bytes from device

  int i = 0;
  while (Wire.available())   //device may send less than requested (abnormal)
  {
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
}

///////////////////////////////////////////////////////////////////////////////////
void writeTo(int device, byte reg_address, byte val)
{
  Wire.beginTransmission(device); //start transmission to device
  Wire.write(reg_address);        // send register address
  Wire.write(val);        // send value to write
  Wire.endTransmission(); //end transmission
}

////////////////////////////////////////////////////////////////////////////////////
void transformation(uncalibrated_values[0], uncalibrated_values[1], uncalibrated_values[2])
{
  // float calibrated_values[3];
 ...}

non compila no, nella definizione della funzione devi dichiarare il tipo del parametro (float, int, ecc.) tu stai solo indicato tre parametri senza il tipo e comunque la dichiarazione anche se metti il tipo stai chiedendo tre array. Il problema non è come avevi dichiarato la prima funzione ma in quello che facevi all’interno, non ha senso passare un array diviso in tre parti.
Il consiglio è quello di farcire la funzione che esegue la trasformazione dei valori nell’array con messaggi di debug per capire dove sta l’errore logico

ho scelto di passare i 3 valori per non far ripetere inutilmente i calcoli nella funzione a parità di posizione e orientamento del sensore

questa è la chiamata:

transformation(magnetic_x, magnetic_y, magnetic_z);

questa la funzione:

void transformation(float uncalibrated_values[0], float uncalibrated_values[1], float uncalibrated_values[2])
{...

purtroppo ancora non comprendo perchè non compila, ho confrontato con altre funzioni, questa è la prima volta che provo con i vettori

@stefa24 mi pare sei un pò in confusione per quanto riguarda la logica

o passi un array di float (e magari anche quanti elementi contiene) (A)

oppure passi semplicemente 3 float ad una funzione (B), quindi nella chiamata metti le singole celle del vettore e nella funzione NESSUNA quadra, la funzione accetta 3 float e basta. Se poi gli passi 3 float non da un array non gli cambia nulla.

Per quello che devi fare mi sembra meglio il caso (B)
Quindi hai semplicemente la funzione

void transformation(float a,float b,float c) { qui elaboro}

e la chiamata

transformation(1.2 , 3.2 , 4.5);    oppure transformation(uncalibrated_values[0],uncalibrated_values[1],uncalibrated_values[2]);

Stai passando alla funzione transformation tre valori che hai definito come float.
La funzione però l'hai definita in modo tale da richiedere tre array di tipo float, il primo di lunghezza zero (e qui hai già un errore un array di lunghezza zero è inamissibile), il secondo di lunghezza 1 e il terzo di lunghezza 2.
Chiaro che le due cose non sono compatibili, passi float a un parametro di tipo array di float e il compilatore è infastidito da questo.
In più dentro transformations lavori su array quindi vedi tu, nid69ita mi ha anticipato, ma cambiare la firma della funzione non ti risolverà il problema di logica che hai all'interno della stessa. Rinnovo il consiglio di tornare sui tuoi passi e analizzare la funzione di trasformazione per trovare l'errore grazie a messaggi di debug

scusate ma mettendo un indice non serve anche per accedere ad una determinata posizione del vettore?

stefa24:
scusate ma mettendo un indice non serve anche per accedere ad una determinata posizione del vettore?

ripeto. la tua funzione VUOLE semplicemente 3 float.
void transformation(float a,float b,float c) { qui elaboro}

Se i tre valori che gli passi li prendi da un array, oppure 3 variabili non array o anche 3 costanti... al compilatore non interessa.

Se invece fai una funzione trasform a cui passi un array di float, allora è diverso.

Questo ti da errore
void transformation(float uncalibrated_values[0], float uncalibrated_values[1], float uncalibrated_values[2])
{...
ed è giusto. Quello è la definizione della funzione, NON può essere legata alle variabili che userai.
La funzione quando la definisci DEVE essere una cosa generica.
void transformation(float a,float b,float c) { qui elaboro}

stefa24:
scusate ma mettendo un indice non serve anche per accedere ad una determinata posizione del vettore?

Si se stai leggendo il valore

float a = arrayDiFloat[0]; //Leggo la posizione zero dell'array e la assegno alla variabile a

no se stai definendo la variabile o un paremtro di una funzione, in tal caso dichiari quanto è grande l'array

float arrayDiFloat[5]; //Dichiari un array di lunghezza 5 di tipo float
void laMiaFunzione(float vettoreDaElaborare[2]){...} //Dichiari una funzione che non ritorna nulla che ha come parametro un array di float di lunghezza 2

I casi sono due: o tu hai una funzione che opera su un numero (che poi sia un elemento di array non é importante) e allora le devi passare un numero
O tu hai una funzione che opera su un intero array in una singola chiamata, allora la chiami una volta sola passandole tutto l'array. Io per completezza modificherei la funzione si da passarne anche la lunghezza dell'array, così da non avere problemi di lettura (o peggio scrittura) da o in posti strani della memoria.
Se sei nel primo caso la sintassi é
For (qualcosa che cicli fino alla lunghezza dell'array)
{
funzione (array[variabile in for]);
}

Nel secondo é

Funzione (array);

@fabpolli occhio che non puoi passare la dimensione del vettore
il gcc stranamente compila sta bruttura
void laMiaFunzione(float vettoreDaElaborare[2]){…}
ma secondo me non considera il 2 tra parentesi.

Tieni conto che il compilatore ragiona e “traduce” il tutto con puntatore
void laMiaFunzione(float *vettoreDaElaborare){…}
che può dire dove inizia il vettore in memoria ma non quanti elementi sono

Un array lo passi tutto, alla logica del programmatore sta trovare un modo per indicare quanti elementi sono validi, o con altro parametro oppure (come per le stringhe classiche) ultimo elemento con valore speciale (0 per le stringhe)

Intanto ringrazio
la situazione è questa, nello sketch ho un ciclo FOR, per 3 valori che devo passare a una funzione, in questa funzione ho dei cicli FOR che è inutile che vengano ripetuti a parità di posizione e orientamento del sensore magnetico
Questo nel SETUP()

int _hmc5883_Gauss_LSB_XY;
int _hmc5883_Gauss_LSB_Z;

float _magData_x, magnetic_x;
float _magData_z, magnetic_z;
float _magData_y, magnetic_y;
float _mag_vector;

float magnetic[3];
float calibrated_values[3];
//float uncalibrated_values[3];

nel LOOP()

magnetic[0] = magnetic_x;
magnetic[1] = magnetic_y;
magnetic[2] = magnetic_z;

  for (int k = 0; k < 3; k++)
  {
   transformation(magnetic);
  }

nella funzione TRANSFORMATION

void transformation(float uncalibrated_values[])
{
  // float calibrated_values[3];
  //calibration_matrix[3][3] is the transformation matrix
  //replace M11, M12,..,M33 with your transformation matrix data
  double calibration_matrix[3][3] =
  {
    {1.171, -.035, -.02},
    { -.064, 1.215, -.009},
    {.051, -.058, 1.228}

    //  {M11, M12, M13},
    // {M21, M22, M23},
    // {M31, M32, M33}
  };
  //bias[3] is the bias
  //replace Bx, By, Bz with your bias data
  double bias[3] =
  {
    6.423, 1.096, -14.26

    //  Bx,
    //  By,
    //  Bz
  };

  //calculation
  for (byte i = 0; i < 3; ++i)
  {
    uncalibrated_values[i] = uncalibrated_values[i] - bias[i];
  }

  float result[3] = {0, 0, 0};

  for (byte i = 0; i < 3; ++i)
    for (byte j = 0; j < 3; ++j)
    {
      result[i] += calibration_matrix[i][j] * uncalibrated_values[j];
    }

  for (byte  i = 0; i < 3; ++i)
  {
    calibrated_values[i] = result[i];
  }
byte i = 0;
i++;
Serial.println(i);
  
}

non ho errore ma mi sembra di avere dei cicli FOR ripetuti inutilmente

Ma... @stefa24 sta funzione è void !!
Che cosa deve fare ? Occhio che se passi un array, allora puoi modificare gli elementi dell'array,
se fai funzione con 3 parametri float... devi passarli per referenza !!

stefa24:
non ho errore ma mi sembra di avere dei cicli FOR ripetuti inutilmente

No, assolutamente nessuna ripetizione inutile. Tu nel calcolo hai per forza dei giri su 3 celle

Al massimo possiamo dire che la funzione da per scontato che il vettore che gli passi DEVE avere 3 celle. Se per caso gli passi un array di float con sole 2 celle... potrebbe dare un bel crash perchè il compilatore non verifica che tu vai a leggere ma soprattutto a scrivere OLTRE alla seconda cella.

nid69ita:
@fabpolli occhio che non puoi passare la dimensione del vettore
il gcc stranamente compila sta bruttura

Si hai ragione ma sono stato tratto in inganno proprio da gcc (ho fatto una prova al volo su pc)
E anche il resto è perfettamente corretto (si potrà dire???) infatti tutte le funzioni standard richiestono il parametro di lunghezza del vettore per le motivazioni che hai giustamente indicato tu

nid69ita:
Ma... @stefa24 sta funzione è void !!
Che cosa deve fare ? Occhio che se passi un array, allora puoi modificare gli elementi dell'array,
se fai funzione con 3 parametri float... devi passarli per referenza !!

grazie per la pazienza
questa funzione corregge i 3 valori grezzi che arrivano dal sensore mediante una matrice 3x3, è qui che nasce la mia perplessità, se devo passare un vettore dimensione [3], lo passo a un vettore dimensione [3], se uno un FOR nello sketch la funzione viene richiamata 3 volte per calcolare gli stessi valori.

Mettendo dei Serial.print ho capito che posso passare il vettore senza il ciclo FOR

Ho fatto così nel LOOP:

  transformation(magnetic, k);
  k++;

nella funzione:

void transformation(float uncalibrated_values[], byte k)
{

ho provato a portare fuori le istruzioni della funzione e le ho messe direttamente nello sketch:

 magnetic_x = _magData_x / _hmc5883_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
  magnetic_y = _magData_y / _hmc5883_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
  magnetic_z = _magData_z / _hmc5883_Gauss_LSB_Z * SENSORS_GAUSS_TO_MICROTESLA;

  magnetic[0] = magnetic_x;
  magnetic[1] = magnetic_y;
  magnetic[2] = magnetic_z;

  //  for (byte k = 0; k < 3; k++)
  //  {
  //    transformation(magnetic, k);
  // }
  /*
        Serial.print(magnetic[0]);
        Serial.print('\t');
        Serial.print(magnetic[1]);
        Serial.print('\t');
        Serial.println(magnetic[2]);
        Serial.println();
  */
  //  transformation(magnetic, k_);
  //  k_++;

  double calibration_matrix[3][3] =
  {
    {1.171, -.035, -.02},
    { -.064, 1.215, -.009},
    {.051, -.058, 1.228}
  };
  //bias[3] is the bias
  //replace Bx, By, Bz with your bias data
  double bias[3] =
  {6.423, 1.096, -14.26};

  //calculation
  for (byte i = 0; i < 3; ++i)
  {
    magnetic[i] = magnetic[i] - bias[i];
  }

  float result[3] = {0, 0, 0};

  for (byte i = 0; i < 3; ++i)
    for (byte j = 0; j < 3; ++j)
    {
      result[i] += calibration_matrix[i][j] * magnetic[j];
    }
  for (byte  i = 0; i < 3; ++i)
  {
    calibrated_values[i] = result[i];
  }

  Serial.print(calibrated_values[0]);
  Serial.print('\t');
  Serial.print(calibrated_values[1]);
  Serial.print('\t');
  Serial.println(calibrated_values[2]);
  Serial.println();


  //  _mag_vector = pow((pow(calibrated_values[0], 2) + pow(calibrated_values[1], 2) + pow(calibrated_values[1], 2)) , 0.5);
  // Serial.println(_mag_vector);

  delay(200);//It appears that delay is needed in order not to clog the port

ma ho risultati diversi:

 Serial.print(calibrated_values[0]);
  Serial.print('\t');
  Serial.print(calibrated_values[1]);
  Serial.print('\t');
  Serial.println(calibrated_values[2]);
  Serial.println();

da quelli che ottengo utilizzando la funzione, eppure ho verificato con SERIAL che i valori passati alla funzione sono i medesimi:

 magnetic[0] = magnetic_x;
  magnetic[1] = magnetic_y;
  magnetic[2] = magnetic_z;

qualcuno riesce a vedere l’errore

Tanto per cominciare un elemento in un array bodomensionale si chiaro ama con due indici
Es:
byte bidim [3][3]={...}
//dichiarazione
budim[0][0]
//primo elemento
bidim[1][0]
//secondo elemento
bidim[0][1]
//quarto elemento
Ecc

Inoltre "ma ho risultati diversi" potrebbe implicare che uno sia giusto ed uno sbagliato. Quale dei due é quello giusto? E una vilta capito ciò usa il metodo che lo fornisce. Se invece entrambi sono sbagliati per favore dicci in italiano che calcoli vuoi fare, perché, almeno io, non lo ho capito, e quindi tutto quello che é sintatticamente giusto (e visto che carica é tutto sintatticamente giusto) potrebbe essere soluzione.

Inoltre non ho capito il nesso tra "ma ho risultati diversi" e quella serie di Serial.print, sarebbe (se proprio) più utile conoscere cosa scrivono. Ma vedi punto precedente.
Scusa se sembro duro