matematykaszkolna.pl
zad johnsop: tworzenie tablice dynamiczna stanowiaca odzwierciedlenie macierzy wewnatrz zmiennej strukturalnej
11 gru 10:39
11 gru 12:45
aa: Po zapoznaniu się z poleceniem "typedef" należy zdefiniować nazwę MACIERZ dla struktury MACIERZS. Deklaracje (oraz definicje struktury i nazwy MACIERZ) należy umieścić w pliku nagłówkowym "macierz.h", definicje funkcji w osobnych plikach (każda w osobnym) o nazwie takiej jak nazwa funkcji+rozszerzenie .c), a następnie napisać programy testujące poprawność opracowanych definicji i nazwać je zgodnie z numeracja zadań: ZAD.15. W oparciu o zdefiniowana strukturę MACIERZ napisać definicje oraz brakujące deklaracje następujących funkcji: kilka przykładowych deklaracji funkcji przedstawiono poniżej: mcreate − tworzy tablice dynamiczna stanowiącą odzwierciedlenie macierzy wewnątrz zmiennej strukturalnej mremove − usuwa zawartość macierzy ( i odpowiednio ustawia wskaźniki) mget − pozwala na odczytanie wartości znajdujących się w określonym miejscu(współrzędne) określonej macierzy mput − pozwala wstawić określona wartość w określone miejsce danej macierzy mprintf − graficznie wyświetla strukturę macierzy z wartościami mscanf − pozwala wypełnić istniejącą(cala) macierz wartościami pobranymi bezpośrednio od użytkownika.
11 gru 12:51
Pytający: I z czym konkretnie masz problem? Nie licz, że ktoś to po prostu zrobi za Ciebie.
11 gru 17:22
aa: https://pastebin.com/B5DHK6DK Tak z nudów, nie wszystko ale coś jest, dawno nie pisałem w C więc będą babole: #include <stdio.h> #include <stdlib.h> #include <limits.h> #define M_ERROR ULONG_MAX; typedef struct MACIERZS { size_t x, y; // wymiary macierzy size_t **m; // macierz jako wskaźnik na wskaźnik } MACIERZ; // typedef robi tak, że można używać nazwy "struct MACIERZS" lub "MACIERZ" void mcreate(MACIERZ *cm, int cx, int cy) { if (cx<=0 || cy<=0) { // jeżeli cx lub cy nie spelnia zakresu to cm = NULL cm = NULL; } else { cm−>x = cx; // ustalanie rozmiarów cm−>y = cy; cm−>m = (size_t **)malloc(cx*sizeof(size_t*)); // malloc alokuje cx pamięci po size_t* bajtów size_t x; for (x=0; x<cx; x++) { // pętla po cm−>m[x] cm−>m[x] = (size_t *)malloc(cy * sizeof(size_t)); // malloc alokuje cy pamięci po size_t bajtów size_t y; for (y=0; y<cy; y++) { cm−>m[x][y] = 0; // zerowanie cm−>m } } } } void mremove(MACIERZ *rm) { size_t x; for (x = 0; x<rm−>x; x++) { size_t y; for (y=0; y<rm−>y; y++) { rm−>m[x][y] = 0; } } } size_t mget(MACIERZ *gm, size_t gx, size_t gy) { if ((gx<gm−>x && gy<gm−>y) && (gx>gm−>x && gy>gm−>y)) { // jeżeli poza zakresem to error return M_ERROR; } else { return gm−>m[gx][gy]; // inaczej zwracamy wartość } } int mput(MACIERZ *pm, int px, int py, size_t pw) { if ((px<pm−>x && py<pm−>y) || (px>pm−>x && py>pm−>y)) { // jeżeli poza zakresem to error return 1; } else { pm−>m[px][py] = pw; return 0; } } void mprintf(MACIERZ *pm) { size_t x; for (x=0; x< pm−>x; x++) { printf("|"); size_t y; for (y=0; y<pm−>y; y++) { printf("%4u", pm−>m[x][y]); } printf(" |\n"); } } void mscanf(MACIERZ *sm) { printf("Podaj wartości macierzy dzieląc je spacją.\nNp. 1 2 3 4 dla macierzy \n|1 2|\n|3 4|\n"); size_t x; for (x=0; x<sm−>x; x++) { size_t y; for (y=0; y<sm−>y; y++) { scanf("%d", &sm−>m[x][y]); } } } int main() { MACIERZ mm; mcreate(&mm, 3, 3); mscanf(&mm); mprintf(&mm); printf("M[%d][%d]: %d\n", 3, 2, mget(&mm, 3, 2)); return 0; }
12 gru 00:41
Pytający: size_t jak sama nazwa wskazuje jest raczej przeznaczony do reprezentowania rozmiaru, nie jakichś danych. Znaczy typ danych w macierzy zdefiniowałbym osobno, coś w tym stylu: typedef int data_t; // int zamień na pożądany typ typedef struct MACIERZS { size_t x, y; // wymiary macierzy data_t **m; // macierz jako wskaźnik na wskaźnik } MACIERZ; Oczywiście w pozostałych funkcjach trzeba by tę zmianę uwzględnić. W mcreate() przypisanie cm = NULL niczego sensownego nie robi, cm to tylko lokalny wskaźnik. Równie dobrze można od razu napisać return. Można też bawić się w sprawdzanie wartości zwracanych przez malloc() (czy faktycznie udało się alokować pamięć). Zerowanie danych też raczej nie jest konieczne (polecenie sugeruje jedynie alokację pamięci). W mremove() zerujesz macierz, zamiast ją usunąć (zwolnić pamięć przy użyciu free() (bo alokujesz poprzez malloc()) i ustawić wskaźniki na NULL). W mput() i mget() niepoprawnie sprawdzany jest zakres. W mget() niby zwracasz size_t (ewentualnie po zmianie, o której wyżej wspomniałem data_t), a jako kod błędu zwracasz ULONG_MAX... skąd pewność, że ULONG_MAX zmieści się w size_t? Zresztą jeśli by się zmieściło, pewnie byłaby to dopuszczalna wartość elementu, a tym samym nie wiadomo by było, czy taka jest wartość elementu, czy chodzi o błąd. Znaczy jak chcesz sprawdzać zakres i jakoś informować o błędzie, to lepiej już rozdzielić zwracaną wartość elementu macierzy od kodu błędu, np. poprzez zwrócenie jednej wartości poprzez argument wskaźnikowy. I też dawno nie pisałem w C.
12 gru 17:02