Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Funkce a pointer na pole

Aktivity
Avatar
Daniel Bršťák:17.8.2021 9:01

Dobrý deň. Potreboval by som opraviť nefunkčný kód avšak tak aby bol môj kód zmenený len minimálne.Jedná sa o Bubblesort ako funkciu poľa. Mám 2 verzie. Jedna pracuje s 2 poľami : vezme dané pole čísel z jedného poľa a utriedené ho uloží do 2 poľa. Nepoužívajú sa pointery.
2.verzia p_bubblesort by mala pretransformovať neutriedené pole na utriedené tak že vezme adresy prvkov poľa...teda používa pointery. Táto druhá verzia mi nefunguje.Neviem prečo.

#include<stdio.h>
void print_array( int array[10] ) ;
void bubblesort( int array[10] , int array2[10] ) ;
void p_bubblesort( int *p_array[ 10 ] ) ;

int main()
{
int pole[10] ={ 7,1,9,15,6,4,­13,8,2,12 } ;
int pole2[10] ;

print_array(pole) ;
bubblesort( pole , pole2 );
print_array( pole2 ) ;
p_bubblesort( &pole) ;
print_array(pole) ;

}
// Vypis matice
void print_array( int array[10] ){
int i ;
for( i=0 ; i<10 ; i++ ){
printf("%d" , array[ i ] ) ;
printf(" ") ;
}
printf("\n") ;
}

// Bubblesort bez pouzitia pointerov
void bubblesort( int array[10] , int array2[10] )
{
int i , j ;
// aux = pomocna premenna
int aux ;

for( i=0 ; i<10 ; i++ )
array2[ i ] = array[ i ] ;

for( j=0 ; j<10 ; j++ ){
for( i=0 ; i<10 ; i++ ){
if( array2[ i ] > array2[ i+1 ] ){
aux=array2[ i ] ;
array2[ i ] = array2[ i+1] ;
array2[ i+1] = aux ;
}
}
}

}

// Bubblesort s poitermi
void p_bubblesort( int *p_array[10] )
{
int i , j ;
int aux ;

for( j=0 ; j<10 ; j++ ){
for( i=0 ; i<9 ; i++ ){
if( *p_array[ i ] > *p_array[ i+1 ] ){
aux=*p_array[ i ] ;
*p_array[ i ] = *p_array[ i+1] ;
*p_array[ i+1] = aux ;
}
}
}

}

Zkusil jsem: Skúšal som nájsť odpoveď v knihách avšak sa neriešia takéto úlohy.

Chci docílit: Pochopenie pointerov na pole vo funkciách aby som mohol programovať matematické funkcie lineárnej algebry .

 
Odpovědět
17.8.2021 9:01
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:17.8.2021 13:46

Hlavní chyba je způsob předávání pole funkci. Pro číselná pole funkce neumí zjistit uvnitř funkce počet prvků pole, je tedy tuto informaci předat jako druhý parametr. Velikost pole uvnitř hranatých závorek je ignorována. Takže správný prototyp funkce může vypadat např. takto:

int func(int arr[], int size);
// nebo
int func(int *arr, int size);
Nahoru Odpovědět
17.8.2021 13:46
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Petan
Člen
Avatar
Petan:17.8.2021 15:55

Ja bych to udelal takto

#define POCET  10

// Bubblesort s poitermi
void p_bubblesort( int* p_array )
{
        int i , j ;
        int aux ;

        for( j=0 ; j< POCET; j++ )
        {
                for( i=0 ; i<POCET - 1 ; i++ )
                {
                        if( p_array[ i ] > p_array[ j ] )
                        {
                                aux = p_array[ j ] ;
                                p_array[ j ] = p_array[ i ] ;
                                p_array[ i ] = aux ;
                        }
                }
        }

}


//a volani
p_bubblesort( pole) ;

protoze pole je vlastne pointer na int (10*int)

 
Nahoru Odpovědět
17.8.2021 15:55
Avatar
Petan
Člen
Avatar
Petan:17.8.2021 16:01

tato cast *p_array[ i ] = bude hodnota nachazejici se na nektere z adres { 7,1,9,15,6,4,­13,8,2,12 } coz by melo skoncit nejakou runtime chybou v adresaci promenne

 
Nahoru Odpovědět
17.8.2021 16:01
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Petan
DarkCoder:17.8.2021 21:08

