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

Bitmapa, czyli mapa bitowa (dosłownie)

Cloud VPS
0 głosów
1,077 wizyt
pytanie zadane 14 kwietnia 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)
edycja 14 kwietnia 2020 przez Hubertius

Cześć :)

Obecnie rozwiązuje zadanie o takiej treści:

Dana jest następująca tablica jednowymiarowa:

uint8_t bmp[] = {
        0xfc, 0x00, 0x00, 0x10, 0x30,
        0xb4, 0x00, 0x00, 0x30, 0x78,
        0x30, 0x78, 0x7c, 0x7c, 0x78,
        0x30, 0xcc, 0xc0, 0x30, 0x30,
        0x30, 0xfc, 0x78, 0x30, 0x30,
        0x30, 0xc0, 0x0c, 0x34, 0x00,
        0x78, 0x78, 0xf8, 0x18, 0x30,
        0x00, 0x00, 0x00, 0x00, 0x00
        };
Jest to obraz monochromatyczny (dwukolorowy), zapisany wiersz po wierszu. Liczba wierszy wynosi 8, liczba kolumn 40. Zakładając, że jeden piksel (punkt obrazu) zakodowany jest na jednym bicie, liczba bajtów w wierszu wynosi 5 (40 kolumn pogrupowanych po 8 bitów).

Napisz program, który pobierze od użytkownika obraz zapisany w taki sam sposób jak tablica bmp oraz nazwę pliku, do którego właściwy obraz ma zostać zapisany (nie więcej niż 50 znaków).

W przypadku wprowadzenia przez użytkownika błędnych znaków program powinien wyświetlić komunikat Incorrect input i zakończyć działanie z kodem błędu 1.

Wyświetl obraz w konsoli zakładając, że bit ustawiony to # a bit wyzerowany to ' ' (spacja). Pamiętaj o znaku nowej linii na końcu wyświetlanego wiersza. Wygenerowany obraz zapisz do pliku tekstowego w takiej formie, jak widzisz go na ekranie. O sukcesie zapisu nalezy poinformować użytkownika, wyświetlając komunikat File saved.

W przypadku kiedy nie uda się utworzyć pliku, program powinien w nowej linii wyświetlić komunikat Couldn't create file i zakończyć działanie z kodem błędu 5

Przykład interakcji z programem -- sukces

Enter values: fc 0 0 10 30 b4 0 0 30 78 30 78 7c 7c 78 30 cc c0 30 30 30 fc 78 30 30 30 c0 c 34 0 78 78 f8 18 30 0 0 0 0 0⏎
Podaj nazwe pliku: beat.txt⏎
######                     #      ##    ⏎
# ## #                    ##     ####   ⏎
  ##     ####    #####   #####   ####   ⏎
  ##    ##  ##  ##        ##      ##    ⏎
  ##    ######   ####     ##      ##    ⏎
  ##    ##          ##    ## #          ⏎
 ####    ####   #####      ##     ##    ⏎
                                        ⏎
File saved
Przykład interakcji z programem -- błąd tworzenia pliku

Enter values: ⏎
0 0 0 0 0 0 0 0 0 0 78 f8 78 cc cc cc cc cc fe cc fc cc fc fe cc c0 cc c0 d6 7c 78 cc 78 c6 c 0 0 0 0 f8⏎
Enter file name: ⏎
equate.txt⏎
                                        ⏎
                                        ⏎
 ####   #####    ####   ##  ##  ##  ##  ⏎
##  ##  ##  ##  ##  ##  ####### ##  ##  ⏎
######  ##  ##  ######  ####### ##  ##  ⏎
##      ##  ##  ##      ## # ##  #####  ⏎
 ####   ##  ##   ####   ##   ##     ##  ⏎
                                #####   ⏎
Couldn't create file⏎
Przykład interkacji z programem -- błąd danych wejściowych

