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