Hej :)
Rozwiązuje obecnie zadanie o takiej treści:
Napisz program do zapisu/odczytu liczby typu double poprzez tablice bajtów do pliku tekstowego.
Przygotuj unię do przechowywania liczby double oraz ośmiobajtowej tablicy znaków:
union double_to_char_t
{
double d;
char tab[8];
};
Napisz funkcje do: zapisywania liczby typu double na dysk po jednym znaku oraz do wczytywania danych z pliku i odtwarzania liczby double. Prototypy funkcji powinny wyglądać następująco:
int save_double(const union double_to_char_t *dtc, const char *filename);
Funkcja zapisuje zawartość unii dtc korzystając jedynie z pola tab. Operację zapisu należy zrealizować bajt po bajcie. Wielkość poprawnie zapisanego pliku to zawsze 8 bajtów.
Parametry:
filename - nazwa pliku, do którego ma zostać zapisana liczba,
dtc - wskaźnik na unię, której zawartość ma zostać zapisana do pliku,
Wartość zwracana:
0 - jeżeli zapis się powiódł,
1 - kiedy podane zostały błędne dane,
2 - w przypadku kiedy nie można otworzyć pliku filename,
3 - w przypadku kiedy nie uda się zapisać wszystkich danych do pliku filename.
int load_double(union double_to_char_t *dtc, const char *filename);
Funkcja wczytuje dane do unii dtc z pliku filename. Dane mogą być zapisywane pod wskaźnik dtc jedynie z wykorzystaniem tablicy tab.
Parametry:
filename - nazwa pliku, z którego ma zostać odczytana liczba,
dtc - wskaźnik na unię, do której mają zostać zapisane dane odczytane z pliku,
Wartość zwracana:
0 - jeżeli odczyt się powiódł,
1 - funkcję wywołano z błędnymi danymi,
2 - w przypadku kiedy nie można otworzyć pliku,
3 - w przypadku, kiedy plik jest uszkodzony.
Napisz program, który pobierze od użytkownika liczbę typu double i zapisze ją do unii, w przypadku wprowadzenia błędnych danych program powinien wyświetlić komunikat Incorrect input i zakończyć działanie z kodem błędu 1. Następnie program ma zapytać użytkownika o nazwę pliku (nie więcej niż 39 znaków) i zapisać do niego liczbę w trybie tekstowym.
W przypadku niepowodzenia program powinien wyświetlić komunikat Couldn’t create file i zakończyć się z kodem błędu 5. Jeżeli udało się zapisać liczbę do pliku to program powinien wyświetlić komunikat File saved i kontynuować pracę.
Następnie program powinien ponownie zapytać użytkownika o nazwę pliku (nie więcej niż 39 znaków) i wczytać z niego zawartość do unii.
Jeżeli operacja zakończy się sukcesem to program powinien wyświetlić na ekranie odczytaną liczbę. Jeżeli plik nie istnieje to program powinien wyświetlić komunikat Couldn’t open file i zakończyć się z kodem błedu 4 W przypadku uszkodzenia pliku wejściowego program ma wyświetlić File corrupted i zakończyć się z kodem błedu 6.
Przykład interakcji z programem -- sukces:
Podaj liczbę: 5860.514410⏎
Podaj nazwę pliku: pick.txt⏎
File saved⏎
Podaj nazwę pliku: die⏎
4820.069145
Pliki: pick.txt, die.
Przykład interakcji z programem -- błędy wejścia/wyjścia:
Podaj liczbę: -79.170020⏎
Podaj nazwę pliku: together⏎
Couldn't create file⏎
⏎
Podaj liczbę: 0.000000⏎
Podaj nazwę pliku: keptbin⏎
File saved⏎
Podaj nazwę pliku: strangebin⏎
Couldn't open file
Przykład interakcji z programem -- próba wczytania uszkodzonego pliku:
Podaj liczbę: 2759.583284⏎
Podaj nazwę pliku: heatbin⏎
File saved⏎
Podaj nazwę pliku: occurbin⏎
File corrupted
Przykład interakcji z programem -- błąd danych wejściowych:
Podaj liczbę: hhYmQwVhb⏎
Incorrect input
Uwaga
W programie nie wolno korzystać z operatora [], oprócz deklaracji tablicy.
Używanie operatorów bitowych jest niedozwolone.
Rozpisałem więc kod do zadania:
#include <stdio.h>
#include <stdlib.h>
union double_to_char_t
{
double d;
char tab[8];
};
int save_double(const union double_to_char_t *dtc, const char *filename);
int load_double(union double_to_char_t *dtc, const char *filename);
int main()
{
union double_to_char_t unia;
printf("Podaj liczbe: ");
if(scanf("%f",&(unia.d))!=1)
{
printf("Incorrect input");
return 1;
}
char tab[40]={0};
char input[40]={0};
char *tab_i=&(*(tab+0)), *input_i=&(*(input+0));
printf("Podaj sciezke do pliku\n");
scanf(" %39[^\n]", input_i);
int i;
for(i=0; i<39; i++)
{
*(tab_i+i)=*(input_i+i);
}
int wynik;
wynik = save_double(&unia,tab);
if( wynik > 0)
{
printf("Couldn’t create file");
return 5;
}
else
{
printf("File saved\n");
}
char tab2[40]={0};
char input2[40]={0};
char *tab_i2=&(*(tab2+0)), *input_i2=&(*(input2+0));
printf("Podaj sciezke do pliku: ");
scanf(" 39[^\n]",input_i2);
for(i=0; i<39; i++)
{
*(tab_i2+i)=*(input_i2+i);
}
wynik = load_double(&unia,tab2);
if(wynik>0 && wynik<3)
{
printf("Couldn’t open file");
return 4;
}
if(wynik == 3)
{
printf("File corrupted");
return 6;
}
printf("%f",unia.d);
return 0;
}
int save_double(const union double_to_char_t *dtc, const char *filename)
{
if(dtc == NULL || filename == NULL)
{
return 1;
}
FILE * f=fopen(filename,"w");
if(f == NULL)
{
return 2;
}
int i;
int result;
char znak;
for( i = 0; i < 8; i++)
{
znak = dtc -> tab + i;
result = fwrite( &znak ,sizeof(char),1,f);
if( result != 1)
{
fclose(f);
return 3;
}
}
fclose(f);
return 0;
}
int load_double(union double_to_char_t *dtc, const char *filename)
{
if( dtc == NULL || filename == NULL)
{
return 1;
}
FILE * f = fopen(filename,"r");
if( f == NULL )
{
return 2;
}
int i;
int result;
char znak;
for(i = 0; i < 8; i++)
{
result = fread(&znak,sizeof(char),1,f);
if( result != 1)
{
fclose(f);
return 3;
}
}
fclose(f);
return 0;
}
Generalnie na chwilę obecną brakuje mi wiedzy na temat jednej rzeczy w celu ukończenia zadania.
Jak za pomocą wskaźnika dtc mogę się odwołać do *(tab + i)? Na ten czas w funkcji save_double nie wiem, czy zapis odbywa się poprawnie ( nie jestem pewien, czy poniższa linijka kodu jest prawidłowa):
znak = dtc -> tab + i;
Ponadto jak mogę zastosować podobny zapis przypisując wartość zmiennej znak pod *(tab + i)? w funkcji load_double?
Gdybym musiał się odwoływać za pomocą unii w funkcji main to pewnie wykorzystałbym zapis w stylu:
unia.tab + i
, ale tutaj mam już działanie na wskaźniku do unii w osobnej funkcji.
P.S Teraz zauważyłem w trakcie sprawdzania poprawności programu, że choćbym przy drugim pliku wpisywał nazwę tego pierwszego to cały czas dostaje komunikat o niemożliwości otwarcia pliku. O co może chodzić?