PDA

View Full Version : [C++] Invertire una stringa


masticaedera
28-11-2016, 17:17
Ciao,
vorrei imparare un po' di C/C++ e ho iniziato, come molti suggeriscono, a scrivere piccoli programmi. In particolare mi sono bloccato su uno in C++ che dovrebbe invertire, con una funzione, una stringa di testo inserita.
Non funziona come dovrebbe in quanto stampa sempre e solo un carattere, l'ottavo della riga, e nulla più.
Il bello è che ho provato a fare un programma analogo in Fortran e lì mi è venuto al primo colpo!
Dove sbaglio?
Grazie,

Lorenzo


#include <iostream>
#include <cstring>
#define BUFFER 1000

char invert(char s[]);

main()
{
char input_string[BUFFER];
std::cout << "Inserire una stringa di testo" << std::endl;
std::cin.getline(input_string, 999);
std::cout << "Stringa invertita:" << std::endl;
std::cout << invert(input_string) << std::endl;
return 0;
}

char invert(char s[])
{
char inverted_string[BUFFER];
int j = 0;
int k = sizeof(s)/sizeof(*s);
do
{
inverted_string[j] = s[k];
j++;
k--;
} while (k == 0);
return *inverted_string;
}

the_best_hacker
28-11-2016, 17:50
A parte che manca un bel pezzo di codice, io ti direi di cercare un modo per utilizzare la classe string.
Se invece vuoi utilizzare le stringhe in stile C ricorda che il terminatore è il carattere '/0' e che la dimensione dell'area di char deve essere nota e costante a tempo di compilazione. Tra l'altro questo valore ti serve a prescindere per creare la funzione..


Inviato dal mio iPhone utilizzando Tapatalk

Torsen_ITA
28-11-2016, 17:57
la condizione del while dovrebbe essere >= 0
Il while viene eseguito fintanto che la condizione è vera.
Per come lo hai scritto al primo passaggio la condizione è falsa ed esce fuori.

71106
28-11-2016, 19:09
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main() {
string s = "abcdefg";
reverse(s.begin(), s.end());
cout << s << endl;
}

masticaedera
28-11-2016, 20:01
Anzitutto grazie per le risposte.
71106, volevo in realtà farlo senza ricorrere ad algorithm. Però è vero, come dice the_best_hacker, che sono palesemente in difetto nell'apprendimento delle classi.
Torsen_ITA, ho provato al volo a cambiare la condizione del while (>=0, >0, oppure mettendo "inverted_string[j] == '\0'", ecc.) ma non cambia nulla.
Sospetto che ci sia un problema più che altro nel passaggio dell'array di char alla funzione.

LM

zeMMeMMez
29-11-2016, 07:20
secondo te sizeof(s) cosa ritorna?

masticaedera
29-11-2016, 08:39
secondo te sizeof(s) cosa ritorna?

Ah. Forse la dimensione del puntatore all'array? Sbaglio lì?

71106
29-11-2016, 12:14
Se non vuoi usare std::reverse te la puoi reimplementare da solo. Qui trovi un esempio di possibile implementazione: http://en.cppreference.com/w/cpp/algorithm/reverse

71106
29-11-2016, 12:25
Ah. Forse la dimensione del puntatore all'array? Sbaglio lì? sei incappato in una feature piuttosto ostica del C e C++. Sarebbe stato meglio seguire una strada piu' semplice come quella delle STL che ti ho indicato, che sono molto ben conosciute e documentate, ma almeno cosi' imparerai qualche dettaglio non ovvio del linguaggio.

Normalmente la sintassi con le parentesi quadre dichiara array e sizeof restituisce la dimensione dell'intero array espressa in bytes. Esempio:


int a[10];
cout << sizeof(a) << endl;


Questo stampa "40" perche' la dimensione di int e' 4 byte e ce ne sono 10.

I parametri di funzione pero'... fanno eccezione. Fanno eccezione perche' gli array vengono sempre passati per puntatore, ma una volta che hai passato un array a un'altra funzione il sistema di tipi perde l'informazione sulla dimensione di quell'array perche' la funzione deve poter accettare array di qualunque dimensione (da cui la possibilita' di non mettere nulla dentro le parentesi quadre, ma solo nelle dichiarazioni di funzioni), quindi si e' deciso che anche a livello semantico i parametri array devono essere dei puntatori a tutti gli effetti anche se vengono dichiarati con la sintassi delle parentesi quadre.

Queste due dichiarazioni sono completamente equivalenti:


void f(char s[]);
void f(char *s);


Quindi si, sizeof(s) restituisce la dimensione in byte di un puntatore, che su una macchina a 64 bit e' 8.

masticaedera
29-11-2016, 14:09
71106, sei stato chiarissimo e ti ringrazio. Ragionerò sulla base delle indicazioni del tuo post!

LM

zeMMeMMez
29-11-2016, 14:41
ci sono poi tutta un'altra serie di errori
1) ritorno un char, ma volevi davvero tornare un char?
2) non allochi memoria "nuova" ad ogni chiamata, anzi usi sempre la stessa
3) avresti ovviamente dei leak di memoria
4) per la lunghezza della stringa (in C) puoi usare strnlen (con la n) per mettere un limite superiore
5) non fare mai confronti (vale in generale) del tipo =0 con variabili int (possono essere anche negative)
6) in linea generale la funzione dovrebbe ricevere DUE parametri.
Il primo è la stringa da invertire, il secondo la stringa invertita.
In questo caso avrai problemi se il secondo parametro non è "buono"
7) oppure un unico parametro, nel qual caso invertirai proprio la stringa che viene passata (personalmente la vedrei come scelta migliore).
in questo caso, ovviamente, NON utilizzerai un vettore di "appoggio" in cui invertire la stringa, per poi ricopiarla.
Ti basta invertire "a coppie" i caratteri
8) nel tuo "tentativo" hai vari approcci
se chiami la funzione di calcolo lunghezza stringa allora userai un ciclo for
se invece fai "caserecciamente" attenzione ad avere una dimensione "ragionevole" nella stringa (per gestire il caso in cui manca lo zero finale)

masticaedera
29-11-2016, 15:15
Così funziona come atteso ma ho usato algorithm. Si poteva fare senza funzione ma volevo vedere se il parametro passava sia in andata che in ritorno.
Leggo che la classe string dovrebbe risolvere automaticamente anche i problemi di allocazione della memoria (in risposta a zeMMeMMez); è così?
Qualsiasi tentativo di fare l'inversione "a mano" col tipo string mi si risolveva invece in errori di out of range, quindi per il momento ho lasciato perdere.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

string invert(string s);

int main()
{
string input_string;
cout << "Inserire una stringa di testo" << endl;
getline (cin, input_string);
cout << "Stringa invertita:" << endl;
cout << invert(input_string) << endl;
return 0;
}

string invert(string s)
{
reverse(s.begin(), s.end());
return s;
}

zeMMeMMez
29-11-2016, 15:50
francamente così non hai imparato nulla.
sporcati le mani, non leggere nessuna soluzione già fatta, impegna la tua testa.
fai il "problem solving" :D

71106
29-11-2016, 16:25
Così funziona come atteso ma ho usato algorithm. Si poteva fare senza funzione ma volevo vedere se il parametro passava sia in andata che in ritorno.
Leggo che la classe string dovrebbe risolvere automaticamente anche i problemi di allocazione della memoria (in risposta a zeMMeMMez); è così?
Qualsiasi tentativo di fare l'inversione "a mano" col tipo string mi si risolveva invece in errori di out of range, quindi per il momento ho lasciato perdere.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

