Zadanie z laboratorium programowania na Informatyce UW.
Zadanie 13 (termin wysylania rozwiazan: 7 maja 2008, godz. 23:59) (Kodowanie) Spacje i tabulacje znajdujace sie na koncu wiersza pliku tekstowego nie sa widoczne dla osoby czytajacej tekst. Mozna to wykorzystac do ukrywania w tekscie informacji. Np. jeden bajt mozemy zakodowac w tekscie, umieszczajac na koncu wiersza osiem znakow: spacje (oznaczajace bit 0) i tabulacje (oznaczajace bit 1). Przyjmiemy, ze bity beda uporzadkowane w kolejnosci od najbardziej znaczacego. Napisz program ktory, w zaleznosci od sposobu wywolania, ukryje w kolejnych wierszach tekstu po jednym bajcie pliku binarnego, lub odczyta je z tekstu. Program bedzie wywolywany z dwoma argumentami - litera 'c' lub 'd' oznaczajaca tryb pracy, oraz nazwa pliku binarnego. Program wywolany poleceniem: ./zsi07z13 c binaria wynik ma zakodowac zawartosc pliku binarnego o nazwie "binaria" w tekscie wczytanym z wejscia (tu jest nim zawartosc pliku o nazwie "tekst") i wypisac na wyjscie wynik kodowania (w tym wypadku wynik trafi do pliku o nazwie "wynik"). Niech liczba wierszy tekstu wejsciowego bedzie rowna K, a liczba bajtow pliku binarnego N. Jesli K jest wieksze lub rowne N, N poczatkowych wierszy tekstu wynikowego ma zawierac reprezentacje kolejnych bajtow, a pozostalych K-N wierszy nalezy skopiowac z wejscia na wyjscie bez zmian. Jesli K jest mniejsze niz N postepujemy tak, jakby na koncu tekstu wejsciowego bylo dodatkowo N-K wierszy pustych. Program wywolany poleceniem: ./zsi07z13 d binaria <tekst ma odkodowac dane ukryte w tekscie wczytanym z wejscia (tu jest nim zawartosc pliku "tekst") i zapisac je w pliku binarnym o nazwie "binaria". Zakladamy, ze tekst wejsciowy dla tego wywolania programu zawiera poprawnie zakodowana informacje. Oznacza to, ze N poczatkowych wierszy tego tekstu konczy sie osmioma znakami spacji i tabulacji. Jesli tekst wejsciowy ma wiecej niz N wierszy, na koncu wiersza o numerze N+1 nie ma osmiu znakow spacji i tabulacji. Program powinien utworzyc plik "binaria" i zapisac do niego N odczytanych bajtow. W zalacznikach do tresci sa pliki przykladowe: zsi07z13.binaria zsi07z13.tekst1 zsi07z13.tekst2 zsi07z13.wynik1 zsi07z13.wynik2 pasujace do ciagu wywolan programu: ./zsi07z13 c zsi07z13.binaria zsi07z13.wynik1 ./zsi07z13 d zsi07z13.binaria <zsi07z13.wynik1 ./zsi07z13 c zsi07z13.binaria zsi07z13.wynik2 ./zsi07z13 d zsi07z13.binaria <zsi07z13.wynik2
A oto rozwiązanie:
#include
#include
#include
//bufor - jeden bajt zapisany tym specyficznym sposobem.
char bufor[8];
int rozkoduj ()
{
//koduje ciag spacji i tabulacji na liczbe w kodzie U2 od najbardziej znaczacego bitu.
int i,wynik,mnoznik;
//dla ujemnego bitu:
if (bufor[0]=='t')
{
wynik=-128;
}
else
{
wynik=0;
}
mnoznik=64;
//7 razy:
for (i=1;i<8;i++)
{
if(bufor[i]=='t')
{
wynik=wynik+mnoznik;
}
mnoznik=mnoznik/2;
}
return wynik;
}
int zakoduj (int liczba)
{
//koduje liczbe znak na ciag spacji i tabulacji.
//Oczywiscie W ZADANIU NIE NAPISANO ZE KOD JEST UZUPELNIENIOWY DO 2!! MUSIELISMY SIE SAMI DOMYSLIC!!
int i,wynik,mnoznik;
//na poczatku dla ujemnego bitu:
if (liczba<0)
{
liczba=liczba+128;
bufor[0]='t';
}
else
{
bufor[0]=' ';
}
mnoznik=64;
wynik=0;
//7 razy:
for (i=1;i=mnoznik)
{
//ta liczba jest w rozkladzie.
bufor[i]='t';
liczba=liczba-mnoznik;
}
else
{
bufor[i]=' ';
}
mnoznik=mnoznik/2;
}
return 0;
}
int main (int argc,char *argv[])
{
FILE * f;
char znak,binarny;
int wynik, wynikb, bufor_index, i;
//Argumanry wywolania
if(argv[1][0]=='c')
{// czyli musimy zakodowac tekst
//printf("%s",argv[2]);
f=fopen(argv[2],"rb");
wynik=scanf("%c",&znak);
wynikb=fscanf(f,"%c",&binarny);
while(wynik!=EOF)
{
if(znak=='r')
{
//nic nie robimy. to zle znaki sa.
}
else if (znak=='n')
{
//kodujemy
//jesli jest co kodowac.
if(wynikb!=EOF)
{
//printf("[%d]",binarny);
zakoduj(binarny);
printf("%s",bufor);
wynikb=fscanf(f,"%c",&binarny);
}
//i koniec linii:
printf("n");
}
else
{
//przepisujemy znak.
printf("%c",znak);
}
wynik=scanf("%c",&znak);
} // ok. caly tekst zrodlowy przepisalismy
//Jesli jeszcze cos do zakodowania:
while(wynikb!=EOF)
{
zakoduj((int) binarny);
printf("%s",bufor);
//printf("[%d]",binarny);
wynikb=fscanf(f,"%c",&binarny);
//i koniec linii:
printf("n");
}
//zamykamy binaria
fclose(f);
}
else if(argv[1][0]=='d')
{//bedziemy dekodowac
f=fopen(argv[2],"wb");
wynik=scanf("%c",&znak);
while(wynik!=EOF)
{
if(znak=='r')
{
//nic nie robimy. to zle znaki sa.
}
else if((znak=='t')||(znak==' '))
{
//mamy jeden z tajemnych znakow. przepisujemy do bufora.
if (bufor_index<8)
{
bufor[bufor_index]=znak;
bufor_index++;
}
else if (bufor_index==8)
{
//dziwna sytuacja. Znaczy ze na koncu tekstu byly biale znaki i do tego zostalo cos dokodowane. musimy przesunac bufor,
for (i=0;i<7;i++)
{
bufor[i]=bufor[i+1];
}
bufor[7]=znak;
//bufor przesuniety,
}
}
else if (znak=='n')
{
//rozkodowujemy.
if(bufor_index==8) //rowniotko 8 bitow.
{
binarny=rozkoduj();
fprintf(f,"%c",binarny);
}
//printf("n");
}
else
{
//przepisujemy znak i zerujemy bufor.
bufor_index=0;
//printf("%c",znak);
}
wynik=scanf("%c",&znak);
}
fclose(f);
}
return 0;
}