Takovéto řešení není šťastné a to z jednoho prostého důvodu. Pracuje se se symbolickou konstantou přímo uvnitř těla funkce. Funkce tak není pružná a z hlediska funkčnosti je omezená. Je třeba tvořit takové funkce, které poskytnou využití pro širokou škálu případů bez ztráty efektivity. Jak bychom pak například třídili jen část pole, popř. pole jiné velikosti? Redefinovat symbolickou konstantou by asi nebylo úplně elegantní řešení. Proto je dobré při předávání ukazatele na pole předávat i jeho velikost ve druhém parametrů funkce.

Nahoru Odpovědět
17.8.2021 21:08
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Petan
Člen
Avatar
Odpovídá na DarkCoder
Petan:18.8.2021 6:53

Souhlasím, ale toto byl priklad kdy mel tyto hodnoty primo dane ve funkci.

 
Nahoru Odpovědět
18.8.2021 6:53
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Petan
DarkCoder:18.8.2021 8:38

To ano, ale to ještě neznamená, že je to správně. Tyto hodnoty by měli být závislé na tom co přichází z věnčí. A velikost pole popř. úsek, který se má třídit, může být proměnlivý. Tedy je potřeba, aby i vnitřek funkce se měnil.

Nahoru Odpovědět
18.8.2021 8:38
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Petan
Člen
Avatar
Petan:18.8.2021 9:28

Ano i ne!. To je pouze uhel pohledu. V tomto programu pracuje z konstantou 10, a funkce p_bubblesort je delana pouze k setrizeni techto 10 hodnot. Pokud by to byla obecna funkce tak ano.

 
Nahoru Odpovědět
18.8.2021 9:28
Avatar
Petan
Člen
Avatar
Petan:18.8.2021 9:40

Ale ted mne napada
funkce void p_bubblesort( int p_array[10] )
Mne to ms vis c++ prekladac odmitne ale co vrati v teto funkci `sizeof(p_array) / sizeof(int
)` 10 nebo 1 ?

 
Nahoru Odpovědět
18.8.2021 9:40
Avatar
Petan
Člen
Avatar
Petan:18.8.2021 9:41

Nejak mi tam vypustil * teda sizeof(p_array) / sizeof(int*) ?

 
Nahoru Odpovědět
18.8.2021 9:41
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Petan
DarkCoder:18.8.2021 10:31

Třídící algoritmus BubbleSort je obecný algoritmus a je holý nesmysl ho implementovat pro konkrétní hodnotu. Dost často bývá součástí vlastních knihoven, což je další důvod, proč se používá se samostatným parametrem udávající velikost pole.

Jak už jsem psal v příspěvku výše

void p_bubblesort( int p_array[10] )

Překladač nezná velikost pole (hodnota 10 v hranatých závorkách je překladačem ignorována) a funkce tak není obecná, jelikož se spoléhá na něco zvenčí (na nějakou globální proměnnou, statickou proměnnou, či symbolickou konstantu). Takovýto postup je z programátorského hlediska nesprávný..

Nahoru Odpovědět
18.8.2021 10:31
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Petan
Člen
Avatar
Petan:18.8.2021 11:26

OK takze parametr v zavorkach je zbytecny..
V TOMTO prikladu JA povazuji parametr velikost ve funkci za zbytecny.
V obecne funkci samozrejme ANO
K obecnemu trideni je v c funkce qsort ktera je asi i rychlejsi...

 
Nahoru Odpovědět
18.8.2021 11:26
Avatar
Daniel Bršťák:19.8.2021 10:05

Dobrý deň, priatelia. Ďakujem za vaše rady, ale asi došlo k nedorozumeniu. Moja otázka sa vzťahovala iba na zápis funkcie s pointermi. Bubblesort bol iba príklad funkcie ktorá pracuje s poliami....pre mňa je irelevantné či je funkcia pružná, či nepracuje pre konkrétny rozsah poľa N....chcem len vedieť ako zapísať funkciu, ktorá vezme nie pole, ale adresy prvkov poľa pole1 , spracuje ich a výsledok uloží do iného poľa pole2 pričom vráti pointery na toto pole2....

Poprosím na príklade súčtu dvoch vektorov v 3d priestore.Zdôraz­ňujem že je to úloha edukačného charakteru .

Verzia bez pointerov :

void sucet_vektorov( int vec1[3] , int vec2[3] , int vec3[3] )
{
for(int i=0 ; i<3 ; i++ )
vec3[i] = vec1[i]+vec[2] ;
}