string invert(string s);

int main()
{
string input_string;
cout << "Inserire una stringa di testo" << endl;
getline (cin, input_string);
cout << "Stringa invertita:" << endl;
cout << invert(input_string) << endl;
return 0;
}

string invert(string s)
{
reverse(s.begin(), s.end());
return s;
} la funzione "invert" non ha scopo, non fa altro che invocare un'altra funzione. Inoltre non e' necessario passare l'oggetto string per copia e poi restituirne un'altra copia ancora, lo stai copiando due volte e senza motivo visto che std::reverse cambia la stringa originale.

Se vuoi creare una funzione che produca un nuovo oggetto std::string senza modificare l'originale, passa l'originale per riferimento ed evita di copiarlo una volta di troppo:


string invert(string const &s) {
string t = s;
reverse(t.begin(), t.end());
return t;
}


Inoltre non includere <cstring>, che equivale a <string.h> e definisce demenziali funzioncine C come la sopracitata strnlen, bensi' <string> che definisce std::string.

masticaedera
29-11-2016, 16:46
Tutto chiaro a parte "const &s"... Perché const e perché &? :mbe:
Sul riscrivere "dal basso" ci ripenso più avanti. Molto difficile comunque la logica della programmazione, davvero (ecco perché non mi è mai troppo riuscita!).

LM

zeMMeMMez
29-11-2016, 17:40
Tutto chiaro a parte "const &s"... Perché const e perché &? :mbe:
Sul riscrivere "dal basso" ci ripenso più avanti. Molto difficile comunque la logica della programmazione, davvero (ecco perché non mi è mai troppo riuscita!).

LMe come pensi, così tanto per curiosità, di "andare avanti" se non sai fare neppure questo.
prima di camminare devi imparare a gattonare.

PS perchè pensavi fosse "facile"?

masticaedera
29-11-2016, 18:08
PS perchè pensavi fosse "facile"?

Non lo pensavo.

LM

71106
29-11-2016, 23:52
Tutto chiaro a parte "const &s"... Perché const e perché &? :mbe: "&" definisce un tipo "reference", nel caso specifico un riferimento a std::string. I reference in C++ sono implementati come i puntatori, solo che nel sistema di tipi hanno caratteristiche diverse che li rendono un po' più sicuri da usare, dove in questo caso "sicuri" significa "type-safe". Un esempio basilare è che i reference sono molto più difficili da rendere nulli o invalidi, anche perchè il compilatore è in grado di emettere warnings in alcune delle situazioni "a rischio". In generale diciamo che i reference dovrebbero essere preferiti ai puntatori ovunque possibile. Il problema è che non sempre è possibile.

Ciò detto ti esorto a documentarti autonomamente sull'argomento che è piuttosto ampio e non mi va di spiegartelo per iscritto.

"const" invece marca la parte a sinistra del tipo come immutabile. Ho specificato "la parte a sinistra" perchè "const" può avere varie posizioni nella definizione di un tipo. Prendi ad esempio questo tipo balordo:

string ***s;

"s" è un puntatore che punta a un puntatore che punta a un puntatore che punta a un oggetto string. Nella pratica non devi mai scrivere una cosa del genere e col tempo i tuoi occhi impareranno a sanguinare nel vederne, ma è per farti l'esempio.

Ora la domanda: se vuoi rendere immutabile l'oggetto string puntato, dove scrivi "const"? Risposta: a destra di "string":

string const ***s;

Se invece avessi voluto rendere immutabile il puntatore a string, a cui s punta con due livelli di indirezione, avresti dovuto metterlo a destra del primo asterisco:

string *const **s;

Se invece avessi voluto rendere immutabile il puntatore al puntatore all'oggetto string, avresti dovuto metterlo a destra del secondo asterisco:

string **const *s;

E così via.

Quindi, come dicevo, "const" rende immutabile la parte a sinistra del tipo definito. Quindi "string const &s" vuol dire che "s è un riferimento a un oggetto string che non può essere modificato. Se provi a modificarlo all'interno della funzione "invert", il compilatore spara un errore. D'altro canto, chi invoca la funzione "invert" ha garanzie che essa non cambierà il contenuto della stringa passata.

Può sembrarti inutile adesso, magari penserai "se non voglio che invert cambi la stringa basta che non la cambio, invert l'ho scritta io". Ma non sarà sempre così, per due motivi: 1. non sempre sarai tu l'autore del codice che usi, molto presto inizierai a usare librerie altrui (come le stesse STL); e 2. quando comincerai a scrivere tonnellate di codice non potrai più fidarti neanche di te stesso perchè la probabilità di commettere errori di programmazione aumenterà con le dimensioni del programma. Lo scopo di un sistema di tipi è quello di impedire determinati tipi di errori bloccando il compilatore qualora tu li commetta.

71106
30-11-2016, 00:11
Ah, dimenticavo. A volte potresti trovare scritto anche così:

const string ***s;

È equivalente a:

string const ***s;

masticaedera
30-11-2016, 09:40
71106, la tua spiegazione, pur nella difficoltà dell'argomento, è molto esaustiva! Hai fatto veramente molto e ti ringrazio. Osservo che anche scrivere un programma per un'operazione tutto sommato semplice non è per nulla ovvio e richiede molta documentazione. Non credo che scriverò tonnellate di codice, ma apprendere le basi mi interessa molto e cercherò di fare un po' di pratica in materia.
Diciamo che ci sono probabilmente linguaggi più semplici per imparare, a quanto mi dicono... :cool: :D
Comunque oggi magari ci lavoro ancora un po', cerco qualche guida più specifica.

Lorenzo

71106
30-11-2016, 12:21
E' normale che ti sembri difficile adesso che stai imparando, ma e' un "one-off effort". L'hai visto anche tu al post #4, a saperlo fare bastavano tre righe, tre di numero.

Sull'esistenza di linguaggi piu' semplici da imparare, sicuramente JavaScript e Python sono due ottimi candidati: JavaScript perche' al giorno d'oggi e' onnipresente e quindi gli investimenti su di esso sono generalmente proficui, e Python perche' se non lo menziono io ci pensa cdimauro. :asd:

