Newsgroup: it.comp.lang.c++
Titolo: Come leggere gli spazi: parte seconda

Il primo post era mio, ma mi stavo collegando dalla biblioteca, quindi è
risultato firmato da un certo Angelo...
Comunque ringrazio per avermi dato quei due belli esempi (in particolar modo
Alex, sempre il massimo!), ma io cercavo un metodo molto più semplice
(sempre se esiste) per copiare un file in un altro.
Vi scrivo il codice che sto usando, così capite come sto cercando di
risolvere il problema degli spazi non letti:
#include <stdio.h>
int main()
{
 FILE *fin, *fout;
 int temp_f=0;
 char leggo[230];
 /*
 printf("\nInserire il nome del file di input: \n");
 scanf("%s",&input_file);
 printf("\nInserire il nome del file di output: \n");
 scanf("%s",&output_file);
 */
 fin=fopen("c:\\file1.txt","r");
 fout=fopen("c:\\file2.txt","w");
 while (fscanf(fin,"%f",&temp_f) != EOF)
 {
  fscanf(fin,"%s",&leggo);
  fprintf(fout,"%s\n", leggo);
 }
 fclose(fin);
 fclose(fout);
 return(0);
}
Inizialmente i nomi dei file li inserivo manualmente, ma visto che il
programma non funzionava bene mi sono concetrato su due soli file,
"file1.txt" e "file2.txt", che ovviamente esistono già.
In più gradirei sapere se esiste il modo di riconoscere il carattere di fine
linea, come in Pascal (eoln).
Grazie in anticipo a tutti.
--
San Vegeta from Hell
http://www.geocities.com/Area51/Dungeon/8436
http://come.to/Fantasy.it

...

Il codice ASCII credo che sia il 13 (Ritorno a capo) o il 10 (salta linea)

linea, come in Pascal (eoln).
Il carattere di fine-linea ha il codice '\n'; per modificare il ciclo
di cui sopra per contare i caratteri di fine-linea presenti, invece
che copiare su fout, basta fare:
    int c;
    int nn=0;
    while((c=fgetc(fin))!=EOF)
        if(c=='\n') ++nn;
Alex


/* Copia un file - 'sizeBuffer' definisce la quantita in byte di
memoria da
riservare per il buffer di trasferimento dei dati (default = 512) - Se
la
funzione non riesce a riservare la memoria richiesta prova ad
impostare
'sizebuffer' al valore di default = 512 -
*/
#include <stdio.h>
#include <io.h>
 int FileCopy(char *FileOrg,char *FileCopia,unsigned int
sizeBuffer=512)
{
 char *buffer = 0 ;
 unsigned int nbyte = 0 ;
 int ret = 0 ;
 long start , size ;
 FILE *Org   = 0 ;
 FILE *Copia = 0 ;
 struct ftime ft ;
 for ( register int x = 0 ; x < 2 ; x ++ ) {
       buffer = new char[sizeBuffer] ;
       if ( ! buffer ) { sizeBuffer = 512 ; continue ; }
       x ++ ;
       }
 if ( ! buffer ) goto termina ;
 Org   = fopen(FileOrg,"rb") ;
 Copia = fopen(FileCopia,"wb") ;
 if ( ! Org || ! Copia ) goto termina ;
 nbyte = sizeBuffer ;
 size = filelength(fileno(Org)) ;
 start = 0 ;
 if ( size < nbyte ) nbyte = size ;
 if ( size == 0 ) goto preterm ;
 while ( 1 ) {
       start += nbyte ;
       if ( start > size ) break ;
       fread(buffer,nbyte,1,Org) ;
       fwrite(buffer,nbyte,1,Copia) ;
       }
 nbyte -= (start-size) ;
 if ( nbyte == 0 ) goto preterm ;
 fread(buffer,nbyte,1,Org) ;
 fwrite(buffer,nbyte,1,Copia) ;
 preterm :
 fflush(Copia) ;
 getftime(fileno(Org),&ft) ;
 setftime(fileno(Copia),&ft) ;
 start = filelength(fileno(Copia)) ;
 if ( start != size ) ret = 0 ;
 else ret = 1 ;
 termina :
 fclose(Org) ;
 fclose(Copia) ;
 if ( buffer ) delete [] buffer ;
 return ret ;
}
~~~~~~~~~~~~~~~~~
MAINARDI Gianfranco
Burago di Molgora (MI)
Italia
Email : 
main...@tin.it
ICQ# number : 11607125
~~~~~~~~~~~~~~~~~

quindi non può verificarsi il caso leggo=='\n' ?
Il formato "%s" di fscanf non legge mai il "whitespace"; la definizione
di "whitespace", oltre al carattere ' ' ("spazio", codice 32 in ANSI),
comprende anche '\t' ("tabulazione"), '\n' ("fine riga"), e altri.
Il whitespace, e quindi in particolare il '\n', TERMINA la "parola"
letta con "%s", e non ne fa parte.
Inoltre: visto che dal tuo "if(leggo=='\n')" pare che "leggo" sia una
variabile di tipo char, la fscanf fara` probabilmente andare in
crash la tua macchina non appena sul file di input si trovera` una
parola sufficientemente lunga; infatti, essa da` per scontato che
il puntatore passato in corrispondenza a %s punti, non a UN solo
carattere, ma entro un buffer sufficientemente lungo per poterci
copiare dentro tutti i caratteri della parola presente sull'input, uno
dopo l'altro.  Cercando di fare tale copia su di un'area che in
realta` e` di 1 solo byte di lunghezza, "sporchera`" altre variabili
in memoria e in tutta probabilita` portera` presto a crash e/o vari
comportamenti anomali.
Questo tipo di fenomeno rende *pericolosissimo* l'uso delle
"antiche" chiamate di I/O, e molto preferibile, invece, l'uso di
quelle, assai meno rischiose, fornite dalla parte "iostream"
della libreria del C++.  Comunque, anche quelle non sono del
tutto tranquille, se usi costrutti di bassissimo livello come gli
array di caratteri; quello che ti garantisce la tranquillita` e`
usare iostream insieme alle *stringhe*, pure fornite dalla libreria
standard del C++.  Se fin e`, NON un "FILE *" come si sarebbe
dovuto fare in C 25 anni fa per mancanza d'alternative, ma uno
std::istream (input-stream standard C++), e s e` una std::string
(stringa standard C++):
    fin >> s;
legge la prossima parola dal file di input alla stringa "senza alcun
rischio" (anche questa, come %s, usa il whitespace come
terminatore), mentre:
    std::getline(fin,s);
legge la prossima _riga_ eccetera.
Per ulteriori esplorazioni delle possibilita` di I/O offerte dal solo
linguaggio C (come fscanf, ecc) ti consiglierei di passare su
it.comp.lang.c, dedicato appunto alla discussione di quel
linguaggio; in it.comp.lang.c++ potrebbe essere piu` appropriato
discutere dei meccanismi di I/O offerti (in addizione alla
"compatibilita` all'indietro" con quelli del C) dal linguaggio C++,
piu` sicuri, flessibili, semplici (grazie alla gestione automatica
della memoria offerta da std::string ecc), eccetera.
Alex