Volanie funkcie v main:
int main()
{
int vektor1[3] = {4,6,8} ;
int vektor1[3] = {7,9,1} ;
int vektor3[3] ;

sucet_vektorov( vektor1,vektor2,vektor3 ) ;

//Vypis vektora:
for(int i=0 ; i<3 ; i++ )
printf("%d," , vektor3[ i ] ) ;
}
/code]
Toto je verzia, ktorá pracuje s prvkami poľa. Potrebume vedieť ako vyzerá verzia, ktorá vezme iba adresy vektorov, sčíta ich pomocou pointerov a ulozi vysledok. Dôležité je aj volanie funkcie z main.
 
Nahoru Odpovědět
19.8.2021 10:05
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:19.8.2021 11:09

Jak takovou funkci napsat jsem psal již v úvodním příspěvku. Tedy ještě jednou. Funkce nepřijímá pole jako celek, ale vždy pouze ukazatel na začátek pole. Existují tři zápisy:

void func1(int arr[]);
void func1(int arr[10]);
void func1(int *arr);

Všechny tyto zápisy jsou identické a všechny přebírají ukazatel na začátek pole. Používá se buď první způsob a zejména třetí způsob. V ani jednom zápisu však nefiguruje velikost pole a je tedy dobré tuto informaci předávat jako druhý parametr.

void func1(int arr[], int size);
void func1(int arr[10], int size);
void func1(int *arr, int size);

Toto neplatí, respektivě není třeba, pro znaková pole tvořící řetězec (nikoli znaky samotné). Ta jsou ukončena nulovým znakem.

Je zbytečné brát adresy jednotlivých prvků pole, když znám adresu pole. Adresy jednotlivých prvků pole lze pak získat pomocí ukazatelové aritmetiky. To se děje pak až uvnitř funkce..

Jak by vypadal příklad s vektory je zde:

#include <stdio.h>

#define SIZE 3

int* sum_vec(int* arr1, int* arr2, int* arr3, int dim);
void print_vec(int* arr, int dim);

int main(void) {
        int v1[SIZE] = { 4,6,8 };
        int v2[SIZE] = { 7,9,1 };
        int v3[SIZE];
        int* pvec = NULL;

        pvec = sum_vec(v1, v2, v3, SIZE);
        print_vec(pvec, SIZE);

        return 0;
}

int* sum_vec(int* arr1, int* arr2, int* arr3, int dim) {
        for (int i = 0; i < dim; i++) *(arr3 + i) = *(arr1 + i) + *(arr2 + i);
        return arr3;
}

void print_vec(int* arr, int dim) {
        for (int i = 0; i < dim; i++) printf("%d ", *(arr + i));
}

Funkce sum_vec() přebírá tři ukazatele na jednotlivá pole (tedy ukazatele na vektory) a velikost vektoru. Vrací ukazatel na výsledné pole (vektor). Funkce print_vec() přebírá ukazatel na pole a opět přebírá velikost tohoto pole. Dále byl deklarován ukazatel, který bude použit pro pole výsledku součtu vektorů. Je mu tedy přiřazena návratová hodnota funkce sum_vec(). Nakonec je výsledek zobrazen na obrazovku pomocí funkce print_vec() která přebírá ukazatel na pole a velikost tohoto pole. Pro ověření funkčnosti vrácené hodnoty funkce sum_vec() byl použit ukazatel pvec namísto ukazatele v3.

Nahoru Odpovědět
19.8.2021 11:09
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Daniel Bršťák:20.8.2021 8:36

Priznávam že Vašim kódom nerozumiem. Zrejme preto, lebo zápis je úplne odlišný od toho ktorý je v učebniciach. Kód už funguje ale neviem prečo. Hlavne nerozumiem , ako je možné že do funkcie sum_vec ste zadal priamo pole a nie pointery naňho. Vo vašom kóde mi chýba adresný operátor &. Niekde by mala byť formula typu: niečo = &arr1[0] ; alebo niečo = arr1 ;
Tiež nerozumiem zápisu return arr3....veď arr3 je celé pole, nie 1 premenná ....mne nikdy program nechce vratit cele pole, vždy len jednu premennú.

 
Nahoru Odpovědět
20.8.2021 8:36
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:20.8.2021 14:32

Hlavne nerozumiem , ako je možné že do funkcie sum_vec ste zadal priamo pole a nie pointery naňho.

Pole se nikdy funkci nepředává, vždy se funkci předává ukazatel na pole.. Pokud se bude předávat adresa jednoho prvku pole, pak se ve volání funkce vyskytne referenční operátor &. Je samozřejmě možné aby ukazatel na pole a adresa jednoho (prvního) prvku byla stejná. Pokud tedy budu mít prototyp funkce:

