vedne på hovede

Tags:    programmering

Hvordan kan jeg i vb eller c++ vende en fil praktisktalt på hovede mest efffektiv!

f.esk

jeg har ne fil på fem byte

150
2
255
75
82

nu vil jeg vende filen så resultatet bliver

82
75
255
2
150


hvordan gør jeg det mest effektiv!

mvh.
Thomas Christensen



6 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 1 karma
Sorter efter stemmer Sorter efter dato
Her er et lille program der kan vende en fil. Bemærk:

1) Udvikleren.dk dræber sikkert alt hvad der hedder indrykning. Hvordan undgår man i øvrigt det?

rettet: brug pre-tags...

2) Linieskift, CRLF bliver også vendt, så det bliver til LFCR.

3) Blocksize er meget lille, så man nemmere kan steppe igennem programmet og se hvad der sker

4) Jeg har brugt GCC til at udvikle det med, ved ikke hvordan det opfører sig i MSVC++ eller lign.

5) Det er ikke testet ret meget, så der er ingen garanti for noget... :-)

here goes...:
<pre>
/* Lille program til at vende en fil
(C) 2002 by Jesper Andersen */

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

/*
a = array der skal vendes
s er antallet af bytes i array
*/
void swap(char a[], int s) {
char t=0;
int i;
for(i=0; i<(s/2); i++) {
t = a;
a = a[s-i-1];
a[s-i-1] = t;
}
}

int main() {
int blockSize = 2; /* Antal bytes der læses af gangen */
int fdI, fdO; /* FileDescriptors for Inout og Output filer */
int filePos = 0; /* Position, relativt til slutning af fil */
int fileSize = 0; /* Størrelse på fil der skal læses */
int iterator = 1; /* Tæller til at tælle blokke */
char buffer[blockSize]; /* buffer til læste data */
int readBytes; /* bytes read */

/* Åben input fil "infile" */
if ((fdI = open("infile", O_RDONLY)) < 0) {
perror("Open input file");
exit(1);
}

/* Åben output fil "outfile" */
if ((fdO = open("outfile", O_TRUNC|O_CREAT|O_WRONLY, 0644)) < 0) {
perror("Open output file");
exit(1);
}

/* Find størrelse på input fil */
if ((fileSize = lseek(fdI, 0, SEEK_END)) < 0) {
perror("Determine filesize");
exit(1);
}

filePos = fileSize;

/* Læs, swap og skriv løkke, indtil der er mindre end blocksize tilbage */
while(filePos >= blockSize) {
/* Sæt posistion til næste blok. */
if ((filePos = lseek(fdI, -((blockSize*iterator++)), SEEK_END)) < 0) {
perror("Set filepos");
exit(1);
}
printf("filePos is: %d\\n", filePos);

/* Læs blok */
if ((readBytes = read(fdI, buffer, blockSize)) < 0) {
perror("Read data");
exit(1);
}

/* Vend data i blok */
if (readBytes>1)
swap(buffer, readBytes);

/* Skriv data i blok */
if (write(fdO, buffer, readBytes) != readBytes) {
perror("Write data");
exit(1);
}
}

/* Check om der er data (< blockSize bytes) der mangler at blive læst */
if (filePos > 0) {
/* Sæt position til start af fil */
if ((lseek(fdI, 0, SEEK_SET)) < 0) {
perror("Set filepos (rest of file)");
exit(1);
}

/* Filepos indeholder posistion af sidst læste blok,
så vi læser til tegnet lige før dette */
if ((filePos = read(fdI, buffer, filePos)) < 0) {
perror("Read data (rest of file)");
exit(1);
}

swap(buffer, filePos-1);

/* Skriv data */
if (write(fdO, buffer, filePos) != filePos) {
perror("Write data (rest of file)");
exit(1);
}
}

close(fdI);
close(fdO);
return 0;
}
</pre>[Redigeret d. 25/07-02 00:58:04 af data][Redigeret d. 25/07-02 00:59:37 af data]




Hvordan kan jeg i vb eller c++ vende en fil praktisktalt på hovede mest efffektiv!

(...cut...)

hvordan gør jeg det mest effektiv!

