|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
[C++] Stringhe standard
Torno ad affrontare il c++ con qualche nuovo esperimento.
Ho inizialmente gestito le stringhe con gli string, ma il c++ standard dovrebbe prevedere l'uso dei vettori di caratteri char. Ho imbastito questo semplice codice per cercare di capire quello che combina. Codice:
char input[4]; cin.getline(input, 4); cout << input; Se digito direttamente invio mi stampa di fatto una riga vuota. Se digito sino a 3 caratteri me li stampa. Se digito 4 caratteri o più, me ne stampa 3. So che una stringa prevede il carattere terminatore \0. Significa che i caratteri digitati e visibili in output sono 3 perchè il quarto è il terminatore e non è visibile in output? Quando digito più di 4 caratteri, in cin rimangono i caratteri seguenti che poi possono finire da qualche parte e alterare qualcosa? Come lo pulisco? E gli spazi? Come li tolgo? Mi chiedevo poi come poter gestire il controllo della stringa che dovrebbe contenere solo cifre per una conversione a intero. Pensavo di usare un algoritmo che avevo già utilizzato, cioè scansionare la stringa e testare con isdigit ogni singolo elemento, prevedendo poi il caso di numero che inizia con 0, come 02, di cui segnalerei l'errore. Esistono sistemi migliori?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Apr 2010
Città: Frosinone
Messaggi: 416
|
in realtà le stringhe intese come vettori di caratteri terminati da '\0' sono più proprie del C che del C++, la classe string è standard ed è decisamente più comoda per fare le operazioni che hai elencato tu
inoltre la classe stringstream può fare il lavoro che dici sui numeri, qui trovi un esempio: http://www.cplusplus.com/reference/i...perator%3E%3E/ tuttavia, con ogni probabilità, i numeri che iniziano con la cifra 0 vengono interpretati come ottali (in linea con quello che succede in C e C++ quando imposti il valore di una variabile intera) |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Quote:
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2010
Città: Frosinone
Messaggi: 416
|
allora per quanto riguarda la storia dei numeri, c'è la funzione strtol: http://www.cplusplus.com/reference/c...stdlib/strtol/
invece per quanto riguarda gli spazi, se vuoi toglierli ti tocca scrivere una funzione che lo faccia |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Non sono ancora riuscito a risolvere la questione per l'acquisizione.
Se eseguo questo codice: Codice:
char stringa [5]; cin.getline(stringa, 5); cout << stringa << endl; cin.getline(stringa, 5); cout << stringa << endl; Se invece digito qualcosa di più lungo, mi stampa i 4 caratteri e poi, a capo, riga vuota prima di concludersi regolarmente, e questo non va per niente bene. Come posso risolvere?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Apr 2010
Città: Frosinone
Messaggi: 416
|
vuol dire che ti serve un buffer più grande dei miseri 5 caratteri ^_^
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Quote:
Ho provato ad aggiungere: Codice:
cin.getline(stringa, 5); cout << stringa << endl; cin.clear(); fflush(stdin); cin.getline(stringa, 5); cout << stringa; cin prevede un buffer che contiene i caratteri digitari giusto? Quindi cin.getline(destinazione, N) mi legge N caratteri da quel buffer. Se il buffer contiene più di N caratteri, se non lo resettassi rimarrebbero i caratteri rimanenti a partire da quello corrispondente al tasto invio che premo per stampare la prima stringa del codice (e sarebbe spiegata anche la ragione della riga vuota al secondo passaggio). Dico bene? Il buffer è in una zona di memoria riservata che non pasticcia su quella per il programma? Cioè, la presenza di caratteri in più, anche se ne facessi leggere il numero giusto, comporta qualche malfunzionamento o in questo caso devo solo occuparmi di non superare il limite della stringa che conterrà quanto voglio fare leggere alla getline?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. Ultima modifica di zanardi84 : 29-03-2011 alle 17:10. |
|
|
|
|
|
|
#8 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Da MSDN...
"IF the function extracts _Count - 1 elements, it calls setstate(failbit). In any case, it returns *this." In pratica la prima chiamata ti legge i dati ma avendo piu' caratteri, ti stampa la stringa corretta ma imposta il bit d'errore. Di conseguenza la seconda chiamata viene ignorata. Per verificare l'eventuale errore puoi inserire dopo la prima cout le righe: bool b=cin.fail(); cout << "Fail=" << b << endl; Se inserissi solo la .clear, otterresti la stampa dei successivi dati inseriti nella prima cin. Spero di essere stato chiaro Ciao
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Quote:
Ma poi?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Se fai solo la .clear, ottieni l'esecuzione della seconda getline(), che elaborera' il restante contenuto dello stream di input (cin).
Quindi sei tu che devi decidere... Puoi gestirti un loop per elaborare/svuotare l'input dell'utente (utilizzando la clear) -----------(p.e.)--------- cin.getline(stringa, 5); cout << stringa << endl; while cin.fail() // se errore ho un overflow. leggo e svuoto! { cin.clear(); cin.getline(stringa, 5); cout << stringa << endl; } -------------------------- oppure semplicemente buttare l'eccedenza (.clear e fflush). Tieni conto che il numero di caratteri gestiti dalla getline e' il valore del secondo parametro -1. A questo punto per la conversione in numerico puoi utilizzare strtol/atoi/atol etc. Ciao
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Quote:
Per curiosità se tentassi un approccio così? Codice:
char buffer[1000]; char stringa[5]; cin.getline(stringa, buffer, 4); stringa[4] = '\0'; Già che ci sono: visto che devo trattare anche float e double, che approccio mi consigli per la conversione?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. Ultima modifica di zanardi84 : 30-03-2011 alle 14:44. |
|
|
|
|
|
|
#12 | |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Quote:
Cioe' quando dallo standard di input preleva un carattere corrispondente al delimiter (p.e. il tab), interrompe la lettura ed esce. (Normalmente questo sistema lo usi per la lettura di file e non per lo streaming prodotto dalla tastiera). Inoltre il \0 finale lo dovrebbe inserire la getline() a "gratisse" ma ti consiglio di verificare (ah la memoria!!!). Un buon giro di debug aiuta a capire tanti comportamenti "nascosti". Per gli approcci dipende da te. Personalmente se prevedo un input di 10 caratteri e l'utente me ne inserisce 20, io normalmente elimino il superfluo!!! Se al contrario prevedo un input di 500 caratteri, allora mi adatto ad una gestione un po' piu' "amichevole". nel tuo caso penso che un'input secco buttando l'eccesso sia preferibile visto che in fondo devi inserire semplicemente dei numeri. per le conversioni: atoi(), atol(), strtol() convertono da Ascii/STRinga ad Intero/Long atof(), strtod() convertono da Ascii/STRinga ad double PS occhio che se i risultati non ti tornano, dai un'occhiata ad eventuali cast... Ciao
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Quote:
Non era quel cin.getline, ma era cin.getline(buffer, 1000) e poi strncpy(stringa, buffer, 4), seguita da stringa[4] = '\0'.
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
|
#14 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
In questo modo rischi di confondere l'utente.
Pensi di aver inserito "12345678" e poi ti accorgi che ti elabora solo "1234". Allora piu' carino sarebbe prendi l'input di 4 caratteri (cin.getline(stringa, 5) e se vai in overflow mandi un msg di errore (input troppo lungo), pulisci lo stream e richiedi l'input. Ovviamente il tutto sempre se vale la pena e ti va di "divertirti"...
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Ma visto che si parla di C++ e "Stringhe standard" perchè non usare le stringhe standard (string) del C++?
Che tra l'altro risolverebbero ogni problema, in questo caso. |
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Quote:
Come posso fare il confronto sull'overflow, e su cosa?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Gli string sono oggetti e nascondono le insidie! Usare gli elementi di base costruendo le proprie funzioni è più istruttivo per chi sta imparando. Gli string sono una stupidata da implementare (nonchè una figata!)
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
|
#18 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
La cin.getline() si preoccupa di metterti il terminatore di stringa (aka \0) in caso di input superiore.
Per il test dell'overflow puoi usare if cin.fail() errore Comunque, riflettendo sui commenti degli altri, devo dire che in realta' non stai utilizzado il C puro (K&R) E' vero per quel che riguarda la definizione della variabile char, ma nel C la "cin.getline()" te la sogni!!!! Ti dovresti ingegnare con la getchar e dintorni. E li si che avresti tutti i problemi inerenti il "buffer overflow" ed affini. Ma questa (come dice uno tizio della televisione) e' un'altra storia Ciao
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5751
|
Risolto! Ora dovrò trovare qualcosa per scandire la stringa per ammettere il punto e/o la virgola come separatore. Qualche idea?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 15:28.




















