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

Ukryta wiadomość w strukturze.

0 głosów
1,316 wizyt
pytanie zadane 27 maja 2020 w C i C++ przez pozdro600 Początkujący (260 p.)

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.

komentarz 27 maja 2020 przez j23 Mędrzec (195,240 p.)
edycja 27 maja 2020 przez j23
    fseek(fp, 0, SEEK_END);
    int x=ftell(fp);
    if (x == 0) {
        fclose(fp);
        return -3;
    }
    fseek(fp, 4, SEEK_SET);
    int i = 0;

Po co te zabiegi? W opisie masz napisane, że pierwsze 4 bajty to ilość zawartych w pliku danych wyrażona w bajtach.

Tak to widzę:

int load_data(struct message_t* cp, int size, const char* filename)
{
    if (filename == NULL || cp == NULL || size < 1) {
        return -1;
    }

    FILE* fp = fopen(filename, "rb");
    if (fp == NULL) {
        return -2;
    }

    unsigned int n;

    if (fread(&n, sizeof(unsigned int), 1) != 1) {
        fclose(fp);
        return -3;
    }

    n /= sizeof(message_t);

    if (n > size) n = size;
    else size = n;

    while (n-- > 0 && fread(cp++, sizeof(message_t), 1, fp) == 1) {}

    if (feof() != 0 || ferror(fp) != 0) {

        fclose(fp);
        return -3;
    }

    fclose(fp);
    return size;
}

 

komentarz 27 maja 2020 przez pozdro600 Początkujący (260 p.)
Uratowałeś mnie, wielkie dzięki! :)

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
0 odpowiedzi 846 wizyt
pytanie zadane 30 kwietnia 2020 w C i C++ przez fortuna Początkujący (310 p.)
0 głosów
1 odpowiedź 1,125 wizyt

93,423 zapytań

142,419 odpowiedzi

322,637 komentarzy

62,782 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
...