Ma il problema di entrambi e' l'assenza di un sistema di tipi. Per entrambi esistono soluzioni che sopperiscono alla carenza: per JavaScript esiste flow (https://flowtype.org/) e per Python e' possibile implementare un sistema di tipi tramite annotazioni, ma quest'ultima non mi piace perche' ne esce fuori una roba a dir poco verbosa.

sottovento
30-11-2016, 14:14
Volendo giocare con i puntatori in C, potresti fare a meno dei cicli:

void _revert(char *p1, char *p2)
{
int diff = p2 - p1;
if (diff > 0)
{
char tmp = *p2;
*p2 = *p1;
*p1 = tmp;
if (diff > 1)
_revert(++p1, --p2);
}
}

Ovviamente devi entrare con un puntatore all'inizio e alla fine della stringa, per esempio:

void revert(char *str)
{
_revert(&str[0], &str[strlen(str) - 1]);
}

zeMMeMMez
30-11-2016, 14:16
71106, la tua spiegazione, pur nella difficoltà dell'argomento, è molto esaustiva! Hai fatto veramente molto e ti ringrazio. Osservo che anche scrivere un programma per un'operazione tutto sommato semplice non è per nulla ovvio e richiede molta documentazione. Non credo che scriverò tonnellate di codice, ma apprendere le basi mi interessa molto e cercherò di fare un po' di pratica in materia.
Diciamo che ci sono probabilmente linguaggi più semplici per imparare, a quanto mi dicono... :cool: :D
Comunque oggi magari ci lavoro ancora un po', cerco qualche guida più specifica.

Lorenzo

Mah... guarda... usare le librerie e gli oggetti già fatti non serve a nulla per imparare, è "zucchero sintattico".

Il C ti tocca conoscerlo, è un po' come l'inglese: bene o male non puoi non saperlo.

Volendo ti scrivo in un singolo statement come invertire una stringa in un linguaggio che probabilmente non avrai mai visto, ma che senso ha? Nessuno.

Ti suggerisco quindi di sforzarti di imparare, per gradi.

Primo punto: data una stringa (cioè una sequenza di caratteri terminata con uno zero), scrivi una funzione che la inverte.
Poi potrai trasformarla in una "simil" funzione di libreria, mettere i vari check e così via.

zeMMeMMez
30-11-2016, 14:18
Volendo giocare con i puntatori in C, potresti fare a meno dei cicli:

void _revert(char *p1, char *p2)
{
int diff = p2 - p1;
if (diff > 0)
{
char tmp = *p2;
*p2 = *p1;
*p1 = tmp;
if (diff > 1)
_revert(++p1, --p2);
}
}

Ovviamente devi entrare con un puntatore all'inizio e alla fine della stringa, per esempio:

void revert(char *str)
{
_revert(&str[0], &str[strlen(str) - 1]);
}

Non è un granchè, per tutta una serie di motivi
1) è inutilmente ricorsiva (già questo è sufficiente)
2) non ha nessuna verifica dei parametri (questo è pure sufficiente, ma è il punto successivo)
3) non insegna nulla utile per un niubbo

sottovento
30-11-2016, 14:23
Non è un granchè, per tutta una serie di motivi
1) è inutilmente ricorsiva (già questo è sufficiente)
2) non ha nessuna verifica dei parametri (questo è pure sufficiente, ma è il punto successivo)
3) non insegna nulla utile per un niubbo
1) si parlava di un esercizio. Mi servisse invertire una stringa, userei funzioni gia' pronte
2) quale verifica faresti?
3) tuo parere

masticaedera
30-11-2016, 15:05
Io avevo pensato, come via intermedia, di usare string::at ma quando ci ho provato ho probabilmente sbagliato i conti... :cry: :doh:
Tanti suggerimenti utili comunque (sono contento che la discussione abbia preso piede!).

LM

zeMMeMMez
30-11-2016, 15:30
1) si parlava di un esercizio. Mi servisse invertire una stringa, userei funzioni gia' pronte
2) quale verifica faresti?
3) tuo parere
1) quindi non impareresti nulla
2) EDIT: mi sono riproposto di non dare questo genere di aiuti (rif punto 3)
3) certo che è un mio parere. ed è noto che vale quanto il tuo. cioè: niente

zeMMeMMez
30-11-2016, 15:34
Io avevo pensato, come via intermedia, di usare string::at ma quando ci ho provato ho probabilmente sbagliato i conti... :cry: :doh:
Tanti suggerimenti utili comunque (sono contento che la discussione abbia preso piede!).

LM

stai facendo un mischione. Il tuo scopo è acquisire un minimo di dimestichezza con le stringhe C, con quelle C++, con la libreria C, con la libreria C++, con tutte o nessuna di queste?

Come già detto ti suggerisco di sforzarti di scrivere un programma che inverte una stringa (anche fissa, per iniziare).
Lascia perdere le inutilità come ricorsione, librerie etc, sono controproducenti per imparare.

Imparerai 10000 volte di più da un programma di 10 righe fatto con la tua testa (e funzionante) che leggendo 1000 forum o 1 miliardo di ricerche google, copia-incolla e così via.

Quindi, tornando al tema, vuoi imparare a fare qualcosa, o ti limiti a rimanere nella fascia bimbominkiesca-niubbesca-copia-incollesca-webcosesca?

Qui ad esempio puoi "scatenare" gli istinti bimbominkiesi-webcoseschi
https://www.rosettacode.org/wiki/Reverse_a_string

sottovento
30-11-2016, 16:00
1) quindi non impareresti nulla
2) EDIT: mi sono riproposto di non dare questo genere di aiuti (rif punto 3)
3) certo che è un mio parere. ed è noto che vale quanto il tuo. cioè: niente
1) posso permetterlo dopo 30 anni di programmazione C. Cosa ne pensi?
2) ti sei riproposto di non dare quel genere di aiuti? Dici che servono dei controlli ma non specifichi i controlli e dici che non dai quel genere di aiuti?
3) d'accordo, soprattutto alla luce del punto #2

zeMMeMMez
30-11-2016, 16:48
1) posso permetterlo dopo 30 anni di programmazione C. Cosa ne pensi?Che se ripeti per 30 anni l'alfabeto non diventi necessariamente un poeta.
Sono stupito che dopo 30 anni proponi la ricorsione che è, in generale, da evitare, pressochè sempre inutile, inesistente in concreto e, nel caso di specie, enormemente costosa dal punto di vista computazionale, senza alcun beneficio reale.
Con una funzione void (ovviamente da evitare) e con nessun controllo sull'input.
Insomma, fossi in te, non smetterei di studiare.
A mio parere è una porzione di codice priva dei requisiti della professionalità.
Sempre a mio parere, che ontologicamente non vale nulla.

zeMMeMMez
30-11-2016, 17:06
dai, spiegaci, dicci un po' le code review nella tua azienda di sole femmine come vengono svolte, illumina. d'altronde sottovento ha scritto codice in giro per l'europa, ma scommetto che un'azienda di sole femmine non l'ha nemmeno mai vista.
Se quello dovrebbe essere un esempio di buon codice stiamo freschi.
Mi correggo: state freschi (considerata anche la temperatura).
Come già detto mi spiace, ma lascio gli aiuti a chi è più esperto di me, a me i difetti paiono evidenti, ma sappiamo ormai quanto valgono le mie opinioni.

sottovento
30-11-2016, 17:19
Che se ripeti per 30 anni l'alfabeto non diventi necessariamente un poeta.

Si, vedo

Sono stupito che dopo 30 anni proponi la ricorsione che è, in generale, da evitare, pressochè sempre inutile, inesistente in concreto e, nel caso di specie, enormemente costosa dal punto di vista computazionale, senza alcun beneficio reale.

Ovviamente non hai capito. Questo e' il tipico esempio che viene proposto all'universita', per esercizio viene chiesto di non utilizzare i cicli. Visto che si stava parlando di esercizi, l'ho riproposto.
Ma per capirlo era necessario capire di cosa si parla


Con una funzione void (ovviamente da evitare) e con nessun controllo sull'input.

Sto ancora aspettando il controllo che proponi.


Insomma, fossi in te, non smetterei di studiare.

Mai smesso. Dopo 2 lauree ho preso anche certificazioni e master.
Nonostante questo non mi permetterei mai di scrivere post come i tuoi.


