Mam do wykonania zadanie:
Przygotuj program do ukrywania wiadomości w nieużywanych częściach struktur języka C, przy założeniu, że struktury nie są upakowane.
W tym celu przygotuj strukturę do przechowywania trzech wartości typu char, double i int w podanej kolejności. Struktura powinna wyglądać następująco:
struct message_t
{
char a;
double b;
int c;
};
Domyślnie kompilator języka C optymalizuje kod programu pod kątem szybkości dostępu do pól struktury, a nie pod kątem miejsca przez nią zajmowanego.
Oznacza to, że rozmiar poniższej struktury wynosi 24 bajty, przy czym dane zajmują tylko 13 bajtów. Różnica - 11 bajtów - jest niewykorzystana i można tam ukryć wiadomość.
Przygotuj funkcję do odczytywania wiadomości ukrytej na niewykorzystanych bajtach sekwencji struktur message_t oraz funkcję do wczytywania tablicy struktur message_t z pliku. Przygotowane funkcje powinny mieć następujące prototypy:
int load_data(struct message_t *cp, int size, const char *filename);
Funkcja ma za zadanie wczytać dane z pliku filename to tablicy struktur cp o pojemności size struktur message_t.
Parametry:
- filename - nazwa pliku, z którego mają zostać odczytane dane.
- cp - wskaźnik na tablicę struktur,
- size - rozmiar tablicy struktur.
Struktura pliku:
Struktura wczytywanego pliku wygląda następująco:
- liczba n bajtów danych od odczytania (pole unsigned int), następnie
- n bajtów, które mają tworzyć zawartość struktur message_t.
Wartość n=24 to jedna struktura message_t, 48 to dwie, itd. Wartość niebędąca wielokrotnością długości struktury jest niedopuszczalna.
Wartość zwracana:
- >0 - w przypadku powodzenia - liczba wczytanych struktur,
- -1 - w przypadku przekazania do funkcji błędnych danych,
- -2 - w przypadku niepowodzenia otworzenia pliku lub
- -3 - w przypadku, kiedy w pliku są uszkodzone dane.
W przypadku, kiedy w pliku znajdzie się więcej danych, niż można zmieścić w tablicy struktur, funkcja powinna wczytać tyle danych ile jest możliwe.
int decode_message(const struct message_t *cp, int size, char *msg, int text_size);
Parametry:
- cp - wskaźnik na tablicę struktur, w których ukryta jest wiadomość,
- size - rozmiar tablicy struktur,
- msg - wskaźnik na tablicę znaków, do której ma zostać zapisana wiadomość wydobyta z sekwencji struktur message_t,
- text_size - rozmiar tablicy znaków (pojemność w bajtach).
Wartość zwracana:
- 1 - w przypadku podanie błędnych danych wejściowych lub
- 0 - w przypadku poprawnego odczytania wiadomości.
Napisz program, który pobierze od użytkownika nazwę pliku (nie więcej niż 30 znaków), a następnie odczyta z niego struktury oraz odczyta ukrytą w nich wiadomość.
W przypadku, kiedy nie można otworzyć pliku program powinien wyświetlić komunikat Couldn't open file i zakończyć działanie z kodem błędu 4. W przypadku kiedy dane w pliku są zapisane niepoprawnie, program powinien wyświetlić komunikat File corrupted i zakończyć działanie z kodem błędu 6.
W przypadku poprawnego odczytania pliku, program powinien wyświetlić na konsoli treść odczytanej wiadomości bez żadnych dodatkowych znaków w wierszu.
Przykładowa interakcja z programem -- sukces:
Pliki: 2420test1.bin
Enter file name: 2420test2.bin⏎
I'm fascinated by the idea that genetics is digital. A gene is a long sequence of coded letters, like computer information. Modern biology is becoming very much a branch of information technology. - Richard Dawkins
Oto moje rozwiązanie:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
struct message_t
{
char a;
double b;
int c;
};
int load_data(struct message_t* cp, int size, const char* filename) {
if (filename==NULL||cp==NULL) {
return -1;
}
if (size<1) {
return -1;
}
unsigned char* ptr = (unsigned char*)cp + 0;
FILE* fp;
fp = fopen(filename, "rb");
if (fp == NULL) {
return -2;
}
fseek(fp, 0, SEEK_END);
int x=ftell(fp);
if (x == 0) {
fclose(fp);
return -3;
}
fseek(fp, 4, SEEK_SET);
int i = 0;
while (feof(fp) == 0&&i<=size) {
if (ferror(fp) != 0) {
return -3;
}
x = fread(ptr, 1, 1, fp);
if (x != 0 && x != 1) {
break;
}
if (x == 0) {
break;
}
ptr++;
x = fread(ptr, 1, 7, fp);
if (x != 0 && x != 7) {
return -3;
}
if (x == 0) {
return -3;
}
ptr += 7;
x = fread(ptr, 1, 8, fp);
if (x != 0 && x != 8) {
return -3;
}
if (x == 0) {
return -3;
}
ptr += 8;
x = fread(ptr, 1, 4, fp);
if (x != 0 && x != 4) {
return -3;
}
if (x == 0) {
return -3;
}
ptr += 4;
x = fread(ptr, 1, 4, fp);
if (x != 0 && x != 4) {
return -3;
}
if (x == 0) {
return -3;
}
ptr += 4;
i++;
cp++;
ptr = (unsigned char*)cp;
}
if (fclose(fp) == EOF) {
return -3;
}
return i;
}
int decode_message(const struct message_t* cp, int size, char* msg, int text_size) {
if (size <1||size>100 || msg == NULL || cp == NULL||text_size<1) {
return 1;
}
unsigned char* ptr = (unsigned char*)cp+0;
int i = 0, x=0;
while (isalpha(*ptr) == 0 && isdigit(*ptr) == 0) {
ptr++;
}
while (1) {
if (i == size) {
*msg = '\x0';
break;
}
i++;
ptr++;
if (x + 7 >= text_size-1) {
memmove(msg, ptr, text_size-1-x);
msg += text_size-1-x;
*msg = '\x0';
break;
}
memmove(msg, ptr, 7);
x += 7;
msg += 7;
ptr += 19;
if (x + 4 >= text_size) {
memmove(msg, ptr, text_size-x-1);
msg += text_size-1-x;
*msg = '\x0';
break;
}
memmove(msg, ptr, 4);
x += 4;
if (x >= text_size) {
*msg = '\x0';
break;
}
msg += 4;
ptr += 4;
if (*(ptr-1) == '\x0' || *ptr == '\x0') {
*msg = '\x0';
break;
}
}
return 0;
}
int main(){
struct message_t t[100];
puts("Enter file name:");
const char str[3000];
char tab[31], c;
int i = 0;
while (1) {
if (scanf("%c", &c) == 0) {
printf("Incorrect input");
return 1;
}
if (i > 29) {
}
else {
if (c == '\n') {
break;
}
*(tab + i) = c;
i++;
}
}
*(tab + i) = '\x0';
FILE* fp;
fp= fopen(tab, "r");
if (fp == NULL) {
printf("Couldn't open file");
return 4;
}
fclose(fp);
i = 0;
int y = load_data(t, 100, tab);
if (y == -3) {
printf("File corrupted");
return 6;
}
decode_message((const struct message_t*)t, 100, (char*)str, sizeof(str));
printf("%s", str);
return 0;
}
zrobiłem juz całe zadanie natomiast moja funkcja "load_data" powinna zwracać '-3', przy uszkodzonym pliku a tego nie robi domyślam się ze jest to związane z tą częscią polecenia której kompletnie nie rozumiem:
Struktura pliku:
Struktura wczytywanego pliku wygląda następująco:
- liczba n bajtów danych od odczytania (pole unsigned int), następnie
- n bajtów, które mają tworzyć zawartość struktur message_t.
Wartość n=24 to jedna struktura message_t, 48 to dwie, itd. Wartość niebędąca wielokrotnością długości struktury jest niedopuszczalna.
Szczególnie chodzi mi o 2 pierwsze podpunkty.