mvh.
Thomas Christensen


Den naive løsning er at læse den sidste byte i input filen, skrive den ned i output filen, læse den næstsidste byte i input filen, skrive den ned i output filen etc.

Da det ikke er videre effektivt at læse en byte af gangen, er det bedre at læse en blok data. Læs de sidste n bytes i filen. vend dem, og skriv dem ned i output filen. Læs de næstsidste n bytes, vend og skriv etc. n skal sættes til en værdi der er et multiplum af den mængde data der kan læses i en read-operation fra det lagermedie dine data ligger på.

Tricket er så at vende bytes på den mest effektive måde. Dette kan fx. gøres ved:

a er et n-byte array der skal vendes.
t er en byte.
i er en iterator fra 0 til (n/2)-1

t=a
a=a[n-i]
a[n-i]=t

Det er umiddelbart det bedste jeg kan komme på, men klokken er også mange.

/data




Hvordan kan jeg i vb eller c++ vende en fil praktisktalt på hovede mest efffektiv!

(...cut...)

hvordan gør jeg det mest effektiv!

mvh.
Thomas Christensen

Den naive løsning er at læse den sidste byte i input filen, skrive den ned i output filen, læse den næstsidste byte i input filen, skrive den ned i output filen etc.

Da det ikke er videre effektivt at læse en byte af gangen, er det bedre at læse en blok data. Læs de sidste n bytes i filen. vend dem, og skriv dem ned i output filen. Læs de næstsidste n bytes, vend og skriv etc. n skal sættes til en værdi der er et multiplum af den mængde data der kan læses i en read-operation fra det lagermedie dine data ligger på.

Tricket er så at vende bytes på den mest effektive måde. Dette kan fx. gøres ved:

a er et n-byte array der skal vendes.
t er en byte.
i er en iterator fra 0 til (n/2)-1

t=a
a=a[n-i]
a[n-i]=t

Det er umiddelbart det bedste jeg kan komme på, men klokken er også mange.

/data


Okay?

det lyder jo meget godt?!

men hvodan læser jeg så en mængede bytes og hvis jeg 33 bytes hvordan får jeg så den sidste bytes med, hvis man antager den læser 3*10 bytes?

hvad ern en iterator?

der er en masse spørgsmål der står uklar for mig, så hvis du gider foklare metoden lidt nærmer!

På forhånd tak!

mvh.
Thomas Christensen







men hvodan læser jeg så en mængede bytes og hvis jeg 33 bytes hvordan får jeg så den sidste bytes med, hvis man antager den læser 3*10 bytes?


I det sprog du vælger at skrive dit program i, er der rutiner til at sætte hvilken position i en fil man vil læse fra, og en rutine til at læse data ind i f.eks. et array af bytes. Lidt udpenslet:

Sæt positionen i filen til filstørrelse-blokstørrelse, læs blokstørrelse bytes, vend dem og skriv til ny fil. Sæt filposition til filstørrelse-(2*blokstørrelse) og læs blokstørrelse bytes og vend og skriv. Fortsæt indtil der er færre end blokstørrelse bytes. Læs de sidste og vend dem og skriv.

Lad os tage en fil:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Vi sætter blokstørrelse til 4 bytes.

Først læser vi de sidste 4 bytes, altså 12 13 14 15. Dem vender vi og skriver til disk (15 14 13 12)

Så læser vi de næstsidste 4 bytes, altså 11 10 9 8. Vend og skriv (output er nu 15 14 13 12 11 10 9 8)

Læs og skriv de næste, så er output 15 14 13 12 11 10 9 8 7 6 5 4.

Der er nu 3 bytes tilbage. Det er mindre end vores blokstørrelse på 4, så vi nøjes med at læse 3 og skrive dem, så output nu er 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1.



hvad ern en iterator?


Et fisefornemt ord for en tæller, f.eks. en for-løkke eller en while-løkke.

/data



Tricket er så at vende bytes på den mest effektive måde. Dette kan fx. gøres ved:

a er et n-byte array der skal vendes.
t er en byte.
i er en iterator fra 0 til (n/2)-1

t=a
a=a[n-i]
a[n-i]=t