A mio parere è una porzione di codice priva dei requisiti della professionalità.

Vero, infatti e' un esercizio. Ovviamente la soluzione da usare e' un'altra ed e' gia' stata proposta. 71106 ha risolto in una sola linea di codice, quindi non c'e' altro da dire. Tranne che - sempre per esercizio - siamo tutti in trepida attesa dei controlli che vuoi proporre.


Sempre a mio parere, che ontologicamente non vale nulla.
Vedi che alla fine siamo d'accordo? :D

sottovento
30-11-2016, 17:21
dai, spiegaci, dicci un po' le code review nella tua azienda di sole femmine come vengono svolte, illumina. d'altronde sottovento ha scritto codice in giro per l'europa, ma scommetto che un'azienda di sole femmine non l'ha nemmeno mai vista.
Aahh! Non avevo associato, e' quello dell'azienda!
Antonio, grazie per la tua difesa, veramente molto apprezzata (tuttavia, ho scritto software anche fuori dall'Europa, visto che ho vissuto 8 anni in Cina, 2 negli USA e 2 in Russia. E da questa settimana, sono ancora fuori Europa :D )

zeMMeMMez
30-11-2016, 17:35
Ovviamente non hai capito. Questo e' il tipico esempio che viene proposto all'universita', per esercizio viene chiesto di non utilizzare i cicli. Qual'è l'attinenza con questo thread?
E' stato chiesto, per caso, di non utilizzare cicli?
Mi sa che a non aver capito qualcosa non sono io.
Certo si vede che frequento università diverse.
Anzi di sicuro.
Sto ancora aspettando il controllo che proponi.Mi spiace, è troppo difficile, e in realtà ce ne sono almeno due da mettere, oltre a una evidente incongruenza nel definire void una funzione siffatta.
Mai smesso. Dopo 2 lauree ho preso anche certificazioni e master.Pensa, io sto prendendo la terza in scienza del tortellino, per poi fare il master in piada (no, non sto scherzando più di tanto...).
Nonostante questo non mi permetterei mai di scrivere post come i tuoi.Certo, certo, come dici, basta magari che non proponi codice che c'entra come i cavoli a merenda.
Magari in Cina succede (questa è sottile).
Vero, infatti e' un esercizio. Ovviamente la soluzione da usare e' un'altra ed e' gia' stata proposta. 71106 ha risolto in una sola linea di codice, quindi non c'e' altro da dire.C'è da dire, eccome. "Una sola linea di codice" mi pare una sciocchezza, soprattutto se (come da domanda) deve essere un esercizio che insegna qualcosa.
Vedi che alla fine siamo d'accordo? :DCerto che lo siamo.
Sono sempre d'accordo con tutti, che mi costa?
Tanto TUTTE le opinioni valgono uguale, cioè esattamente zero :D

!fazz
30-11-2016, 17:36
datevi una calmata

sottovento
30-11-2016, 17:44
Io avevo pensato, come via intermedia, di usare string::at ma quando ci ho provato ho probabilmente sbagliato i conti... :cry: :doh:

Certo, lo puoi fare. Puoi sempre mettere il codice qui

zeMMeMMez
30-11-2016, 17:46
Io sono calmissimo, mi chiedevo, ad esempio, se qualcuno può spiegarmi cosa succede se viene passata una stringa che non termina con zero.
Poi avrei anche altri dubbi, ma iniziamo con questo.
Riagevolo
void revert(char *str)
{
_revert(&str[0], &str[strlen(str) - 1]);
}

sottovento
30-11-2016, 17:50
Io sono calmissimo, mi chiedevo, ad esempio, se qualcuno può spiegarmi cosa succede se viene passata una stringa che non termina con zero.
Poi avrei anche altri dubbi, ma iniziamo con questo.
Riagevolo
void revert(char *str)
{
_revert(&str[0], &str[strlen(str) - 1]);
}

Il dubbio ovviamente non si pone perche' avresti il crash sulla strlen.
Quindi, non entreresti nemmeno nella funzione che criticavi, ma avresti un errore di programmazione a priori, su una funzione standard. Inserire ulteriori controlli sarebbe ridondante, anche se la curiosita' resta: quale controllo?

zeMMeMMez
30-11-2016, 17:56
Il dubbio ovviamente non si pone perche' avresti il crash sulla strlen.
Quindi, non entreresti nemmeno nella funzione che criticavi, ma avresti un errore di programmazione a priori, su una funzione standard. Inserire ulteriori controlli sarebbe ridondante, anche se la curiosita' resta: quale controllo?
Ma davvero? :eek:

EDIT: vabbè visto che stasera mi perfezionerò nel Teorema della Cioccolata Calda mi chiedevo anche... ma cosa farà mai, revert(0)?
Qualcuno me lo può spiegare?

71106
30-11-2016, 18:11
Ma davvero? :eek:

EDIT: vabbè visto che stasera mi perfezionerò nel Teorema della Cioccolata Calda mi chiedevo anche... ma cosa farà mai, revert(0)?
Qualcuno me lo può spiegare? Le tue escort minorenni? :D

zeMMeMMez
30-11-2016, 18:13
Le tue escort minorenni? :D

Purtroppo le ragionieri programmatrici ora non sono in servizio, magari domani faccio compilare questo frammentino e vediamo cosa succede
char bufferello[256];
sprintf(bufferello,"123456abcdefghi");
printf("pre |%s|\n",bufferello);
revert(0); // cosa accadrà? Trallallero trallallà (la specifica delle accentate ha un suo perchè, ma poi si entra in argomenti meno scontati)
revert(bufferello);
printf("post |%s|\n",bufferello);

71106
30-11-2016, 18:22
Mah... guarda... usare le librerie e gli oggetti già fatti non serve a nulla per imparare, è "zucchero sintattico". Questo e' tecnicamente errato: gli zuccheri sintattici sono caratteristiche del linguaggio, non delle librerie a corredo.

Inoltre, anche se in questo thread dobbiamo tutti subire la tua inutile opinione su come la gente debba imparare le cose, imparare a usare le STL e' un passaggio obbligato che e' inutile rimandare.

E' un passaggio obbligato perche' se tu, a 2016 quasi finito, quasi 2017, usi ancora strnlen in ambienti di produzione... che Dio ti aiuti e cerca attenzione medica il prima possibile.

71106
30-11-2016, 18:23
Purtroppo le ragionieri programmatrici ora non sono in servizio, magari domani faccio compilare questo frammentino e vediamo cosa succede
char bufferello[256];
sprintf(bufferello,"123456abcdefghi");
printf("pre |%s|\n",bufferello);
revert(0); // cosa accadrà? Trallallero trallallà (la specifica delle accentate ha un suo perchè, ma poi si entra in argomenti meno scontati)
revert(bufferello);
printf("post |%s|\n",bufferello); Oh no, sei un hacker Unix old school e mi hai smontato! Ma ci sono cascato come una pera cotta, proprio! :eek:

FreeMan
30-11-2016, 18:23
zeMMeMMez sospeso 15gg per continuato flame

71106, non dargli corda... si chiude qui

>bYeZ<

masticaedera
30-11-2016, 20:15
Arrivo a casa e scopro che involontariamente ho scatenato una querelle tra programmatori.
Mi dispiace.
Prima che il thread sia chiuso, se è questo il suo destino, volevo solo dire che era una semplice richiesta di un amatore che a ogni tentativo di imparare un po' di più su come funziona un programma si scontra coi suoi limiti e con un argomento oggettivamente difficile.
Io ringrazio comunque tutti dei contributi, li leggerò attentamente (anche quelli del sospeso, nonostante non mi abbiano fatto piacere alcuni titoli che mi ha affibbiato e in cui proprio non mi riconosco).
Solo per chiarire. Tutto qui.
Buona serata,

Lorenzo

71106
30-11-2016, 20:44
Assolutamente rilassati, non si tratta di un incidente che hai causato tu, è che certe volte sul forum si incontrano personaggi particolari (incluso il sottoscritto :asd: ) e questo è perfettamente normale. Se provi a usare la funzione di ricerca potresti trovare dei trascorsi di zeMMeMMez davvero niente male. :D

Tornando sul tecnico :D, mi è venuta in mente un'altra cosa riguardo a quanto ho scritto al post #8:

Se non vuoi usare std::reverse te la puoi reimplementare da solo. Qui trovi un esempio di possibile implementazione: http://en.cppreference.com/w/cpp/algorithm/reverse

Ossia che essendo alle prime armi potresti non avere idea di cosa sono i template.

Questa è l'implementazione esemplificativa riportata da cppreference.com:


template<class BidirIt>
void reverse(BidirIt first, BidirIt last)
{
while ((first != last) && (first != --last)) {
std::iter_swap(first++, last);
}
}


Volendo eliminare il template bisogna istanziare "BidirIt", ma a scrivere a mano il tipo di un iteratore ci vuole una quaresima, ergo conviene fare tutto inline:


#include <iostream>
#include <string>

using namespace std;

int main()
{
string s;
getline(cin, s);
auto first = s.begin();
auto last = s.end();
while ((first != last) && (first != --last)) {
iter_swap(first++, last);
}
cout << s << endl;
return 0;
}


La keyword "auto" è un altro modo per fare type inference, ossia per dire al compilatore di inferire automaticamente il tipo di una variabile e non rompere le balle (l'altro modo sono appunto i template).

Quindi questa linea:

auto first = s.begin();

Equivale a dire "dichiarami una variabile first e mettici l'iteratore di inizio stringa, al tipo pensaci tu".

In generale con gli iteratori è sempre così, bisogna fare type inference. Non solo per convenienza ma anche perchè le uniche specifiche che le STL forniscono ad un qualsiasi oggetto per essere un "iteratore" sono specifiche d'uso. Nessuno dice che un iteratore debba essere un oggetto della classe tal dei tali, ma è richiesto che l'iteratore bidirezionale (come il "BidirIt" della reverse) esponga gli operatori ++, --, e il necessario per dereferenziare. Anche un puntatore a char è un iteratore bidirezionale.

Vedi qui: http://en.cppreference.com/w/cpp/concept/Iterator

E qui: http://en.cppreference.com/w/cpp/concept/BidirectionalIterator

Ed ecco che in questo modo abbiamo preso due piccioni con una fava: abbiamo evitato di usare std::reverse ma anche di preoccuparci della gestione della memoria e imporre limiti arbitrari sulla dimensione della stringa di input.

!fazz
01-12-2016, 11:06
tornando in topic visto che l'utente è alle primissime armi non è meglio consigliare prima un approccio convenzionale e didattico procedurale (alla c insomma) mediante vettori gestiti manualmente e successivamente semplificare il codice utilizzando le varie funzioni a disposizione in modo da fornire un approccio graduale?

praticamente masticaedera segui questo

dovresti sapere che nel c una stringa non è altro che un vettore di caratteri di lunghezza variabile (ma inferiore alla dimensione massima del vettore) e per indicare la fine della stringa nel c l'ultimo carattere utile viene seguito dal carattere '\0'
ora per invertire la stringa cosa devi fare? essenzialmente 2 cose
1) individuare quanto la stringa è lunga
2) leggere la stringa al contrario e copiare carattere per carattere la stringa in modo inverso ovvero se la stringa è lunga x l'ultimo carattere va messo nel primo della nuova stringa ecc ecc

