Salve,
vorrei modificare delle funzioni su uno sketch che fanno uso della classe String per farle funzionare con gli array char, ma sto avendo difficoltà... Sono parecchio arrugginito con il C ed i puntatori e malgrado le diverse ore passate davanti allo schermo a leggere esempi e provare a scrivere codice, non ne vengo a capo. Il codice da modificare è questo:
String inString = String((char*)"");
void ServeWebClients()
{
EthernetClient client = server.available(); // Wired
if (client)
{
inString = client.readStringUntil('\n');
client << F("HTTP/1.1 200 OK") << endl;
client << F("Content-Type: text/html") << endl;
client << F("Connection: close") << endl << endl;
#if defined(USE_REM_DISPLAY)
if (Command((char*)"disp")) SendToremDisplay(sensors); // Send data to remote dispplay
#endif
if (Command((char*)"save")) SaveValues();
if (Command((char*)"reset")) ResetValues();
if (Command((char*)"restart")) while(1); // stay here until the watchdog barks
if (Command((char*)"ntp")) UpdateTime(); // reload the ntp time
if (Command((char*)"resetwdc")) eeprom_write_byte ((uint8_t*)EE_CTR, (byte*)0);
if (Command((char*)"resetday")) eeprom_write_byte ((uint8_t*)EE_RESETDAY, (byte*)day());
int i=inString.indexOf("?");
if(i != -1) ReadValue(i);
ShowStatus(client);
client.stop();
}
}
bool Command(char* command)
{
int i = inString.indexOf(command);
if (i == -1) return false;
return true;
}
void ReadValue(int i)
{
// String format is "?0=12345"
// "?3=-12345"
// "?G=12345"
long val = 0;
bool neg = false;
int j = i + 3;
int address = inString[i+1];
if((address >= '0' && address < '9') || (address >= 'A' && address < 'J'))
{
char c = inString[j];
if(c == '-')
{
neg = true;
j ++;
c = inString[j];
}
while(c >= '0' && c <= '9')
{
val = 10 * val + (c - '0');
j ++;
c = inString[j];
}
if(neg) val = -val;
if(address >= 'A') // Address = 'A...'J' to write the total counters
{
sensors[address-'A']->NewTotal(val);
}
else // Address = '0'...'9' to write the day counters
{
// Let the sensor write the value to eeprom
sensors[address-'0']->Update(val);
}
}
}
E quello che ho scritto fino ad ora è questo (ho lasciato le righe commentate del vecchio codice per riferimento):
//String inString = String((char*)"");
char inString[81];
void ServeWebClients()
{
EthernetClient client = server.available(); // Wired
if (client)
{
// inString = client.readStringUntil('\n');
size_t numchars = client.readBytes(inString, 80);
inString[numchars] = '\0'; // terminate the string
client << F("HTTP/1.1 200 OK") << endl;
client << F("Content-Type: text/html") << endl;
client << F("Connection: close") << endl << endl;
#if defined(USE_REM_DISPLAY)
if (Command((char*)"disp")) SendToremDisplay(sensors); // Send data to remote display
#endif
if (Command((char*)"save")) SaveValues();
if (Command((char*)"reset")) ResetValues();
if (Command((char*)"restart")) while(1); // stay here until the watchdog barks
if (Command((char*)"ntp")) UpdateTime(); // reload the ntp time
if (Command((char*)"resetwdc")) eeprom_write_byte ((uint8_t*)EE_CTR, (byte*)0);
if (Command((char*)"resetday")) eeprom_write_byte ((uint8_t*)EE_RESETDAY, (byte*)day());
// int i = inString.indexOf("?");
// if(i != -1) ReadValue(i);
char *i = strstr(inString, "?");
if(i != NULL) ReadValue(i);
ShowStatus(client);
client.stop();
}
}
bool Command(char* command)
{
// int i = inString.indexOf(command);
// if (i == -1) return false;
char *i = strstr(inString, command);
if (i == NULL) return false;
return true;
}
// void ReadValue(int i)
void ReadValue(char *i)
{
// String format is "?0=12345"
// "?3=-12345"
// "?G=12345"
long val = 0;
bool neg = false;
// int j = i + 3;
// int address = inString[i+1];
char *j = i + 3;
char *address = i + 1;
if((address >= '0' && address < '9') || (address >= 'A' && address < 'J'))
{
// char c = inString[j];
char c = j;
if(c == '-')
{
neg = true;
j ++;
// c = inString[j];
c = j;
}
while(c >= '0' && c <= '9')
{
val = 10 * val + (c - '0');
j ++;
// c = inString[j];
c = j;
}
if(neg) val = -val;
if(address >= 'A') // Address = 'A...'J' to write the total counters
{
sensors[address-'A']->NewTotal(val);
}
else // Address = '0'...'9' to write the day counters
{
// Let the sensor write the value to eeprom
sensors[address-'0']->Update(val);
}
}
}
Mi sa che ho fatto una gran confusione... Mi sapreste aiutare?
Ciao, non puoi utilizzare metodi che restituiscono un oggetto String e assegnarlo ad un array di char.
readStringUntil(), mi sembra che restituisca un oggetto string, comunque non puoi assegnare a un array di char utilizzando la sintassi array=stringa.
Se vuoi usare array di char, le stringhe stile C, devi partire con la lettura della stringa carattere per carattere e assegnarli agli elementi dell' array.
Userai il metodo Client.read(). Leggere un carattere da client o leggerlo da seriale non cambia niente, quindi puoi vedere gli esempi "leggere una stringa da seriale" e applicarla nelle tue funzioni.
Poi userai se necessario le funzioni stringa del C, strcmp() per confrontare due stringhe, strlen() lunghezza
ecc..
Devi cambiare la lettura della stringa da client, devi andare a leggere un carattere alla volta. Come detto prendi esempio da lettura stringa da seriale.
A quanto so io la funzione strcmp() restituisce vero anche se le stringhe sono di diversa lunghezza ma quella più corta è identica ai primi caratteri della più lunga.
Ad esempio "assurdo" e "a".
La Nintendo Wii venne craccata proprio per questo errore.
Ma è normale, è un errore utilizzare la lunghezza della stringa più corta (sempre dipendentemente da cosa si voglia confrontare ed ottenere), occorre fare una cosa del tipo:
Hai ragione.
Il baco era generato dal fatto che venne usato strcmp per la comparazione di hash che potevano quindi anche contenere lo zero, il che non succede per le stringhe vere e proprie che lo zero lo hanno solo alla fine. http://wiibrew.org/wiki/Signing_bug
Ma hanno usato anche il parametro lunghezza, proprio come hai fatto tu
torn24:
Ciao, non puoi utilizzare metodi che restituiscono un oggetto String e assegnarlo ad un array di char.
readStringUntil(), mi sembra che restituisca un oggetto string, comunque non puoi assegnare a un array di char utilizzando la sintassi array=stringa.
Se vuoi usare array di char, le stringhe stile C, devi partire con la lettura della stringa carattere per carattere e assegnarli agli elementi dell' array.
Userai il metodo Client.read(). Leggere un carattere da client o leggerlo da seriale non cambia niente, quindi puoi vedere gli esempi "leggere una stringa da seriale" e applicarla nelle tue funzioni.
Se guardi bene, quella riga è commentata. Come ho scritto nel primo post, ho lasciato il vecchio codice commentato per capire come avevo sostituito quello che c'era con quello nuovo... Tranne nelle ultime righe, dove ho semplicemente aggiunto gli * dove secondo me era necessario senza lasciare la vecchia riga di codice commentata. Sembra che funzioni ma volevo essere sicuro di non aver scritto castronerie...
Grazie.
docdoc:
Una sola nota o curiostà personale: ma nel codice preesistente, che senso ha la prima riga?
String inString = String((char*)"");
Non serve a nulla, basta:
String inString = "";
anzi:
String inString;
Ciao, il codice originale non era scritto da me ma è uno sketch che ho trovato in rete, da li sono partito e modificandolo radicalmente, ho creato un nuovo sketch che pian piano sto cercando di migliorare. Ho gia trovato diversi errori e bugs nel codice originale che ho corretto e probabilmente ce ne sono di altri... Mi sembrava una buona idea partire da un codice funzionante e modificare ma forse avrei fatto prima a scrivere tutto di sana pianta (e non escludo che prima o poi lo farò), anche perchè ci ho già trascorso decine di ore a modificare e testare cose che credevo funzionanti ed invece non lo erano...
Per le divagazioni, non c'è problema, ho imparato anche da li.
CrazyHorse80:
Ciao, il codice originale non era scritto da me ma è uno sketch che ho trovato in rete
Si, si, lo so, non dicevo che l'avessi scritta tu, mi chiedo solo quale mente abbia partorito quell'inizializzazione che a me pare inutile, e perché...