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; }