prova a fare questo semplice esercizio una volta che l'avrai padroneggiato vedremo come migliorare il codice :D :D

71106
01-12-2016, 11:54
tornando in topic visto che l'utente è alle primissime armi non è meglio consigliare prima un approccio convenzionale e didattico procedurale (alla c insomma) mediante vettori gestiti manualmente e successivamente semplificare il codice utilizzando le varie funzioni a disposizione in modo da fornire un approccio graduale? Si, oppure no.

masticaedera
01-12-2016, 13:08
Per ora ho prodotto una versione C++ che, allo stato attuale, funziona.

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
string input_string, inverted_string;
int a = 0;
int b;
cout << "Inserire una stringa di testo" << endl;
getline (cin, input_string);
b = input_string.length();
inverted_string.resize(b);
do
{
inverted_string.at(a) = input_string.at(b - 1);
a++;
b--;
}
while (b > 0);
cout << "Stringa invertita:" << endl;
cout << inverted_string << endl;
return 0;
}

Il problema delle lettere accentate, però, è reale (non sono stampate correttamente... ma leggevo che forse è un problema di console).
Sto lavorando, facendo seguito al suggerimento del mod, anche a una versione C.

LM

tomminno
01-12-2016, 14:41
Ma se invece che C++ (nel titolo c'è scritto C++ non C) avesse cominciato con C# o Java, ci sarebbe qualcuno che avrebbe consigliato l'accesso ai singoli elementi della stringa per farne l'inversione e non l'utilizzo di funzioni della librerie standard?

71106
01-12-2016, 18:42
Il problema delle lettere accentate, però, è reale http://en.cppreference.com/w/cpp/string/multibyte/mbsrtowcs

71106
01-12-2016, 18:49
http://en.cppreference.com/w/cpp/string/multibyte/mbsrtowcs

In realta' dovrei probabilmente porre l'accento sul fatto che la sopracitata funzione non costituisce una soluzione completa.

Il "multi-byte character set" di cui si parla dovrebbe essere se non erro UTF-8, che e' in grado di esprimere tutti i caratteri Unicode. La funzione converte da UTF-8 a wide characters, ossia ti permette di memorizzare in un oggetto wstring sul quale a quel punto puoi fare std::reverse.

Tuttavia i "wide characters" non sono in grado di memorizzare tutti i caratteri Unicode. I wide characters sono interi senza segno da 16 bit, quindi al massimo 65536 combinazioni, mentre i caratteri Unicode sono molti di piu' perche' includono svariati alfabeti esoterici.

Quindi in sostanza l'uso di mbsrtowcs ti permetterebbe di risolvere per le lettere accentate, ma non per caratteri asiatici strani, o altro. Per quello l'unica soluzione e' la decodifica e ricodifica, quindi o ti impari lo standard UTF-8 o usi una libreria di terze parti.

La prima sarebbe in realta' un ottimo esercizio. :D

Tie': http://man7.org/linux/man-pages/man7/utf-8.7.html

masticaedera
01-12-2016, 21:47
In attesa di approfondire 'sta cosa, ho preparato una possibile soluzione in C:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *input_string, *inverted_string;
int a = 0;
int b;
printf("Inserire una stringa di testo:\n");
scanf("%m[^\n]", &input_string);
b = strlen(input_string);
inverted_string = malloc(sizeof(char) * b);
if (inverted_string == NULL)
{
printf("Errore di allocazione memoria!");
return 1;
}
while (b >= 0)
{
inverted_string[a] = input_string[b - 1];
a++;
b--;
}
printf("Stringa invertita:\n%s\n", inverted_string);
free(input_string);
free(inverted_string);
return 0;
}