podaj liczby: ⏎
57 f6 40 5b 69 95 67 2b 46 b1 fd aa 2c ac 1e c3 6e df 41 23 50 89 cc a7 ea bc 58 cd b4 62 45 61 ed 26 31 3a a7 67 ofBbM⏎
Incorrect input
Uwaga

Wszystkie operacje na tablicach powinny być wykonywane za pomocą wskaźników, a nie operatora []!
Używanie operatorów bitowych jest niedozwolone.
Wykorzystaj unię bit_set z zadania 5.3 Byte to bits.

Rozpisałem więc swój kod:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct my_bits
{
    unsigned char B0:1;
    unsigned char B1:1;
    unsigned char B2:1;
    unsigned char B3:1;
    unsigned char B4:1;
    unsigned char B5:1;
    unsigned char B6:1;
    unsigned char B7:1;

};
union bit_set
{
    struct my_bits bity[40];
    unsigned char tekst[40];
};

char znaczek(unsigned char z)
{
    if(z==1)
    {
        return '#';
    }
    else
    {
        return ' ';
    }
}

int main()
{
    printf("Enter values: ");
    union bit_set moje;
    union bit_set * pointer= &moje;
    int i =0;
    char table[328];
    int j = 0;
    for(i=0;i<40;i++)
    {
        if(scanf("%hhx",&(moje.tekst[i]) ) != 1)
        {
            printf("Incorrect input");
            return 1;
        }
        *(table + j)=znaczek(moje.bity[i].B7);
        *(table + j + 1)=znaczek(moje.bity[i].B6);
        *(table + j + 2)=znaczek(moje.bity[i].B5);
        *(table + j + 3)=znaczek(moje.bity[i].B4);
        *(table + j + 4)=znaczek(moje.bity[i].B3);
        *(table + j + 5)=znaczek(moje.bity[i].B2);
        *(table + j + 6)=znaczek(moje.bity[i].B1);
        *(table + j + 7)=znaczek(moje.bity[i].B0);
        if( (i + 1) % 5 == 0)
        {
            *(table + j + 8)='\n';
            j += 9;
        }
        else
        {
            j += 8;
        }
    }
    // Poniższy for to tylko sprawdzenie, czy to co jest wyżej działa.
    for(j = 0; j<328; j++)
    {
        printf("%c",*(table + j));
    }

    char tab[51]={0};
    char input[51]={0};
    char *tab_i=&(*(tab+0)), *input_i=&(*(input+0));
    printf("Podaj sciezke do pliku\n");
    scanf(" %51[^\n]", input_i);
    for(i=0; i<50; i++)
    {
        *(tab_i+i)=*(input_i+i);
    }
    FILE *f= fopen(tab_i,"wb");
    if(f==NULL)
    {
        printf("Couldn't create a file");
        fclose(f);
        return 5;
    }
    //fwrite(table, strlen(table) + 1, 1, f);
    j = 0;
    fwrite(table,sizeof(char),strlen(table),f);
    char bufor[328];
    fseek(f,0,SEEK_SET);
    fread(bufor,sizeof(char),strlen(table),f);
    printf("%s",bufor);
    fclose(f);
    return 0;
}

Na chwilę obecną mam problem z dwoma rzeczami. O ile na obecną chwilę poprawnie zapisuje to co ma zapisać w pliku, o tyle fread już chyba nie za bardzo. Bufor (tablica, w której zapisuje każdy odczytany znak z tablicy table) nie posiada tego co powinien odczytać fread. Gdzie popełniłem błąd?

A co drugiego. Jak poniższy zapis:

scanf("%hhx",&(moje.tekst[i]) )

mogę przekształcić na wersję wskaźnikową? Albo ot choćby ten:

moje.bity[i].B7

Chodzi mi o to, aby w ich zapisie nie pojawił się operator []

1
komentarz 14 kwietnia 2020 przez mokrowski Mędrzec (158,900 p.)
Na marginesie... zapytaj prowadzącego czy wie w jakiej kolejności ułożone są bity w polach bitowych? Po zadaniu widzę że raczej nie ma pojęcia o tym że ułożenie bitów jest zależne do architektury i rodzaju kompilatora.
komentarz 14 kwietnia 2020 przez Hubertius Bywalec (2,970 p.)

