• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Kopiowanie plików w C (z nieco innym podejściem do tematu)

42 Warsaw Coding Academy
0 głosów
1,453 wizyt
pytanie zadane 29 marca 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)
edycja 29 marca 2020 przez Hubertius

Cześć :)

Muszę rozwiązać zadanie o takiej treści:

Zmodyfikuj program z zadania 3.3 Co dwa pliki, to nie jeden tak, aby kopiowanie odbywało się od końca pliku -- ostatni znak pliku źródłowego powinien być pierwszym znakiem pliku docelowego.

**Przykład interakcji z programem -- sukces (dla pliku wejściowego text.txt, plik wyjściowy tuo.txt):

Podaj sciezke do pliku:⏎
text.txt⏎
Podaj sciezke do pliku wyjściowego:⏎
tuo.txt⏎
File copied⏎
Uwaga

W programie nie wolno używać funkcji alokujacych pamięć.
W programie można zadeklarować tylko tablice na 30 znaków (do przechowywania nazw plików). Deklaracja musi wyglądać następująco: nazwa_zmiennej[31];.
W programie nie wolno używać operatora [].
Plik wyjściowy musi mieć taką samą liczbę bajtów co plik wejściowy.

Poprzednie zadanie polegające na kopiowaniu zawartości od początku do końca udało mi się rozwiązać w następujący sposób:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char tab[31]={0};
    char input[31]={0};
    char *tab_i=&(*(tab+0)), *input_i=&(*(input+0));

    char tab2[31]={0};
    char input2[31]={0};
    char *tab_i2=&(*(tab2+0)), *input_i2=&(*(input2+0));

    int i;
    printf("Podaj sciezke do pliku\n");
    scanf(" %31[^\n]", input_i);
    for(i=0; i<30; i++)
    {
        *(tab_i+i)=*(input_i+i);
    }

    FILE *f= fopen(tab_i,"rb");
    if(f==NULL)
    {
        printf("Couldn't open file");
        return 4;
    }


    printf("Podaj sciezke do pliku wyjsciowego: \n");
    scanf(" %31[^\n]", input_i2);
    for(i=0; i<30; i++)
    {
        *(tab_i2+i)=*(input_i2+i);
    }

    FILE *f_2=fopen(tab_i2,"w+");
    if(f_2==NULL)
    {
        fclose(f);
        printf("Couldn't create file");
        return 5;
    }

    char znak;


    while(fread(&znak,1,1,f) != 0 )
    {
        fwrite(&znak,1,1,f_2);
    }

    fclose(f);
    fclose(f_2);
    printf("File copied");
    return 0;
}

Tak więc kopiowanie kończyło się w momencie, gdy fread napotykał na koniec pliku i wartość zwracana była mniejsza od count (czyli mniejsza od jeden, a tym samym de facto równa 0). Obecnie zastanawiam się jak mogę przeprowadzić ten sam proces tylko z kopiowaniem od końca, czuję, że dobrym rozwiązaniem byłoby posłużenie się funkcją fseek().

Tylko jeżeli tak to pojawia się pytanie. Czy to będzie dobra metoda? Jeśli tak to jak mogę ją rozwinąć ( fseek()-a ogarniałem dotychczas tylko w kwestii przesuwania kursora odczytu/zapisu danych na początek i koniec)? Z góry dziękuję za wszelkie odpowiedzi. 

komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)

O co chodzi z tab_i i input_i? Po co to?

1 odpowiedź

+1 głos
odpowiedź 30 marca 2020 przez j23 Mędrzec (195,240 p.)
wybrane 30 marca 2020 przez Hubertius
 
Najlepsza
Ja bym użył którąś z tablic, żeby nie fseekować co bajt. Czytać blokami od końca, kolejność bajtów w blokach odwracać i zapisywać do nowego pliku.
komentarz 30 marca 2020 przez Hubertius Bywalec (2,970 p.)
A jeżeli bym już używał fseek?

Na początku musiałbym zrobić fseek(f,0,SEEK_END). A potem? Jak zrobić, by przesuwać go co bajt aż do pierwszej pozycji? Oczywiście użyłbym do tego pętli while, ale jak mógłbym rozpisać do niej warunek?
komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)

Jak będziesz już miał SEEK_END, to wtedy funkcją ftell pobierz wielkość pliku i kręć pętlę tyle razy, ile jest w nim bajtów.

 

komentarz 30 marca 2020 przez Hubertius Bywalec (2,970 p.)

Czyli coś w tym rodzaju?

int result=ftell(f);
    //printf("\n%d\n",result);
    fseek(f,0,SEEK_END);
    result=ftell(f);
    while(result>=0)
    {
        char znak;
        fread(&znak,1,1,f);
        fwrite(&znak,1,1,f_2);
        fseek(f,-1,SEEK_CUR);
        result--;
    }

Ale widzę, że popełniłem błąd chyba przy zapisie fseek. Na obecną chwilę odnoszę wrażenie, że powinno przesuwać się o -1 od bieżącej pozycji. Ale tak się nie dzieje.

komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)
fseek(f, -1, SEEK_CUR);

while (result-- > 0) {
    char znak;
    fread(&znak, 1, 1, f);
    fwrite(&znak, 1, 1, f_2);
    fseek(f, -2, SEEK_CUR);
}

 

komentarz 30 marca 2020 przez Hubertius Bywalec (2,970 p.)

No dobra. Kod teraz działa u mnie poprawnie. Ale czemu dałeś:

fseek(f, -1, SEEK_CUR);

przed pętlą? I potem w samej pętli:

 fseek(f, -2, SEEK_CUR);

Czy nie powinno to przesuwać o 2 pozycje na lewo od bieżącej pozycji? Oczywiście widzę, że jednak przesuwa o jeden. Ale dlaczego tak się dzieje?

komentarz 30 marca 2020 przez j23 Mędrzec (195,240 p.)

Ale czemu dałeś:

przed pętlą?

bo wcześniej wskaźnik odczytu został przesunięty na koniec pliku, czyli za ostatnim bajtem.

Czy nie powinno to przesuwać o 2 pozycje na lewo od bieżącej pozycji?

Powinno.

Ale dlaczego tak się dzieje?

Dlatego, że fread przesuwa o jedną pozycję w prawo.

Podobne pytania

0 głosów
0 odpowiedzi 653 wizyt
pytanie zadane 26 marca 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)
0 głosów
1 odpowiedź 413 wizyt
pytanie zadane 16 kwietnia 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)
0 głosów
1 odpowiedź 848 wizyt

93,382 zapytań

142,382 odpowiedzi

322,539 komentarzy

62,740 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...