Anche questa dà il risultato atteso (caratteri strani a parte). Non sarà una meraviglia ma qualche base in più l'ho imparata effettivamente.
Sicuramente è da migliorare parecchio. Ma - ribadisco - la mia ambizione non è quella di diventare un programmatore...! :O :cool:

71106
01-12-2016, 22:25
In attesa di approfondire 'sta cosa, ho preparato una possibile soluzione in C:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *input_string, *inverted_string;
int a = 0;
int b;
printf("Inserire una stringa di testo:\n");
scanf("%m[^\n]", &input_string);
b = strlen(input_string);
inverted_string = malloc(sizeof(char) * b);
if (inverted_string == NULL)
{
printf("Errore di allocazione memoria!");
return 1;
}
while (b >= 0)
{
inverted_string[a] = input_string[b - 1];
a++;
b--;
}
printf("Stringa invertita:\n%s\n", inverted_string);
free(input_string);
free(inverted_string);
return 0;
}
Contiene un errore piuttosto grave che il C++ ti avrebbe risparmiato. Ricordati che ad ogni chiamata malloc deve sempre corrispondere una e una sola chiamata free, e viceversa.

Il programma che hai scritto funziona ugualmente, ma le specifiche del linguaggio C per un sorgente simile ricadono nell'"undefined behavior", che nella pratica può anche tradursi in vulnerabilità di sicurezza.



Ma - ribadisco - la mia ambizione non è quella di diventare un programmatore...! :O :cool: Eppure sembri sulla buona strada. :D

(qualche errore all'inizio è normale)

masticaedera
01-12-2016, 22:34
Quindi ciò significa che non serve - anzi, mi correggo: è controproducente - la free(input_string)?

LM

sottovento
01-12-2016, 23:07
while (b >= 0)
{
inverted_string[a] = input_string[b - 1];
a++;
b--;
}

Attenzione - quando b==0, vai oltre il limite della stringa!

masticaedera
01-12-2016, 23:19
while (b != 0)
dovrebbe andare.

71106
01-12-2016, 23:32
Quindi ciò significa che non serve - anzi, mi correggo: è controproducente - la free(input_string)?

LM L'allievo supera il maestro... Ho appena ricontrollato la documentazione della scanf, il flag "m" che hai specificato nella format string alloca automaticamente e richiede che la memoria allocata venga liberata dal chiamante con la free, quindi hai fatto giusto. :D

Dimentica il post #56, sono un pirla. :asd:

masticaedera
02-12-2016, 15:11
Ho appena ricontrollato la documentazione della scanf, il flag "m" che hai specificato nella format string alloca automaticamente e richiede che la memoria allocata venga liberata dal chiamante con la free, quindi hai fatto giusto.

Più che altro mi è venuto in mente: ma la chiamata a scanf con allocazione automatica richiede controllo pure quella (if input_string == NULL...) oppure lo fa già in automatico la funzione di libreria?

LM

sottovento
02-12-2016, 17:43
Più che altro mi è venuto in mente: ma la chiamata a scanf con allocazione automatica richiede controllo pure quella (if input_string == NULL...) oppure lo fa già in automatico la funzione di libreria?

LM

Ho controllato: %m e' una funzionalita' "nuova" ed alloca memoria per te, per evitarti il fastidio.
Sembra che la allochi nell'heap, quindi l'allocazione puo' fallire. Io aggiungerei il controllo sull'input_string == NULL.

71106
02-12-2016, 23:23
Probabilmente non serve, io voto per codice di errore dalla scanf se fallisce la malloc interna. ENOMEM è elencato tra i possibili valori di ritorno, quindi l'if lo metterei sul valore di ritorno della scanf.

Ma programmare così mi sembra veramente idiota, in C++ questi casi si gestiscono tramite eccezioni.

71106
08-12-2016, 13:26
Ma il problema di entrambi e' l'assenza di un sistema di tipi. Per entrambi esistono soluzioni che sopperiscono alla carenza: per JavaScript esiste flow (https://flowtype.org/) e per Python e' possibile implementare un sistema di tipi tramite annotazioni, ma quest'ultima non mi piace perche' ne esce fuori una roba a dir poco verbosa. Ho appena ritrovato riferimenti riguardo al tipaggio statico in Python.

In realta' non serve usare le annotazioni, esiste il PEP 484 (https://www.python.org/dev/peps/pep-0484/) e progetti come questo (https://github.com/google/pytype/).

Python potrebbe essere un'alternativa completa al C++ per un principiante.

(cdimauro in 3... 2... 1...)

masticaedera
08-12-2016, 15:07
Python potrebbe essere un'alternativa completa al C++ per un principiante.


Mi ero un po' documentato su Python, però i linguaggi interpretati in tutta sincerità non mi convincono molto (a parte che per i comodissimi shell script!).

LM

masticaedera
08-12-2016, 15:46
71106, leggero off topic: pensa te che ho ritrovato in una directory del mio pc fisso un mio tentativo di scrivere un editor di testo in C, con le GTK+!
(Ero arrivato ai menu carica/salva, poi avevo piantato lì)

zeMMeMMez
16-12-2016, 07:17
Buongiorno, scrivo quanto non ho potuto al tempo per sospensione.
Telegraficamente

1) riguardo alla funzione revert proposta sono ovviamente necessari (almeno) DUE controlli sull'input. Il primo relativo alla presenza o meno di uno zero per la terminazione della stringa, il che normalmente si fa con una strNlen o con un qualsiasi "accrocchio" fatto a mano, che impedisca uno dei problemi classici durante l'utilizzo di funzioni di libreria e C su stringhe
Il secondo è su un parametro 0 o NULL (cosa che, dalla definizione della funzione, è perfettamente legittimo)

2) riguardo ai "miglioramenti" da apporvi ce ne sono vari
a- è cosa buona e giusta avere funzioni che ritornano valori sull'effettivo risultato delle operazioni (cioè vero-falso riuscito-fallito), piuttosto che funzioni-procedure (cioè funzioni void)
b- come già detto la ricorsione è inutile ed anzi dannosa praticamente sempre (per non dire sempre). se qualcuno è più interessato apra il relativo thread.
c- la formulazione "corretta" (che stavo faticosamente tentando di introdurre) è palesemente quella dello "swap" che è ottimale, e che dopo pagine e pagine vedo "saltar fuori"
d- c'è pure il discorso delle codifiche di caratteri a lunghezza variabile, che stavo pure faticosamente tentando di introdurre (argomento banale per chi studia il russo, o comunque deve scontrarsi con alfabeti non latini). però l'avrei lasciato sullo sfondo, troppo difficile per questo livello.

3) sulla risposta alla domanda del thread costato che perfino un moderatore non ha fatto altro che riproporre il tema che avevo già posto (ma, come spesso accade, non recepito). Ovvero quale fosse l'obiettivo dell'esercizio, se imparare il C, il C++, le librerie C, le librerie C++. Perchè non sono affatto sinonimi

4) in generale se non si hanno idee chiarissime è abbastanza ovvio che il risultato non lo sarà, la regola GIGO si applica anche in questo caso.