Det er umiddelbart det bedste jeg kan komme på, men klokken er også mange.

/data


Hmm......

Det lader til at når jeg skriver a(venstreklamme) i (højreklamme), altså indeks 'i' i arrayet a, så fjerner udvikleren det. Der skulle stå

t = a (venstreklamme) i (højreklamme)
a (venstreklamme) i (højreklamme) = a[n-i]
a[n-i]=t





Her er et lille program der kan vende en fil. Bemærk:

1) Udvikleren.dk dræber sikkert alt hvad der hedder indrykning. Hvordan undgår man i øvrigt det?

rettet: brug pre-tags...

2) Linieskift, CRLF bliver også vendt, så det bliver til LFCR.

3) Blocksize er meget lille, så man nemmere kan steppe igennem programmet og se hvad der sker

4) Jeg har brugt GCC til at udvikle det med, ved ikke hvordan det opfører sig i MSVC++ eller lign.

5) Det er ikke testet ret meget, så der er ingen garanti for noget... :-)

here goes...:
<pre>
/* Lille program til at vende en fil
(C) 2002 by Jesper Andersen */

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

/*
a = array der skal vendes
s er antallet af bytes i array
*/
void swap(char a[], int s) {
char t=0;
int i;
for(i=0; i<(s/2); i++) {
t = a;
a = a[s-i-1];
a[s-i-1] = t;
}
}

int main() {
int blockSize = 2; /* Antal bytes der læses af gangen */
int fdI, fdO; /* FileDescriptors for Inout og Output filer */
int filePos = 0; /* Position, relativt til slutning af fil */
int fileSize = 0; /* Størrelse på fil der skal læses */
int iterator = 1; /* Tæller til at tælle blokke */
char buffer[blockSize]; /* buffer til læste data */
int readBytes; /* bytes read */

/* Åben input fil "infile" */
if ((fdI = open("infile", O_RDONLY)) < 0) {
perror("Open input file");
exit(1);
}

/* Åben output fil "outfile" */
if ((fdO = open("outfile", O_TRUNC|O_CREAT|O_WRONLY, 0644)) < 0) {
perror("Open output file");
exit(1);
}

/* Find størrelse på input fil */
if ((fileSize = lseek(fdI, 0, SEEK_END)) < 0) {
perror("Determine filesize");
exit(1);
}

filePos = fileSize;

/* Læs, swap og skriv løkke, indtil der er mindre end blocksize tilbage */
while(filePos >= blockSize) {
/* Sæt posistion til næste blok. */
if ((filePos = lseek(fdI, -((blockSize*iterator++)), SEEK_END)) < 0) {
perror("Set filepos");
exit(1);
}
printf("filePos is: %d\\n", filePos);

/* Læs blok */
if ((readBytes = read(fdI, buffer, blockSize)) < 0) {
perror("Read data");
exit(1);
}

/* Vend data i blok */
if (readBytes>1)
swap(buffer, readBytes);

/* Skriv data i blok */
if (write(fdO, buffer, readBytes) != readBytes) {
perror("Write data");
exit(1);
}
}

/* Check om der er data (< blockSize bytes) der mangler at blive læst */
if (filePos > 0) {
/* Sæt position til start af fil */
if ((lseek(fdI, 0, SEEK_SET)) < 0) {
perror("Set filepos (rest of file)");
exit(1);
}

/* Filepos indeholder posistion af sidst læste blok,
så vi læser til tegnet lige før dette */
if ((filePos = read(fdI, buffer, filePos)) < 0) {
perror("Read data (rest of file)");
exit(1);
}

swap(buffer, filePos-1);

/* Skriv data */
if (write(fdO, buffer, filePos) != filePos) {
perror("Write data (rest of file)");
exit(1);
}
}

close(fdI);
close(fdO);
return 0;
}
</pre>[Redigeret d. 25/07-02 00:58:04 af data][Redigeret d. 25/07-02 00:59:37 af data]


Jeg har borland c++ og den kan ikke finde include filen unistd.h

og dne kommer også med andre fejl!

men det kan jo være fordi den ikke kan finde den fil!

-Thomas




t