Newsgroup: it.comp.lang.c
Titolo: Aiuto cercasi

Ciao a tutti.
Mi sono scritto un programmino per modificare pseudocasualmente dei byte di 
un file per testare un algoritmo di un programma di backup(rsync) che 
trasferisce solo le differenze fra file...
Il programma è il seguente:
----------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
void exit(int status);
FILE *fp;
int dimensione,buffer,i,numero_iterazioni,seed,casuale;
main(int argc, char *argv[])
{
 if(argc!=4)
  {
   printf("Sintassi: ./prova nomefile seme numero_iterazioni\n");
   exit(0);
  }
 fp=fopen(argv[1],"r+");
 if(fp==NULL)
  {
   printf("File inesistente o inaccessibile in lettura!\n");
   exit(0);
  }
 else
  {
   fseek(fp,0,SEEK_END);
   dimensione=ftell(fp);
   seed=atoi(argv[2]);
   srand(seed);
   numero_iterazioni=atoi(argv[3]);
   for(i=0;i<numero_iterazioni;i++)
   {
    casuale=rand()%dimensione;
    fseek(fp,casuale,SEEK_SET);
    buffer=fgetc(fp);
    buffer=buffer^rand()%400000000;
    fseek(fp,casuale,SEEK_SET);
    fputc(buffer,fp);
    fflush(fp);
   }
   fclose(fp);
  }
}
--------------------------------------------------------
In pratica il programma funziona così:
da riga di comando prendo il nome del file da modificare, il seme da mettere 
nella rand e il numero di iterazioni.
Poniamo che il numero di iterazioni sia uguale a 5:
per 5 volte il programma accederà pseudo-casualmente in determinate parti 
del file e applicherà  lo xor(byte_letto^rand()%400000000).
La particolarità dello xor è che dovrebbe essere una funzione 
invertibile(a^b^b=a giusto? )
Come caso di test ho preso un'immagine iso(circa 700Mb) e ho eseguito due 
volte il programma:
steve suse.iso 10802(il seme) 1000(il numero di interazioni).
Su linux per verificare se tutto andava correttamente eseguivo la cksum del 
file prima e dopo aver eseguito per due volte il programma. Tutto ok...
Ho provato anche a creare un file con 92 a e ho eseguito due volte il 
programma con gli stessi dati di cui sopra: tutto ok...
Su windows ho provato a creare col notepad un file con 92 a e ho rieseguito 
due volte il programma ma non funzia!
Lo strano e' che se per esempio digito:
nome_programma file_da_modificare 10802(seed) 100(numero iterazioni)
nome_programma file_da_modificare 10802(seed) 100(numero iterazioni)
tutto ok ma se aumento il numero di interazioni a 1000 non funziona!
Secondo voi ho sbagliato qualcosa?
E' normale che se eseguo
steve nome_programma 10802 1000 su un programma piccolo mi termina molto 
prima che su un programma grande?
Grazie in anticipo per le risposte
Stefano

 due volte il programma ma non funzia!