void func(int *arr);

pak máme-li např. pole v1[10], tak adresa předávaná funkci u následujících volání funkcí je stejná

func(v1); // bazová adresa pole v1
func(&v1[0]); // adresa prvního prvku pole v1

Pokud se ale předává ukazatel na začátek pole, používá se výhradně první varianta. V profi psaných programech se druhá varianta nepoužívá. Lze ji ovšem využít pro přístup k adrese daného prvku pole.

Podívej se na následující dva programy, jeden bez funkcí, druhý s funkcemi. První varianta by Ti měla býti jasná. Tam najdeš to na co si se ptal. Druhá varianta Ti nejspíš jasná nebude, neboť se ve funkci kde se předává pole ukazatelů vyskytuje vícenásobná dereference. Nicméně jako představa Ti to poslouží více než dobře..

Bez funkce

#include <stdio.h>

#define SIZE 3

int main(void) {
        int v1[SIZE] = { 4,6,8 };
        int* v2[SIZE];

        for (int i = 0; i < SIZE; i++) v2[i] = &v1[i];
        for (int i = 0; i < SIZE; i++) printf("%d ", *v2[i]);

        return 0;
}

S Funkcí

#include <stdio.h>

#define SIZE 3

void get_adr(int* adr, int **arr, int pos);

int main(void) {
        int v1[SIZE] = { 4,6,8 };
        int* v2[SIZE];

        for (int i = 0; i < SIZE; i++) get_adr(&v1[i], v2, i);
        for (int i = 0; i < SIZE; i++) printf("%d ", *v2[i]);

        return 0;
}

void get_adr(int* adr, int** arr, int pos) {
        arr[pos] = adr;
}

Tiež nerozumiem zápisu return arr3....veď arr3 je celé pole, nie 1 premenná

arr3 je ukazatel na začátek pole deklarovaný jako formální parametr funkce. Opět, nevrací se celé pole, ale pouze ukazatel na pole.

Nakonec zmíním, že je důležité vědět čeho chci dosáhnout. Podle toho stavím kód programu. Pokud tedy vím že pracuji s prvky celého pole (traversuji), tak použiji ukazatel na začátek pole. Používá se mnohem častěji než práce s jednotlivými prvky pole.

Doporučuji si nejprve osvojit práci s běžnou proměnnou u funkce - volání hodnotou, odkazem, vrácení hodnoty a vrácení adresy přes návratový typ a přes argument funkce, atd.. a pak se pustit do práce s polem.. vědět vztah mezi indexací pole a ukazatelovou aritmetikou, vědět co představuje jméno pole bez indexu, umět předat ukazatel na pole, jeden prvek z pole, atd..

Nahoru Odpovědět
20.8.2021 14:32
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Daniel Bršťák:31.8.2021 13:00

Dobrý deň. Pokúšal som sa podľa Vášho návodu zkonštruovať analogický program pre súčet 2-rozmerného poľa ale nefunguje mi. Dokážete nájsť chybu ? Môj program je len 2d analóg vášho a nefunguje.

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define N 3

int *sucet_matic(int *arr1 ,int *arr2, int *arr3, int dim );
void print_matrix( int *matrix , int size) ;

int main()
{
   int matrix1[N][N]={
   { 4,6,8 },
   { 4,6,8 },
   { 4,6,8 }} ;
   int matrix2[N][N] = {
   { 7,9,1 },
   { 7,9,1 },
   { 7,9,1 } } ;
   int matrix3[N][N] ;
   int *pvec = NULL;
   pvec=sucet_matic(matrix1 , matrix2,matrix3 , N ) ;
   print_matrix(pvec , N ) ;
   return 0;
}
int *sucet_matic(int *arr1, int *arr2, int
*arr3 , int dim)
{
   int i , j ;
   for( j =0 ; j < dim; j++ ){
      for( i =0 ; i < dim; i++ ){
         *(*(arr3 + i)+j) ==
           *(*(arr1 + i )+j ) + *(*(arr2 + i)+j ) ;
      }
   }
   return arr3;
}

void print_matrix( int *matrix, int size)
{
   int i ,j ;
   for( j=0 ; j< size ; j++ ){
      for( i = 0 ; i < size ; i++ ){
         printf("%d", *(*(matrix + i)+j) ) ;
         printf('\t') ;
      }
      printf("\n") ;
   }
}
 
Nahoru Odpovědět
31.8.2021 13:00
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:31.8.2021 14:56

