PDA

Visualizza versione completa : C++ N° 1 - Subito strani comportamenti


realtebo
02-05-2004, 16.02.37
#include <string>
#include <iostream>

std::string riga; //Una riga

void main()
{
// Inserimento
std::cout << "Inserire del testo:";
std::getline(std::cin, riga);

// Stampa
std::cout << "La lunghezza e' " << riga.length;

}



Ebbene, mi aspetto che mi dica 'inserire del testo'. e lo fa
io lo inserisco, premo invio e lui va a capo !
solo dopo un'altra pressione di invio passa alla fase di stampa, ma mi dice che la lunghezza e' di 1 carattere !!! xkè ?!

P8257 WebMaster
03-05-2004, 09.57.54
Perché come riga successiva, prende il carattere di Carriage Return.
Per risolvere il problema opererei a monte... ma non voglio confonderti le idee, diciamo che non devi vedere quel carattere.

Bye :cool:

LoryOne
03-05-2004, 12.15.26
Non capisco perchè:

"std::getline(std::cin, riga);"

Quanti input gli fai fare ?
Se per scrivere utilizzi std::cout << (standard out), per eseguire un input hai std::cin >>.

LoryOne
03-05-2004, 12.19.10
Consiglio:

Se non lo hai ancora fatto, ti consiglio di studiare cosa sono i namespace. E' fondamentale.

realtebo
03-05-2004, 14.56.27
'namespace' ok, ora me lo segno.

L'esempio da me quotato è preso pari pari (cut&paste) da un libro su c++ !

a dire il vero, sull help in line di V.Studio 6 la funzione getline richiede proprio tra parentesi la periferica da cui ricevere l'input e la variabile in cui metterla, cmq proverò con solo il cin >>

P8257 WebMaster
03-05-2004, 17.16.21
La sintassi a me sembra giusta (non posso provarlo per ora).. ribadisco ciò che ho detto sopra .. ed è riguardante quell'"a capo"...

Bye :cool:

realtebo
04-05-2004, 14.10.59
scusami P8257 ma non ho capito proprio il tuo primo commento. spiegami, non avere paura di conferndermi, grazie !..

LoryOne
04-05-2004, 15.19.04
Prima dell'introduzione della tipologia string, tra l'altro piuttosto recente, le stringhe venivano considerate come array di caratteri di tipo char.
Sebbene una stringa sia un'array di caratteri, definire una variabile di tipo string ed una di tipo char può sembrare la stessa cosa ma ci sono sottili differenze.

Se identifico s come stringa, devo scrivere:
string s;

Il compilatore assegna ad ogni componente dell'array s un quantitativo di memoria pari ad un byte ma non sa ancora di quanti byte sarà composta la stringa di caratteri.

Se identifico s come char, devo scrivere:
char s[]="";

Anche qui, il compilatore assegna ad ogni componente dell'array s un quantitativo di memoria pari ad un byte ma non sa ancora di quanti byte sarà composto l' array di caratteri.

In entrambi i casi il compilatore deve allocare un quantitativo di memoria indefinito ma comunque limitato.
Nel primo caso potrò definire s="Io vado al mare con mia moglie" come:

s="Io vado al mare ";
s+="con mia moglie";

cosa impensabile nel secondo caso.
Ora, se volessimo assegnare ad s un valore digitato da tastiera, in entrambi i casi si potrebbe scrivere:

cin >> s;

cin >> considera il carattere spazio come terminatore di stringa.
Fin qui tutto ok ma se volessimo inserire più parole separate da spazi come si potrebbe agire ?
Beh, dovremmo utilizzare un'altra funzione atta allo scopo, ossia getline.
cin.getline (funzione membro) surclassa la limitazione imposta dallo stream cin >>.
Questa funzione riempie un array di caratteri con i valori immessi da tastiera fino a quando non viene premuto il tasto invio "\n" ed elimina tale tasto dal valore restituito.

Si potrebbe quindi pensare di utilizzare questa funzione per eseguire un input da tastiera:
#include <iostream>