@mokrowski Wiesz, a zapytałbym... gdyby nie to, że praktycznie pomimo zajęć online jest to jedyny przedmiot, który na obecną chwilę polega na 100% pracy samodzielnej. Nawet kontaktu z prowadzącym zbytnio nie mamy. Jeżeli miałbym oddać stan tego jak wygląda nauka na kierunku informatycznym pewnej Politechniki to ten obrazek mówi wszystko:

komentarz 14 kwietnia 2020 przez mokrowski Mędrzec (158,900 p.)
No i nie mam pytań, ale chociaż wiesz jak jest (z tymi polami bitowymi)....

1 odpowiedź

+1 głos
odpowiedź 14 kwietnia 2020 przez j23 Mędrzec (195,240 p.)
wybrane 14 kwietnia 2020 przez Hubertius
 
Najlepsza

o tyle fread już chyba nie za bardzo.

Przecież otworzyłeś strumień tylko do zapisu.

fread(bufor,sizeof(char),strlen(table),f);

Nie strlen tylko sizeof.

komentarz 14 kwietnia 2020 przez Hubertius Bywalec (2,970 p.)
edycja 14 kwietnia 2020 przez Hubertius

A dziękuję, udało mi się na to wpaść z zastosowaniem "w+" akurat stosunkowo niedawno przed twoją odpowiedzią.
A co z tym zapisem wskaźnikowym? Jak mógłbym to rozpisać?

P.S Swoją drogą, dlaczego tam nie mógł być strlen?

https://pl.wikibooks.org/wiki/C/fwrite

Tutaj pisze, że w 3 argumencie musi być rozpisana liczba elementów, które chcemy przekazać do pliku. Dlaczego więc lepiej użyć sizeof-a, a nie strlen-a? 

Tak to wyglądało u mnie przed chwilą wcześniej:

fwrite(table,sizeof(char),strlen(table),f);
    char bufor[329];
    fseek(f,0,SEEK_SET);
    fread(bufor,sizeof(char),strlen(table),f);
    printf("%s",bufor);
    printf("File saved");
    fclose(f);
    return 0;

, a obecnie w ten sposób:

fwrite(table,sizeof(char),sizeof(table),f);
    char bufor[329];
    fseek(f,0,SEEK_SET);
    fread(bufor,sizeof(char),sizeof(table),f);
    printf("%s",bufor);
    printf("File saved");
    fclose(f);
    return 0;

Zauważyłem, że zdarzało się czasami, że w przypadku użycia strlen-a czasami zapisywało o jeden znak za dużo w pliku. W przypadku sizeof-a skuteczność jest teraz 100%. 

1
komentarz 14 kwietnia 2020 przez j23 Mędrzec (195,240 p.)

P.S Swoją drogą, dlaczego tam nie mógł być strlen?

Dlatego, że teoretycznie w table niczego nie ma, a fread musi wiedzieć, ile danych ma przeczytać, dlatego podajesz wielkość bufora, do którego chcesz czytać.

A co z tym zapisem wskaźnikowym? Jak mógłbym to rozpisać?

scanf("%hhx", moje.tekst + i);

(moje.bity + i)->B7

Podobne pytania

0 głosów
0 odpowiedzi 869 wizyt
pytanie zadane 30 kwietnia 2020 w C i C++ przez fortuna Początkujący (310 p.)
+1 głos
1 odpowiedź 140 wizyt
pytanie zadane 19 stycznia 2021 w C i C++ przez Modest_8978 Nowicjusz (130 p.)
0 głosów
0 odpowiedzi 1,223 wizyt
pytanie zadane 27 maja 2020 w C i C++ przez pozdro600 Początkujący (260 p.)

93,482 zapytań

142,415 odpowiedzi

322,761 komentarzy

62,895 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

Kursy INF.02 i INF.03
...