Wstęp do Programowania, laboratorium 08 Zadanie 1. Zrobić

Transkrypt

Wstęp do Programowania, laboratorium 08 Zadanie 1. Zrobić
Wstęp do Programowania, laboratorium 08
Zadanie 1. Zrobić program szyfrujący pliki tekstowe. Ścieżki do pliki do zaszyfrowania
odczytywane są z listy argumentów programu, np.:
./szyfrator.exe plik1.txt /home/mietek/wiadomosc.rtf
Zadanie 2. Zrobić program odszyfrowujący pliki tekstowe
./deszyfrator.exe plik1-szyfr.txt
Zadanie 3. Połączyć powyższe programy w jeden. Domyślnie pliki będą szyfrowane. Umieszczenie
argumentu „-d” przed ścieżką do pliku oznaczać będzie, że ma być on odszyfrowany.
./szyfrator.exe plik1.txt -d plik1_zaszyfrowany.txt
Instrukcja
Argumenty programu:
#include <stdio.h>
#include <string.h>
// Pierwszy argument funkcji main – liczba argumentów programu
// Drugi argument – tablica łańcuchów tekstowych – argumentów
// Nazwy dowolne, przeważnie używane są argc i argv
int main(int argc, char *argv[])
{
int i;
for(i=0; i<argc; ++i)
{
printf("Argument %d: %s\n", i, argv[i]);
// strcmp – porównanie dwóch tekstów
// zwraca '0' jeśli są równe
if(strcmp(argv[i], "bla")==0)
printf("Argument %d to 'bla'\n", i);
}
return 0;
}
Uruchomienie: ./a.out tekst "dlugi tekst ze spacja" bla 32
Argumentem o indeksie 0 jest zawsze nazwa uruchomionego programu (nazwa pliku).
http://pl.wikibooks.org/wiki/C/strcmp
Otwarcie pliku:
#include <stdio.h>
int main(int argc, char *argv[])
{
// Sprawdz czy podana została ścieżka do pliku
if(argc<2)
{
printf("Podaj sciezke do pliku\n");
return 1;
}
// Zmienna przechowująca informacje o otwartym pliku
FILE *plik;
// Otworz plik do odczytu
plik=fopen(argv[1], "r");
// 'plik' jest równy 0 jeśli nie udało się otworzyć pliku
if(!plik)
{
printf("Plik %s nie istnieje\n", argv[1]);
return 2;
}
printf("Plik %s istnieje\n", argv[1]);
// Zamknij otwarty plik (ważne!)
fclose(plik);
return 0;
}
Funkcja fopen służy do otwarcia pliku. Pierwszym argumentem jest ścieżka do niego, drugi
informuje o tym, co z plikiem chcemy zrobić:
• "r" oznacza, że plik otwarty będzie do odczytu (read),
• "w" – zapis do pliku (write), plik zostanie nadpisany,
• "a" – dopisywanie (append).
Dodanie "b" po literce (np. "rb", "wb") oznacza, że plik traktowany będzie jako binarny (domyślnie
jest uznawany za tekstowy). Wszystkie funkcje do zapisu i odczytu do/z pliku działają na plikach
binarnych i tekstowych. Plik z tekstem może być otwarty w trybie binarnym. Otwarcie pliku w
trybie tekstowym może spowodować konwersje pewnych znaków (np. znaków końca linii).
Przeważnie otwarcie pliku w trybie binarnym jest bezpieczniejsze (stwierdzenie potwierdzone
doświadczeniem autora).
http://pl.wikibooks.org/wiki/C/Czytanie_i_pisanie_do_plik%C3%B3w
http://www.cplusplus.com/reference/cstdio/fopen/
Odczyt i zapis do pliku:
•
•
printf([format], [zmienne]) – wypisuje sformatowany tekst na ekran
fprintf([plik], [format], [zmienne]) – wypisuje sformatowany tekst do podanego pliku
•
•
scanf([format], [zmienne]) – wczytanie tekstu z konsoli i wpisane do zmiennej
fscanf([plik], [format], [zmienne]) – wczytanie tekstu z pliku i wpisanie do zmiennej
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
int i;
int tab[20];
// Otworz plik do odczytu
fp=fopen("plik.txt", "r");
// Wczytaj 20 liczb calkowitych z pliku
for(i=0; i<20; ++i)
fscanf(fp, "%d", &tab[i]);
// Zamknij plik
fclose(fp);
// Otworz plik do zapisu (binarnie)
fp=fopen("wyjscie.txt", "wb");
// Wpisz 20 liczb do pliku
for(i=0; i<20; ++i)
fprintf(fp, "%d ", tab[i]+1);
// Zamknij plik
fclose(fp);
return 0;
}
Odczyt i zapis binarny z pliku:
#include <stdio.h>
// Program kopiujący plik bajt po bajcie
int main(int argc, char *argv[])
{
FILE *in;
FILE *out;
if(argc<3)
{
printf("Uzycie: %s [plik do skopiowania] [sciezka]\n");
return 1;
}
in=fopen(argv[1], "rb");
out=fopen(argv[2], "wb");
while(1)
{
char c;
c=fgetc(in);
if(feof(in))
break;
putc(c, out);
printf("Przekopiowano %d bajtow\n", ftell(in));
}
fclose(in);
fclose(out);
return 0;
}
feof([plik]) – zwraca zero jeśli nie doszliśmy do końca pliku.
ftell([plik]) – zwraca pozycję w pliku (gdyby plik traktować jako tablicę, powie na którym indeksie
aktualnie jesteśmy).
http://www.cplusplus.com/reference/cstdio/ftell/
http://www.cplusplus.com/reference/cstdio/feof/
#include <stdio.h>
// Program zwracający wielkość podanych plików
int main(int argc, char *argv[])
{
FILE *fp;
int i;
int wielkosc;
for(i=0; i<argc; ++i)
{
fp=fopen(argv[i], "rb");
// Przeskocz na koniec pliku...
fseek(fp, 0, SEEK_END);
// Sprawdź w którym miejscu on jest...
wielkosc=ftell(fp);
// i wróć na początek, o ile chcesz odczytywać plik.
fseek(fp, 0, SEEK_SET);
printf("Plik %s zajmuje %d bajtow\n", argv[i], wielkosc);
fclose(fp);
}
return 0;
}
fseek([plik], [przesunięcie], [względem czego]) – przeskakuje na podane miejsce w pliku.
http://www.cplusplus.com/reference/cstdio/fseek/
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
int i;
int tab[20];
for(i=0; i<20; ++i) tab[i]=i;
// Otworz plik do odczytu (binarnie)
fp=fopen("plik.bin", "rb");
for(i=0; i<20; ++i)
// Wczytaj 1 element wielkości typu int
fread(&tab[i], sizeof(int), 1, fp);
// Zamiast używać pętli...
//fread(tab, sizeof(int), 20, fp);
// Zamknij plik
fclose(fp);
// Otworz plik do zapisu (binarnie)
fp=fopen("plik.bin", "wb");
// Wpisz 20 liczb do pliku
for(i=0; i<20; ++i)
{
++tab[i];
fwrite(&tab[i], sizeof(int), 1, fp);
}
// lub...
//fwrite(&tab[i], sizeof(int), 20, fp);
// Zamknij plik
fclose(fp);
return 0;
}
fread([adres zmiennej], [wielkość elementu w bajtach], [liczba elementów], [plik]) – wczytuje
podaną liczbę elementów o podanej wielkości pod podany adres.
sizeof([typ]) – zwraca ile bajtów zajmuje podany typ (sizeof(int) → 4, sizeof(char) → 1)
http://www.cplusplus.com/reference/cstdio/fread/
http://www.cplusplus.com/reference/cstdio/fwrite/
Podpowiedzi
Zrobić program szyfrujący pliki tekstowe. Ścieżki do pliki do zaszyfrowania odczytywane są z listy
argumentów programu, np.:
Ad. 1
1. Zrobić funkcję szyfrującą plik. Jako argument przyjmować może ścieżkę do pliku.
2. Otworzyć plik odczytywany i plik do zapisu.
3. Nazwę pliku do zapisu można utworzyć przy pomocy funkcji sprintf (patrz niżej)
4. Wczytać znak z pliku szyfrowanego, zaszyfrować, wpisać do pliku wyjściowego.
5. Wykonywać aż do końca pliku odczytywanego.
6. Zrobić pętlę od 1 do argc (nie chcemy szyfrować pliku programu), wywołać funkcję
szyfrującą dla każdego z argumentów.
void szyfruj(char sciezka[])
{
// Wstawić kod
}
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
char tablica[100];
for(i=1; i<argc; ++i)
{
sprintf(tablica, "tekst_%d_%s", i, argv[i]);
printf("%s\n", tablica);
// printf(tablica); // tez jest dozwolone
}
return 0;
}
http://www.cplusplus.com/reference/cstdio/sprintf/
printf – wypisanie na ekran
fprintf – wypisanie do pliku
sprintf – wypisanie do tablicy
Ad. 2 Zrobić tak samo jak program pierwszy, zamiast szyfrowania zrobić odszyfrowanie.
Ad. 3 Zrobić program zawierający funkcje szyfrującą i odszyfrowującą. Zrobić pętlę od 1 do argc,
po napotkaniu argumentu „-d” wywołać funkcję odszyfrowującą dla następnego argumentu, w
przeciwnym razie wywołać funkcję szyfrującą.
for(i=1; i<argc; ++i)
{
if(strcmp(argv[i], "-d")==0)
odszyfruj(argv[++i]);
// Zwrócić uwagę na ++i
else
szyfruj(argv[i]);
}