71106
16-12-2016, 09:55
Minchia, ci teneva davvero tanto! Non si e' neanche domandato come mai ha ricevuto la sospensione. :asd:



1) riguardo alla funzione revert proposta sono ovviamente necessari (almeno) DUE controlli sull'input. Il primo relativo alla presenza o meno di uno zero per la terminazione della stringa, il che normalmente si fa con una strNlen o con un qualsiasi "accrocchio" fatto a mano, che impedisca uno dei problemi classici durante l'utilizzo di funzioni di libreria e C su stringhe
Il secondo è su un parametro 0 o NULL (cosa che, dalla definizione della funzione, è perfettamente legittimo) Si... oppure una riga di STL.



a- è cosa buona e giusta avere funzioni che ritornano valori sull'effettivo risultato delle operazioni (cioè vero-falso riuscito-fallito), piuttosto che funzioni-procedure (cioè funzioni void) Quando avevo 16 anni, cioe' 15 anni fa, in effetti lo facevo. Poi pero' ho fatto quel passo in piu' che evidentemente a qualcun altro e' mancato, e sono giunto alla conclusione che era inutile sprecare la mia vita a scrivere controlli demenziali nei miei programmi e che era meglio trovare degli strumenti che mi dessero delle garanzie tali da permettermi di focalizzarmi sulla funzionalita' e sull'aspetto algoritmico.

E cosi' adesso, che nel frattempo e' diventato 2016 / quasi 2017, ho avuto la possibilita' di scrivere nel curriculum che sono esperto di algoritmi anziche' di costrutti if. :fagiano:



b- come già detto la ricorsione è inutile ed anzi dannosa praticamente sempre (per non dire sempre). :friend:



3) sulla risposta alla domanda del thread costato che perfino un moderatore non ha fatto altro che riproporre il tema che avevo già posto (ma, come spesso accade, non recepito). Ovvero quale fosse l'obiettivo dell'esercizio, se imparare il C, il C++, le librerie C, le librerie C++. Perchè non sono affatto sinonimi Praticamente un genio incompreso, maledetto dal possesso di una verita' infame che nessuno comprende perche' la vita e' piu' facile da vivere nell'ingenuita', salvo poi quando tutto va in merda e nessuno sa come fare e allora serve zeMMeMMez, l'eroe della situazione che e' l'unico in grado di risolvere. :rolleyes:

Anzitutto volevo ringraziarti sentitamente perche' sei sempre pronto a salvare il mondo :D e poi volevo anche offrirti un passaggio in ospedale qualora tu ritenga che nel 2017 imparare il C possa o debba essere effettivamente un obiettivo ragionevole. :)

masticaedera
16-12-2016, 10:50
Minchia, ci teneva davvero tanto! Non si e' neanche domandato come mai ha ricevuto la sospensione. :asd:


Va beh dai 71106, possiamo anche considerare chiuso quell'incidente, no? :)
Penso che abbiamo chiarito tutto.
Sempre con simpatia mia per tutti.
Sono tutti argomenti che continuo a ritenere molto interessanti.
Parlando di linguaggi, forse il più diretto da imparare della famiglia sarebbe il C#, che però su Linux non ho (se non tramite Mono). Lì, a quanto ho capito, molte di queste problematiche sono belle e risolte in automatico o quasi. Però ha ragione anche chi dice che si capisce meno come funziona la macchina.
La funzione di inversione stringa l'ho lasciata lì a decantare, nel frattempo eh! Ho ripreso a leggere quell'editorino GTK di cui sopra. :mc: :D

LM

71106
16-12-2016, 14:42
Va beh dai 71106, possiamo anche considerare chiuso quell'incidente, no? :) Pover ingenuo. :asd:



La funzione di inversione stringa l'ho lasciata lì a decantare, nel frattempo eh! Ho ripreso a leggere quell'editorino GTK di cui sopra. :mc: :D Per cortesia... no. :stordita:

A programmare interfacce grafiche native in C nel 2017 sono rimasti quattro sfigati di cui uno e' zeMMeMMez. Oggi la maggior parte degli utenti interagisce con interfacce web. Se vuoi produrre un applicativo desktop che funzioni localmente puoi valutare opzioni come electron (http://electron.atom.io/). Guarda che fico, ci hanno fatto pure Slack! :D

Il C++ in questo mondo ha ancora un ruolo importante, ma molto diverso. Resta infatti un linguaggio che consente un controllo molto fine sulla gestione della memoria e le cui librerie di default, le STL appunto, permettono di implementare algoritmi efficienti ma non interfacce grafiche. Sono queste (alcune del)le considerazioni da fare quando si sceglie il linguaggio in cui implementare un software.

GTK dimenticalo, e' solo un brutto incidente di percorso nella storia dell'umanita'. :mc:

Ziosilvio
16-12-2016, 16:53
Fine delle polemiche.