Vedi [1]. Con Linux (o un qualsiasi OS POSIX) funziona perchè non c'è
differenza tra un apertura di una file in modo testo o in modo binario
(c'è sempre corrispondenza 1:1 tra quando passato alle funzioni di I/O e
quanto scritto su file). Su win non è così, ad esempio viene effettuata
la conversione dei newline ('\n' -> '\r\n' in scrittura e viceversa in
lettura). Devi aprire il file specificando il flag "b" nella fopen().
Luca
-- 
Home: 
http://kronoz.cjb.net
Tentare e` il primo passo verso il fallimento.
Homer J. Simpson


Ok l'ho fatto e funziona tutto! Grazie!  Ti chiedo un ultima cosa (OT): 
eseguendo lo stesso mio programmino con gli stessi parametri e con lo stesso 
file da modificare su un celeron 2.2 ghz con 192 mb di ram con OS linux 
fedora core5  e' normale che richieda anche 10 volte il tempo che richiede 
un Pentium IV 2.4 ghz con 512 mb di ram con OS winXp?
La mia è solo curiosità... Il file e' di circa 700Mb
Ciao e grazie ancora!
Stefano


 ha scritto nel messaggio
news:eg0hhn$f2m$1...@dreamland.darkstar.lan...

Anche con il "b" non è garantito al 100% che fseek(fp,0,SEEK_END);
funziona!
Comunque normalmente sì.
--
Giorgio Silvestri
DSP/Embedded/Real Time OS   Software Engineer

 Comunque normalmente sě.
Sono curioso.Come mai? 

Ah un'altra cosa... Come mai il mio programmino su WinXp va velocissimo e 
con gli stessi parametri e lo stesso file su Linux va anche 10 volte piu' 
lento? All'inizio pensavo fosse un problema di potenza del processore e/o di 
memoria. Ma adesso ho provato tutto sullo stesso computer(Pentium IV 2.4ghz 
512Mb ram) e i risultati sono gli stessi 

Rimetto il listato:
#include <stdio.h>
#include <stdlib.h>
void exit(int status);
FILE *fp;
int dimensione,buffer,i,numero_iterazioni,seed,casuale;
main(int argc, char *argv[])
{
 if(argc!=4)
  {
   printf("Sintassi: ./prova nomefile seme numero_iterazioni\n");
   exit(0);
  }
 fp=fopen(argv[1],"r+b");
 if(fp==NULL)
  {
   printf("File inesistente o inaccessibile in lettura!\n");
   exit(0);
  }
 else
  {
   fseek(fp,0,SEEK_END);
   dimensione=ftell(fp);
   seed=atoi(argv[2]);
   srand(seed);
   numero_iterazioni=atoi(argv[3]);
   for(i=0;i<numero_iterazioni;i++)
   {
    casuale=rand()%dimensione;
    fseek(fp,casuale,SEEK_SET);
    buffer=fgetc(fp);


 ha scritto nel messaggio
news:eg2gkc$f4f$1...@sun250.unimi.it...

Lo dice lo standard C.
C99: 7.19.9.2   The fseek function
Synopsis
#include <stdio.h>
int fseek(FILE *stream, long int offset, int whence);
...
A binary stream need not meaningfully support fseek calls with whence of
SEEK_END.
...



OT {
    La disparità di efficienza potrebbe dipendere dalla
    bontà del file-system del particolare OS e quindi
    si riflette poi sulle funzioni C (la libreria!) che si appoggiano
    a system-call del sistema operativo stesso.
    Può anche dipendere da quanta RAM viene effettivamente usata.
    Magari molta meno di quella disponibile.
    Se ci sono meccanismi di cache più o meno efficienti
    nei due sistemi.
    Dimensioni dei file di swap.
}
Può dipendere da un sacco di cose!


lento?
Prova senza fflush.

 ...
Ma allora... in C99 qual' e' il modo standard per andare a EOF di un file
aperto in modo "rb+" per appendere altri bytes senza riaprirlo in "ab" ?
Ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 aperto in modo "rb+" per appendere altri bytes senza riaprirlo in "ab" ?
Hum, leggere fino alla fine del file? Perchè non vuoi usare "a"?
Luca
-- 
Home: 
http://kronoz.cjb.net
"La vita potrebbe non avere alcun significato. Oppure, ancora peggio,
 potrebbe averne uno che disapprovo". -- Ashleigh Brilliant

Hum, leggere fino alla fine del file? Perchè non vuoi usare "a"?
...spiegare perché dovrebbe dare problemi, no eh ? :-)

 
mai trovato un sistema su cui fseek(..,..,SEEK_END) non abbia 
funzionato, comunque, se proprio bisogna:
long int size;
size = ftell(fp);		   // Longhezza del file, in bytes...
result= fseek(fp, SEEK_SET, size); //...e sono a file file :-)
oppure feof();
ciao

 result= fseek(fp, SEEK_SET, size); //...e sono a file file :-)
Luca
-- 
Home: 
http://kronoz.cjb.net
"It is more complicated than you think"
                -- The Eighth Networking Truth from RFC 1925

Andrea Laforgia <a.laf...@andrealaforgia.it.invalid> ha scritto:

Che problemi? Il fatto che le scritture finiscono sempre in fondo al
file? Beh, quella è la semantica del flag "a".
Luca
-- 
Home: 
http://kronoz.cjb.net
Il coraggio non mi manca.
E` la paura che mi frega...

file? Beh, quella è la semantica del flag "a".
Non mi sono spiegato.  Intendevo problemi derivanti dall'uso di
fseek() nell'andare a fine file, su qualsiasi piattaforma.  Se lo
standard precisa che questa operazione non è supportata su tutte le
piattaforme, una ragione tecnica c'è.  Qual è ?

 piattaforme, una ragione tecnica c'č.  Qual č ?
ISO/IEC 9899:1999 - p. 303
.......
225	Setting  the  file  position indicator to end-of-file, as
	with fseek(file, 0, SEEK_END), has undefined behavior for
	a  binary  stream  (because  of  possible  trailing  null
	characters)  or  for  any  stream  with   state-dependent
	encoding that does not assuredly end in the initial shift
	state.