Hlavní chybou je způsob předávání 2D pole funkci. Je třeba přesně specifikovat typ ukazatele. Budeme-li chtít napsat např. prototyp funkce print_matrix(), bude vypadat následovně:

void print_matrix(int mat[][N], int size);
// nebo
void print_matrix(int (*mat)[N], int size);

A to za předpokladu, že je definováno N.

Celý kód pak bude vypadat například takto:

#include <stdio.h>

#define N 3

void sucet_matic(int mat1[][N], int mat2[][N], int mat3[][N], int size);
void print_matrix(int mat[][N], int size);

int main(void){
        int matrix1[N][N] = {
                4,6,8,
                4,6,8,
                4,6,8
        };

        int matrix2[N][N] = {
                7,9,1,
                7,9,1,
                7,9,1
        };

        int matrix3[N][N];

        sucet_matic(matrix1, matrix2, matrix3, N);
        print_matrix(matrix3, N);

        return 0;
}

void sucet_matic(int mat1[][N], int mat2[][N], int mat3[][N], int size) {
        for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                        *(*(mat3 + i) + j) = *(*(mat1 + i) + j) + *(*(mat2 + i) + j);
                }
        }
}

void print_matrix(int mat[][N], int size){
        for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                        printf("%d ", *(*(mat + i) + j));
                }
                putchar('\n');
        }
}

Není třeba přikládat matematickou knihovnu math.h ani knihovnu stdlib.h.

Další chyby ve tvém programu jsou, že ve funkci sucet_matic() používáš pro přiřazení znak operátor rovnosti == namísto operátoru přiřazení =. A funkce printf() pro výpis tabulátoru vyžaduje dvojité uvozovky pro ohraničení formátovacího řetězce, nikoli apostrofy. Ty se používají u funkce putchar() pro výpis jednoho znaku, tedy i escape sekvence.

Nahoru Odpovědět
31.8.2021 14:56
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Daniel Bršťák:31.8.2021 16:56

Pán DarkCoder:
Vždy keď Vám napíšem fragment kódu, tak ho modifikujete tak že sa stratí pointa otázky.Konkrétne:
Prečo ste moju funkciu sucet_matic prepísali bez pointerov ? Moja pôvodná funkcia bola:

int *sucet_matic(int *arr1 ,int *arr2,int *arr3 , int dim ) ;

Vaša modifikovaná funkcia:

void sucet_matic(int mat1[][N],int mat2[][N],int mat3[][N], int size ) ;

Pritom ja som svoju funkciu definoval na základe Vašej funkcie súčtu vektorov, kde jediná zmena bola že sčítavam 2-rozmerné pole:

int* sum_vec(int* arr1, int* arr2, int* arr3 , int dim ) ;

Tú funciu som definoval na základe analógie s Vašou funkciou práve preto aby ste nemuseli nič meniť-a Vy ste funkciu zase od základu zmenil.
Aký má zmysel prepis pola arr na mat ? Prestalo platiť že matica je dvojrozmerné pole ?
'A to za předpokladu, že je definováno N' - veď som ho definoval jasne :
#define N 3
Neviem či je problém komunikačná bariéra medzi češtinou a slovenčinou, alebo sme naladení na inej vlne , ale Vaše odpovede mi pochopenie skôr stažujú než uľahčujú . Na toto treba ísť inak: predpokladám že sa vyznáte aj v literatúre. V ktorej učebnici sú pointery vysvetlené najzrozumiteľnejšie pre začiatočníka ? Pokúšam sa učiť z knihy Ritchie, Kerninghan : Programovací jazyk C , ale aj tá kniha je nevhodná. Je to referenčná príručka , nie učebnica.

 
Nahoru Odpovědět
31.8.2021 16:56
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:31.8.2021 18:30

Pointa otázky byla zodpovězena hned v první větě. Opakuji, že to co bylo špatně byl způsob předávání 2D pole funkci. Ostatní modifikuji dle sebe, neboť by to mělo naopak pomoci k pochopení činnosti celého programu. Arr jako formální parametr používám pro 1D pole, mat pro 2D pole. Samozřejmě si každý může zvolit libovolné platné jméno. Dále znovu opakuji, že se nepředává pole funkci ale vždy ukazatel na pole. Dále je obrovský rozdíl předat ukazatel na pole nebo ukazatel na N-prvkové pole. To je hlavní odlišnost v zápisu hlavičky funkce.

Funkci

int *sucet_matic(int *arr1 ,int *arr2,int *arr3 , int dim ) ;