masticaedera
16-12-2016, 21:18
Se vuoi produrre un applicativo desktop che funzioni localmente puoi valutare opzioni come electron (http://electron.atom.io/). Guarda che fico, ci hanno fatto pure Slack! :D

Ah però, mica male! Non ne ero proprio a conoscenza.
Mi pare di capire che si programma in Javascript.
Non sarà il solo nuovo paradigma di questo tipo, immagino... Ve ne sono altri e con altri linguaggi?
(però stiamo andando proprio OT... :mc: )
Tornando IT, rileggevo il codice e la versione che mi ha aiutato di più, secondo me, è quella C puro coi puntatori ecc. Adesso mi documento sul discorso caratteri accentati.

LM

masticaedera
16-12-2016, 22:04
Scopro che si può fare con wchar_t, che però mi pare di capire non sia di implementazione universale. Su gcc comunque c'è.
La scanf diventa:

scanf("%ml[^\n]", &input_string);

Poi si deve usare wcslen al posto di strlen e "%ls" nel formato della printf.
A queste condizioni, va: legge e stampa correttamente ogni carattere.

LM

71106
17-12-2016, 00:17
Si ma ripeto, non puo' funzionare con tutti i caratteri Unicode. Prova a copiaincollare caratteri giapponesi sulla console.

Se non ti interessano i caratteri giapponesi ma solo quelli della tua cultura, da qualche parte nel tuo sistema dovrebbe essere possibile configurare le console in modo da usare ANSI anziche' il multi-byte character set, cosicche' tu possa tornare alla versione char anziche' wchar_t.

whcar_t comunque ormai dovrebbe fare parte degli standard del C e del C++. E, specialmente per chi apprende, consiglio fortemente di usare clang al posto di gcc.

71106
17-12-2016, 00:32
Ah però, mica male! Non ne ero proprio a conoscenza.
Mi pare di capire che si programma in Javascript. Esatto. Conosci Node.js (https://nodejs.org/)? Electron in sostanza prende un'applicazione web (backend Node.js e frontend in HTML/CSS/JavaScript) e la inscatola in una applicazione desktop.

Per qualche motivo a me oscuro esistono due framework che da quanto ho capito fanno esattamente la stessa cosa: Electron (http://electron.atom.io/) e NW.js (https://nwjs.io/).

Mi sembra un caso molto curioso di https://xkcd.com/927/, e dico "molto curioso" perche' questi due fanno ESATTAMENTE la stessa cosa.



Non sarà il solo nuovo paradigma di questo tipo, immagino... Ve ne sono altri e con altri linguaggi? Non sono al corrente di strumenti analoghi per altri linguaggi perche' in genere gli altri linguaggi permettono di sviluppare applicazioni desktop direttamente.

Be'... a meno che non consideriamo HTA (https://en.wikipedia.org/wiki/HTML_Application), tecnologia che Microsoft introdusse addirittura negli anni '90 e che fa qualcosa di estremamente simile ad Electron ed NW.js. :D

masticaedera
17-12-2016, 15:57
Si ma ripeto, non puo' funzionare con tutti i caratteri Unicode. Prova a copiaincollare caratteri giapponesi sulla console.

No ma infatti, sicuramente non basta. Però già così c'è un miglioramento :)

E, specialmente per chi apprende, consiglio fortemente di usare clang al posto di gcc.

Questa mi suona proprio nuova... Come mai? Io avevo orecchiato che Gcc fosse uno standard più che attendibile... :eek:
Invece di Node.js, Electron e compagnia cantante proprio non sapevo nulla... Anche se sicuramente chissà quante applicazioni uso che saranno basate su questi modelli di sviluppo! :muro:

LM

71106
17-12-2016, 17:25
Questa mi suona proprio nuova... Come mai? Io avevo orecchiato che Gcc fosse uno standard più che attendibile... :eek: Piu' d'una volta mi e' capitato di scrivere codice C++ che l'ha mandato in crash. :asd:

Ho anche fatto dei bug report che sono stati accettati e credo fixati, ma in generale la codebase di g++ col tempo e' diventata uno schifo. clang invece e' nuovo e pulito ed emette messaggi di errore umanamente intellegibili. :D

Inoltre clang e' basato su LLVM (http://llvm.org/) e ha un'architettura modulare e un'API documentata e accessibile (http://clang.llvm.org/doxygen/group__CINDEX.html), e questi fattori hanno permesso il proliferare di utilissimi strumenti di contorno come clang-format.

Infine, la transizione da gcc a clang e' facile perche' le command line sono compatibili (non so fino a quanto lo siano ma lo sono per le opzioni piu' comuni, non ricordo che mi sia capitato di dover usare un flag diverso).

Non so tu ma io uso una distribuzione di Linux basata su Ubuntu, ergo per installare clang lancio quanto segue:

$ sudo apt-get install llvm build-essential clang

Dopodiche' puoi compilare codice C++ usando il comando "clang++" al posto di "g++".

masticaedera
18-12-2016, 13:15
Ok, grazie sempre per le dritte, cercherò di andare avanti con gli esercizi (anzi, se hai qualche dritta anche su questo, nel senso se mi sai indicare qualche manuale o sito dove si possono trovare dei temi buoni e interessanti, write me :)
Buona domenica,

LM

71106
18-12-2016, 17:11
Ok, grazie sempre per le dritte, cercherò di andare avanti con gli esercizi (anzi, se hai qualche dritta anche su questo, nel senso se mi sai indicare qualche manuale o sito dove si possono trovare dei temi buoni e interessanti, write me :) HackerRank (https://www.hackerrank.com/) e TopCoder (https://www.topcoder.com/). Specialmente il primo, che io amo. :flower:

cdimauro
28-12-2016, 18:29
Ho appena ritrovato riferimenti riguardo al tipaggio statico in Python.

In realta' non serve usare le annotazioni, esiste il PEP 484 (https://www.python.org/dev/peps/pep-0484/) e progetti come questo (https://github.com/google/pytype/).

Python potrebbe essere un'alternativa completa al C++ per un principiante.

(cdimauro in 3... 2... 1...)
Purtroppo ho avuto non poco da fare in questo periodo, e poco tempo libero a disposizione, per cui mi son perso un bel po' di roba.

Certamente Python è LA soluzione migliore (al momento) per un principiante. :cool:
Mi ero un po' documentato su Python, però i linguaggi interpretati in tutta sincerità non mi convincono molto (a parte che per i comodissimi shell script!).

LM
Uno sviluppatore che si rispetti deve imparare a risolvere problemi nel "miglior" (in senso di compromesso) modo possibile.

Per cui non porre limiti preventivi agli strumenti che utilizzerai per farlo.

Se non ti piace l'implementazione standard/mainstream di Python, puoi sempre dare un'occhiata a PyPy (http://pypy.org), che ti consiglio come alternativa se t'interessa aumentare le prestazioni.

Mentre se vuoi eliminare l'interprete, compilando i sorgenti Python, butta un occhio a Shedskin (https://github.com/shedskin/shedskin) o Nuika (http://nuitka.net).
71106, leggero off topic: pensa te che ho ritrovato in una directory del mio pc fisso un mio tentativo di scrivere un editor di testo in C, con le GTK+!
(Ero arrivato ai menu carica/salva, poi avevo piantato lì)
Meno male che ti sei fermato in tempo. :asd:
Va beh dai 71106, possiamo anche considerare chiuso quell'incidente, no? :)
Penso che abbiamo chiarito tutto.
Sempre con simpatia mia per tutti.
Sono tutti argomenti che continuo a ritenere molto interessanti.
Parlando di linguaggi, forse il più diretto da imparare della famiglia sarebbe il C#, che però su Linux non ho (se non tramite Mono). Lì, a quanto ho capito, molte di queste problematiche sono belle e risolte in automatico o quasi. Però ha ragione anche chi dice che si capisce meno come funziona la macchina.
Chi te lo dice evidentemente non sa come funziona la macchina, altrimenti t'avrebbe consigliato il linguaggio macchina. :p
La funzione di inversione stringa l'ho lasciata lì a decantare, nel frattempo eh! Ho ripreso a leggere quell'editorino GTK di cui sopra. :mc: :D

LM
GLOM. Ti prego: certe cose non si possono leggere. :stordita:
Esatto. Conosci Node.js (https://nodejs.org/)? Electron in sostanza prende un'applicazione web (backend Node.js e frontend in HTML/CSS/JavaScript) e la inscatola in una applicazione desktop.

Per qualche motivo a me oscuro esistono due framework che da quanto ho capito fanno esattamente la stessa cosa: Electron (http://electron.atom.io/) e NW.js (https://nwjs.io/).

Mi sembra un caso molto curioso di https://xkcd.com/927/, e dico "molto curioso" perche' questi due fanno ESATTAMENTE la stessa cosa.



Non sono al corrente di strumenti analoghi per altri linguaggi perche' in genere gli altri linguaggi permettono di sviluppare applicazioni desktop direttamente.

Be'... a meno che non consideriamo HTA (https://en.wikipedia.org/wiki/HTML_Application), tecnologia che Microsoft introdusse addirittura negli anni '90 e che fa qualcosa di estremamente simile ad Electron ed NW.js. :D
Puoi dare un'occhiata a pyjs (http://pyjs.org). :fagiano:

masticaedera
29-12-2016, 14:51
Grazie cdimauro, rifletterò anche su questo :)
La difficoltà maggiore, per me, è trovare esercizi di programmazione che siano realmente interessanti e che portino a un prodotto utile (ecco perché la faccenda dell'editor di testo, o comunque dell'applicativo con interfaccia utente). Bello anche trovare i modi di invertire stringhe o ordinare array, certamente, ma ben presto (per me almeno che sono solo un amatore) diventa un esercizio un po' fine a se stesso.
Non sapevo che Python si potesse, alla bisogna, compilare.

LM