.......
Quindi tutto filera' liscio col SEEK_END (Dos, Win, Unix, ...) finche' 
non vorrete portare il vostro programma su CP/M-80 :) o VAX/VMS (vi 
ricordate altri sistemi che usavano solo il car. EOF - eg. CTRL-Z - per 
segnare la fine del file?).
Ciao
-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

	state.
Cioč ?

 Cioč ?
Si parlava di modalita' di apertura binaria?
I car. multibyte sono utilizzati in questa modalita'?


I car. multibyte sono utilizzati in questa modalita'?
Che cosa c'entrano i caratteri multi-byte?

 Cioè ?
Serve per coprire qualche encoding multibyte strano. In un encoding
multibyte il significato di un particolare byte dipende da quelli
precedenti (prendi ad esempio UTF-8) e l'interpretazione di una stringa
puo' essere eseguita con una macchina a stati. In UTF-8 il significato
delle sequenze e' fisso, ma nulla vieta che anche le sequenze di byte
possano cambiare significato in base ai byte precedenti. Per
interpretare le sequenze hai quindi bisogno di un ulteriore macchina a
stati (che e' quella che ci interessa).
L'interpretazione inizia nello stato di default ("initial shift
state"[1]); i byte letti vengono interpretati secondo le regole di
questo stato. Il passaggio di stato avviene quando vengono trovate
sequenze apposite ("shit sequence"); ci si sposta in un altro stato e
l'interpretazione prosegue con regole differenti.
Ora, il problema con i file di *testo*, con encoding multibyte a stati
multipli e' che se ti posizioni alla fine del file ti trovi in uno stato
non noto. Anche se il posizionamento fosse possibile (nel senso che l'OS
vede un normale file, il seek si puo' fare), non sarebbe possibile
scrivere visto che per memorizzare la stringa voluta potrebbe essere
necessaria una shift sequence (ma non sarebbe corretto metterla
incondizionatamente) e questa sequenza potrebbe anche dipendere dallo
stato precedente.
Un esempio di encoding a stati il JIS per il giapponese. Di default i
caratteri sono interpretati come ASCII (initial shift state), ma c'e'
una particolare sequenza di 3 byte che sposta lo stato in modalita'
"giapponese" dove sequenze di 2 byte sono associate ai relativi kanji;
un'altra sequenza serve per tornare in modo ASCII.
Luca
[1] Requisito dell'initial shift state e' che tutti i caratteri del
basic set del C siano a byte singolo e che non ci siano ambiguita'.
UTF-8 rispetta questo requisito visto che c'e' un mapping identico con
ASCII per il basic set mentre le sequenze multibyte hanno il bit MS
sempre a 1. JIS soddisca il requisito perche' in modo standard e'
identico all'ASCII; nel modo giapponese compaiono byte che potrebbero
essere interpreati come ASCII, ma questo e' accettabile perche' sono
preceduti da un cambio di stato.
-- 
Home: 
http://kronoz.cjb.net
La mia opinione puo` essere cambiata, ma non il fatto che ho ragione.

 Cioè ?
Evidentemente non hai mai lavorato su VAX.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

Evidentemente non hai mai lavorato su VAX.
No, non ho mai lavorato su VAX.

non noto. 
Ok, ma qui si parla di stream binari, non di file di testo.  Si sta
quindi sorvolando sull'eventuale interpretazione di sequenze di byte.
O no ?

 Che cosa c'entrano i caratteri multi-byte?
Credo si riferisca alla gestione dei car. multibyte (a lunghezza 
variabile tipo UTF-8) con la stdio.h.
Prova "man wchar.h" su Linux.


Prova "man wchar.h" su Linux.
So cosa sono i caratteri multi-byte.  Chiedevo che cosa c'entrano, se
si sta parlando di stream binari.

 sempre ha senso.
...qui non ti seguo: troppo difficile per me :)
Ciao :)


 O no ?
No, per quello che ho evidenziato *testo* ;)
Dallo standard:
   *or for any stream* with state-dependent
si parla di stream binari _oppure_ di stream (potenzialmente di testo)
con encoding state-dependent.


 ...qui non ti seguo: troppo difficile per me :)
Uno "stream" può essere un file, un terminale, una stampante, una
memoria flash, etc. Ad alcuni di questi si può applicare il concetto di
"dimensione", ad altri no. Per mantenere la genericità lo standard non
può forzare questo concetto, dovrebbe dettare qualcosa del genere:
- alcuni stream (implementation defined) supportano il concetto di
  dimensione
- quando lo stream supporta la dimensione essa può essere letta con
  fgetsize()
- se lo stream ammette dimensione allora fseek(file, 0, SEEK_END)
  funziona
Che però è esattamente la situazione corrente: se l'implementazione
capisce il concetto di "dimensione" allora fseek funziona.
Luca
-- 
Home: 
http://kronoz.cjb.net
"L'amore consiste nell'essere cretini insieme." -- P. Valery

con encoding state-dependent.
Ah ok! sorry! ora ci siamo :-)
(Certo, se lo standard facesse qualche esempio riferendosi a casi
concreti non sarebbe però male...)

 capisce il concetto di "dimensione" allora fseek funziona.
Si', ma io rimanevo sul concetto di block device. Altrimenti puo' non 
aver senso nemmeno fare un fseek(..., posN, SEEK_SET).
Un character device, una pipe o comunque (ad esempio) uno dei tanti file 
speciali di Unix (eg. su /dev, /proc) sono tutti stream. Ma prima di 
fare una seek su questi ci penserei su... :)
Ciao


(il Vim e' un detersivo, mica un editor :) )
Shhh... non svegliarlo, non dirgli che hanno inventato degli editor
veri! :-) :-)

Andrea Laforgia ha scritto:

Aldila' della battuta... in verita' stimo chi riesce ad usare il Vi come 
editor principale. E' spesso insostituibile quando devi creare o 
modificare files sui server da terminale, ma credo siano veramente in 
pochi a riuscire ad usarlo per programmare in modo altamente produttivo.


editor principale. 
Personalmente ho imparato a non criticare chi usa un determinato
strumento, perché "de gustibus non disputandum est", ma personalmente
(e sottolineo _personalmente_) lo aborrisco come strumento di lavoro. 
Ho lavorato con svariati Unix (da AIX a HP-UX a Tru64 e i disparati
Linux) e per quanto apprezzi la solidità e l'efficienza di questi
sistemi operativi (entrambe qualità di gran lunga superiori a quelle
di quasliasi s.o. Microsoft, s'intenda) non mi è mai piaciuta la
filosofia Unix-like del "se è difficile ed enigmatico, è bello".
Ovvio, poi, che tutto diventa facile e splendente se si impara a
utilizzarlo...

 fare una seek su questi ci penserei su... :)
Stai facendo confusione: lo standard dice che _se_ il file supporta il
posizionamento allora puoi usare fseek (e fseek() può ritornare una
valore diverso da zero nel caso non possa soddisfare la richiesta). Come
ulteriore aggiunta, lo standard dice che, anche se lo stream supporta il
seeking, non è necessario che supporti fseek(..., SEEK_END) nei due
famosi casi (binario e encoding multibyte state-dependent).
Luca
-- 
Home: 
http://kronoz.cjb.net
Tentare e` il primo passo verso il fallimento.
Homer J. Simpson

 Stai facendo confusione
No :-)


 buon esito dell'operazione.
Ok, ma usiamo "filesystem" nell'accezione più ampia possibile, ovvero un
insieme qualsivoglia di metadati che descrivono il mio stream.
Il punto è:
- i metadati non ci sono: tutto ok, niente fseek (SEEK_END oppure anche
  del tutto)
- i metadati ci sono e:
  a) la libreria non li comprende
    i) se l'OS li maschera in modo trasparente fseek dovrebbe
    funzionare, SEEK_END potrebbe non operare in modo sensato (vedi
    CP/M)
    ii) i metadati sono gestiti dall'applicazione, la libreria potrebbe
    supportare il seeking ad offset noto ma non SEEK_END (/dev/hda)
  b) la libreria li comprende: tutto ok  
Spero di essermi spiegato ;)
Luca
-- 
Home: 
http://kronoz.cjb.net
Al termine di un pranzo di nozze mi hanno dato un
amaro alle erbe cosi' schifoso che perfino sull'etichetta
c'era un frate che vomitava.

     supportare il seeking ad offset noto ma non SEEK_END (/dev/hda)
il fatto che un fseek/SEEK_END non funzioni con il file /dev/hda 
probabilmente e' perche' torna un errore su eccezione di overflow 
(errno=75 - mi sembra - su Linux). Cioe' i normali HD in commercio sono 
ormai troppo grandi perche' la loro dimensione in byte possa entrare 
tutta in un 'signed long int' :(
Questo per precisare ancora un altro possibile caveat delle funzioni 
stdio su stream di grosse dimensioni, almeno su architetture a 32 bit.