main (void) // oppure void main() in VC++
{
char s[80]; // imposto un array di caratteri abbastanza grande per l'input che devo effettuare
std::cout << "Immettere qualcosa : ";
std::cin.getline(s,sizeof(s)); //effettuo l'input
std::cout << "Hai immesso : " << s;
std::cin.get(); // premo un tasto per continuare
}

Se si prende in considerazione il codice postato da Realtebo sintatticamente è tutto corretto (tant'è che il compilatore compila senza poblemi) ma al momento dell'esecuzione del codice, sembra che il programma richieda due volte la pressione del tasto invio prima di procedere con l'esecuzione.

Possibile che VC++ sia affetto da un baco nell'utilizzo degli stream di input/output ?
Ho compilato lo stesso codice con DEV-C++ e non c'è stato nessun problema.

P8257 WebMaster
04-05-2004, 16.22.32
Ci sono effettivamente delle differenze nell'implementazione del set di oggetti di Visual C++ rispetto ad altri ambienti di sviluppo paralleli, ho potuto personalmente notarlo nel caso di altre procedure (arrotondamenti, gestione dei long ecc.) e la cosa non mi ha per nulla soddisfatto .. lasciando anche me con questo dilemma (ma non credo si tratti di bachi, piuttosto di differenti "interpretazioni").

Nell'esempio postato da Realtebo (anche se non ho potuto provarlo), sono quasi sicuro che il problema stia proprio nella pressione del tasto INVIO, e qui si scende in discorsi "filosofici" sull'implementazione dello stream.
Ciò che mi viene "al volo" da pensare è che alla pressione del tasto INVIO, non entri semplicemente un '\n' ma che la cosa sia stata implementata come "completo carriage return" e quindi '\n\r' il che cambia notevolmente le carte in tavola...

Il codice postato da Lory sembra più stabile in questo senso:

std::cin.getline(s,sizeof(s));


Questa linea, anche se non molto differente da quella postata da Realtebo, fornisce una maggiore sicurezza, dato che lo stream resterà aperto solo per un valore <= a sizeof(s).
Il punto cruciale della questione è che, alcune differenze di implementazione, come detto sopra, permettano ad uno o più caratteri (come il carriage return ad esempio) di rientrare nello stream ancora prima del terminatore di stringa.

Suggerisco di provare questa chiamata subito dopo la lettura dello strem:

std::cin.ignore()


Ignore può essere chiamata senza parametri (come in questo caso) per "strappare" un carattere dal fondo dello stream ed assicurarsi che nessun carattere indesiderato possa rientrare, altrimenti può essere chiamata con un numero corrispondente al numero di caratteri che desideriamo estirpare dallo stream, in modo da depurarlo di elementi indesiderati.

Io penso che questa differenza di implementazione sia risolvibile in questo modo, spero di essere stato esauriente.

Bye :cool:

realtebo
04-05-2004, 16.59.09
mmh.. alora grazie per la spiegazione. so di questa mutazione da c a c++ da char[] a oggetto string.

effettivamente ora che mi ci fai pensare sul manuale di v.studio 6 (quello dell'help in linea) se ne parla proprio nella sezione delle stringhe 'c-like'. questa sera a casa verifico
a) se nel manuale l'esempio riportato indicava questo limite
e
b) se con solo cin funziona

pholcus
05-05-2004, 12.57.58
Mah..
Ho compilato sotto linux il codice postato da realtebo con gcc, e nn mi ha dato alcun problema..

Dico la mia..secondo me e' un bug nel parsing della stringa dall'input standard MS..

La ragione potrebbe essere che sotto windows il terminatore e' \r\n

Sotto linux (\n) e sotto mac (\r) e' solo un carattere..

Ciao!

PS: considerazione personale..e' assurdo che nel 2004 il programmatore debba ancora perdere tempo e controllare queste cose in queste cose :rolleyes:

realtebo
05-05-2004, 13.07.26
daccordo, sia dell'assurdità della cosa sia che sotto linus girava...
cmq risolto, grazie.