View Full Version : [C++] Bug di GCC (o meglio, MinGW)?
vendettaaaaa
21-06-2013, 23:18
Ciao,
ho questo codice:
int main(int arcg, char* argv[])
{
{
// Open input file stream
ifstream ifs("Test Element.txt");
if (!ifs)
throw runtime_error("Couldn't open the input file!");
// Find the beginning of the Element Data section
string line;
while (getline(ifs, line, '\n'), line != "$* ELEMENT DATA")
{
if (ifs.eof())
{
cout << "Cannot find Species Data!!" << endl;
return 0;
}
}
// Save the beginning of the Element Data section
streampos begin = ifs.tellg();
}
}
con questo file di testo:
!File di prova per testare la routine di gestione degli elementi
$* ELEMENT DATA
C .1201070000D+02 CO2 CO2 .3700000000D-03
H .1007940000D+01 H2O H2O .0000000000D+00
N .1400670000D+02 N2 N2 .7809000000D+00
O .1599940000D+02 O2 O2 .2095000000D+00
$* END OF ELEMENT DATA
Ebbene, se eseguo il tutto in VS 2012, begin ha valore 85, mentre se uso QtCreator con MinGW (4.7, o 4.8, non cambia) ha valore 94, che è ERRATO!
Infatti se poi faccio ifs.seekg(begin) e uso getline, in VS ottengo la linea intera
C .1201070000D+02 CO2 CO2 .3700000000D-03
mentre con MinGW ottengo
70000D+02 CO2 CO2 .3700000000D-03
e non capisco davvero perchè! Mi sfugge qualcosa o è un baco?
vendettaaaaa
22-06-2013, 09:25
Avrei potuto svegliarmi prima a cercare in Google...speriamo almeno che possa tornare utile a qualcun'altro :cool:
http://stackoverflow.com/questions/9817806/why-does-my-program-produce-different-results-on-windows-and-linux-about-file-r
The difference you're seeing between Windows and Linux is because the file is open in text mode: newline characters will be converted silently by the implementation. This means that the combination "\r\n" (used in Windows for newlines) will be converted to a single '\n' character in Windows, making the file have only 8 characters. Note how vim shows a ^M at the end of the first line: that's the '\r' part. In Linux a newline is just '\n'.
You should open the file in binary mode if you want to preserve the original as is:
file.open(path, std::ios_base::in | std::ios_base::binary);
Io sono su Windows, ma MinGW a quanto pare usa le stesse librerie di GCC per Linux e quindi il discorso si applica anche al mio caso :)
Su Linux con GCC 4.8.1, il tuo file con codifica UNIX da il risultato giusto (82, C .1201070000D+02 CO2 CO2 .3700000000D-03)
Già il fatto che VS ti dica che ti trovi in posizione 85 è strano e fa pensare proprio che il file ha una codifica Windows (ovvero \r\n al posto di \n)
Ecco cosa succede se uso la codifica Windows sul file:
Cannot find Species Data!!
Che è il risultato atteso
VS funziona correttamente perchè la libreria standard di C++ MS controlla il fine riga come prima cosa anche se imposti un tuo delimitatore
Per MinGW invece mi pare un bug - certo che è strano che nessuno lo abbia notato prima - prova a chiedere nella loro mailing list
Forse la maniera più semplice, è usare la codifica *NIX
Fai sapere che ti rispondono sulla loro mailing list
vendettaaaaa
22-06-2013, 09:46
Intanto grazie per la risposta!
Io sono stato un po' precipitoso a cantar vittoria: se apro il file in modalità binaria, ora ottengo ad un certo punto
line == "$* ELEMENT DATA\r"
e quel CR fa fallire la comparazione...
Intanto scrivo alla mailing list di MinGW, poi continuo a provare...il fatto strano è che seekg sembra funzionare bene, è proprio tellg che scazza...
vendettaaaaa
22-06-2013, 11:15
Update: aprendo il file in modalità binaria, leggendo carattere per carattere e stampando i caratteri su un file di output, ottengo che 'C' è il carattere immediatamente successivo all'85 e '7' è successivo a 94:
Character 80 = D
Character 81 = A
Character 82 = T
Character 83 = A
Character 84 = \r
Character 85 = \n
Character 86 = C
Character 87 =
Character 88 =
Character 89 = .
Character 90 = 1
Character 91 = 2
Character 92 = 0
Character 93 = 1
Character 94 = 0
Character 95 = 7
Character 96 = 0
Character 97 = 0
Character 98 = 0
Character 99 = 0
mentre aprendo il fine senza specificare ios_base::binary, 'C' sta dopo la posizione 82 come dicevi tu, nico:
Character 80 = T
Character 81 = A
Character 82 = \n
Character 83 = C
Character 84 =
Character 85 =
Character 86 = .
Character 87 = 1
Character 88 = 2
Character 89 = 0
Character 90 = 1
Character 91 = 0
Character 92 = 7
Character 93 = 0
Character 94 = 0
Character 95 = 0
Character 96 = 0
Character 97 = D
Character 98 = +
Character 99 = 0
Sembrerebbe quindi che tellg() restituisca la posizione leggendo i caratteri "raw" anche se il file è stato aperto in modalità text...
// Open input file stream
bool binary = true;
ifstream ifs;
if (binary)
ifs.open("Test Element.txt", ios_base::binary);
else
ifs.open("Test Element.txt");
if (!ifs)
throw runtime_error("Couldn't open the input file!!\n");
ofstream ofs("tellg debug.txt");
if (!ofs)
throw runtime_error("Couldn't open the output file!!\n");
char c;
string s;
int n = 0;
while (ifs.get(c))
{
++n;
s += c;
if (n < 100)
{
ofs << "Character " << n << " = ";
if (c == '\r')
ofs << "\\r" << endl;
else if (c == '\n')
ofs << "\\n" << endl;
else if (c == '\t')
ofs << "\\t" << endl;
else
ofs << c << endl;
}
}
cout << "String s: " << endl << s << endl << endl;
ofs << endl;
if (binary)
ofs << "File opened in binary mode" << endl;
else
ofs << "File opened in text mode" << endl;
ofs << "Character 82 = " << s[82] << endl << endl;
ofs << "Character 83 = " << s[83] << endl << endl;
ofs << "Character 85 = " << s[85] << endl << endl;
ofs << "Character 94 = " << s[94] << endl << endl;
return 0;
Su *NIX (Linux, Mac OS X, FreeBSD...) non c'è alcun bisogno di conversione, quindi il discorso si chiude qua
La libreria standard di MS pare gestire i casi come std::getline direttamente all'interno della funzione, senza nascondere allo sviluppatore i caratteri \r che vengono conteggiati anche in text mode.
Non avendo mai programmato C++ su Windows non so dirti di più :D
MinGW nasconde le differenze tra \n e \r\n sfruttando il fatto che è qualcosa che lo standard prevede - il problema è che pare buggato:D
Il tutto non dovrebbe dare problemi, finchè:
- Non provi ad aprire un file creato su Windows su *NIX
- Non usi un compilatore che ha problemi
Più o meno è la situazione che si trova anche in altri luoghi (Java, C#...)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.