PDA

View Full Version : [C/C++] Ridirezionamento output su file


shang84
06-11-2005, 16:34
Ciao a tutti,
non ricordo più come fare per ripristinare lo standard output su monitor, anzichè su file, al termine del ciclo..

Cosa sto dimenticando? Sicuramente ho tralasciato qualche dup/dup2 per ripristinare il flusso, ma sono fuso ora e non capisco dove..


grazie!

using namespace std;
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char *argv[]){
for(int i=0;i<10;i++){
int fd;
fd=open(argv[1],O_WRONLY|O_APPEND|O_CREAT);
dup2(fd,1);
cout << "mia zia è sexy!" << endl;
chmod(argv[1],S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
close(fd);
}
cout << "Questo non lo displaya" << endl;
return 0;
}

ilsensine
07-11-2005, 09:32
Devi prima salvare l'fd originale:
int old_fd = dup(fileno(stout));
e infine ripristinarlo:
dup2(old_fd, fileno(stdout));
dopo aver evvettuato i flush del caso.

NB la tua è una pessima tecnica, in quanto il c++ supporta tranquillamente gli stream su file.

shang84
07-11-2005, 13:02
Ok, hai ragione! Non avevo ricevuto la notifica della tua risposta quindi ho creato una nuova discussone credendo nessuno avesse risposto.

Cmq ora ho sistemato e funziona la ridirezione.

Cosa intendi per flush?

PS: io sono il tizio del Santech che doveva verificare quali sono i driver che non vanno bene, appena torno a casa (nei prossimi giorni) proverò a fare come dici tu.. scusa il ritardo!

Thanks

ilsensine
07-11-2005, 13:14
Cosa intendi per flush?
Stai facendo una cosa sbagliata, ovvero accedere a un file in due modi: tramite il descrittore e tramite un layer di astrazione. Il layer di astrazione potrebbe benissimo introdurre una sua bufferizzazione, che viene persa se cambi l'fd sotto i piedi (o finire nel fd sbagliato). In particolare, stdout è notoriamente line-buffered, ma cout potrebbe benissimo essere implementata aggiungendo addirittura altre cose.

In soldoni: usa gli strumenti di streamed I/O del c++ se devi scrivere su un file.

ilsensine
07-11-2005, 13:26
nb c'è inoltre un bug serio; se la open viene invocata con O_CREAT, occorre passare un terzo parametro (il "modo" di creazione, ad es. 0640). Nel tuo caso, se il file non esiste e viene creato, gli attributi saranno assolutamente casuali.

shang84
07-11-2005, 13:46
E' vero.. infatti non capivo perchè poi non mi lasciava copiare la cartella in cui è scritto il codice. Ora ho modificato aggiungendo 0640 e funzica meglio.

Grazie..

vedrò inoltre di usare le librerie del c++

ilsensine
07-11-2005, 13:50
vedrò inoltre di usare le librerie del c++
Più semplice di quanto credi:
http://www.cplusplus.com/ref/iostream/ofstream/open.html

ilsensine
07-11-2005, 13:56
E questo infine è un esempio pratico del perché il tuo metodo è sbagliato.
Prova a eseguire questo programma, e vedrai che la scritta "ciao" finisce nel file prova.txt!

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>

int main(void)
{
std::cout << "ciao";
dup2(open("prova.txt", O_WRONLY|O_CREAT|O_APPEND, 0640), fileno(stdout));
return 0;
}

shang84
14-11-2005, 11:29
Cosi facendo però mi da un errore di compilazione...


ofstream outfile;
outfile.open (argv[1], ofstream::out | ofstream::app);
outfile << "prova";
outfile << spectras[i]->display_results() << endl;
outfile.close();


nb: il metodo display_results() fa il cout dei diversi campi della classe...

Cosa ne dici?
Il problema è che non riconosce il metodo della classe come stdout secondo me..

make
g++ -c main.cpp
main.cpp: In function `int main(int, char**)':
main.cpp:76: error: no match for 'operator<<' in 'outfile <<
spectras[i]->MsmSpectra::display_results()'
/usr/include/g++/bits/ostream.tcc:63: error: candidates are:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ostream<_CharT,
_Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char,
_Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:74: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_ios<_CharT,
_Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits
= std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:86: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::ios_base&(*)(std::ios_base&)) [with _CharT = char,
_Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:122: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(long int) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:156: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:98: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(bool) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/ostream:178: error: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/ostream:189: error: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned
int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/ostream:193: error: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT
= char, _Traits = std::char_traits<char>]
/usr/include/g++/ostream:204: error: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int)
[with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:181: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(long long int) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:216: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:241: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(double) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/ostream:219: error: std::basic_ostream<_CharT,
_Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:265: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(long double) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:289: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(const void*) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:313: error:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT =
char, _Traits = std::char_traits<char>]
/usr/include/g++/ostream:436: error: std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:512: error:
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, char) [with _Traits = std::char_traits<char>]
/usr/include/g++/ostream:447: error: std::basic_ostream<char,
_Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char)
[with _Traits = std::char_traits<char>]
/usr/include/g++/ostream:452: error: std::basic_ostream<char,
_Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char)
[with _Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:572: error:
std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/bits/ostream.tcc:616: error:
std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char,
_Traits>&, const char*) [with _Traits = std::char_traits<char>]
/usr/include/g++/ostream:486: error: std::basic_ostream<char,
_Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const signed
char*) [with _Traits = std::char_traits<char>]
/usr/include/g++/ostream:491: error: std::basic_ostream<char,
_Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const unsigned
char*) [with _Traits = std::char_traits<char>]
/usr/include/g++/iomanip:82: error: std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&,
std::_Resetiosflags) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/iomanip:116: error: std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&,
std::_Setiosflags) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/iomanip:154: error: std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&,
std::_Setbase) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/iomanip:227: error: std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&,
std::_Setprecision) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/g++/iomanip:261: error: std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Setw)
[with _CharT = char, _Traits = std::char_traits<char>]
make: *** [main.o] Error 1



Ho poi provato così:


ofstream outfile;
outfile.open (argv[1], ofstream::out | ofstream::app);
outfile.operator<< (spectras[i]->display_results());
outfile.close();

Ma mi dice che l'utilizzo della funzione in questo modo è invalido..

ilsensine
14-11-2005, 11:53
Cosi facendo però mi da un errore di compilazione...


ofstream outfile;
outfile.open (argv[1], ofstream::out | ofstream::app);
outfile << "prova";
outfile << spectras[i]->display_results() << endl;
outfile.close();


nb: il metodo display_results() fa il cout dei diversi campi della classe...

...e outfile::operator<<, dotato di sfera di cristallo, riesce a intuire che quel metodo scrive con cout e a catturare il risultato, vero? :D

Puoi passare un reference dell'ostream outfile al metodo display_results, e usarlo al posto di cout, oppure far sì che display_results ritorni una stringa o simile oggetto per il quale l'operatore << può capirci qualcosa ;)
Ad esempio la prima strada puoi seguirla così:

class myclass {
void display_results(ostream &os=cout);
};
...
void myclass::display_results(ostream &os)
{
os << "scrivo qualcosa" << endl;
}

int main(void)
{
ofstream ofile;
myobject = myclass::create();

ofile.open("ciao.txt", ofstream::out | ofstream::app);
myobject->display_results(ofile); // scrive su ofile
ofile.close();
...
myobject->display_results(); // scrive su cout!
}

shang84
14-11-2005, 12:57
...e outfile::operator<<, dotato di sfera di cristallo, riesce a intuire che quel metodo scrive con cout e a catturare il risultato, vero? :D


:mc: mi piace la programmazione fantasy :D

Cmq ora funziona tutto, ho fatto come dicevi tu passando al metodo direttamente lo stream. E' una figata così, molto efficacie da gestire..

grazie per la dritta :)