nelze použít pro 2D pole! Pro 2D pole je třeba, aby funkce vypadala následovně:

void sucet_matic(int (*mat1)[N], iint (*mat2)[N], iint (*mat3)[N], int size);
// nebo
void sucet_matic(int mat1[][N], int mat2[][N], int mat3[][N], int size);

tedy formální parametr je ukazatel na N-prvkové pole typu int. V obou případech se předává ukazatel.
Návratovou hodnotu jsem vypustil, jelikož ukazatel na cílové 2D pole je již součástí argumentu funkce.

Shrnutí:

1D pole předané funkci:

void func(int arr[], int size);
// nebo
void func(int *arr, int size);

2D pole předané funkci

void func(int mat[][N], int size);
// nebo
void func(int (*mat)[N], int size);

Definování N je důležité. V opačném případě by došlo k chybě během překladu, proto to bylo zdůrazněno.

Co se týká knih, pár jsem jich přečetl. Kniha Ritchie, Kerninghan - Programovací jazyk C, je opravdu obecný základ.

Knih o ukazatelích je obrovské množství: Herb Schildt - Teach Yourself C, Herb Schildt - Complete References C, Stephen Prata - C Primer Plus, Reya Nadeya - Programming in C, Dewan Hrishikesh - Pointers in C, Reese Richard - Understanding and Using C Pointers, Robert J. Traister - Mastering C Pointers: Tools for Programming Power a mnoho dalších..

Dost možná pro české čtenáře něco o ukazatelích napíšu i já... nicméně to teď není na pořadu dne..

Obecně ale, čím více knížek pročteš, tím více Ti to dá. Z každé si něco odneseš. Něco Ti bude jasnější z jedné, něco z druhé..

Nahoru Odpovědět
31.8.2021 18:30
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:1.9.2021 14:56

Způsobů, jak předat 2D pole jako argument funkci, je samozřejmě mnohem více a záleží na situaci. Zde jsou některé z nich

Pokud jsou známy rozměry a jsou definovány jako makro:

void print_matrix(int mat[M][N]) {
        for (int i = 0; i < M; i++) {
                for (int j = 0; j < N; j++) {
                        printf("%d ", *(*(mat + i) + j));
                }
                putchar('\n');
        }
}

// volaní funkce
print_matrix(matrix);

Pokud jsou známy oba rozměry a jen druhý je definován jako makro:

void print_matrix(int mat[][N], int rows) {
        for (int i = 0; i < rows; i++) {
                for (int j = 0; j < N; j++) {
                        printf("%d ", *(*(mat + i) + j));
                }
                putchar('\n');
        }
}

// volaní funkce
print_matrix(matrix, M);

Pokud jsou známy oba rozměry a jen druhý je definován jako makro (koncept ukazatele na pole):

void print_matrix(int (*mat)[N], int rows) {
        for (int i = 0; i < rows; i++) {
                for (int j = 0; j < N; j++) {
                        printf("%d ", *(*(mat + i) + j));
                }
                putchar('\n');
        }
}

// volaní funkce
print_matrix(matrix, M);

Pokud jsou známy oba rozměry ale nedefinované jako makro (koncept prostého ukazatele):

void print_matrix(int* mat, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                        printf("%d ", *(mat + i * cols + j));
                }
                putchar('\n');
        }
}

// volaní funkce
print_matrix((int *)matrix, M, N); // je nutné přetypování na ukazatel

Pokud je 2D pole vytvořeno dynamicky

void print_matrix(int** mat, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                        printf("%d ", *(*(mat + i) + j));
                }
                putchar('\n');
        }
}

// volaní funkce
print_matrix(matrix, m, n);

Takže stačí si jen vybrat vhodný způsob dle situace..

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
1.9.2021 14:56
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Daniel Bršťák:2.9.2021 9:10

Ďakujem. Kód konečne funguje tak ako má. Presne takáto kategorizácia rôznych zápisov je to čo mi v knihách chýba.

 
Nahoru Odpovědět
2.9.2021 9:10
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Daniel Bršťák
DarkCoder:2.9.2021 10:31

Tak to je fajn, že vše funguje tak jak má. Ano, to je také důvod proč chci napsat knihu i přesto, že na trhu už jich je bezpočet. Žádná totiž nemá takovouto strukturu, která vše čtenáři podává jasnou a srozumitelnou formou bez vší té omáčky kolem..

Nahoru Odpovědět
2.9.2021 10:31
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 23 zpráv z 23.