Προς το περιεχόμενο

Δυναμικά Οριζόμενοι Πίνακες σε C


Lomar

Προτεινόμενες αναρτήσεις

Χαίρομαι όταν μαθαίνω:

 

"... It's not necessary (given that coercion of void * to ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a proxy for it, fails to be declared as returning void *. ..."

 

Μπράβο dop, με έπεισες (και) σε αυτό...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 64
  • Δημ.
  • Τελ. απάντηση
On the other hand, pre-ANSI, the cast was necessary, and it is in C++ also

 

Εμένα πάλι με προβληματίζει αυτό. Δλδ αν θες να γράψεις κώδικα που να είναι reusable σε C++, θα πρέπει να κάνεις casting?

Τελικά, τί να κάνει κανείς? Πού βαδίζουμε? Γιατί δε μου "πέφτει" το Τζόκερ? Γιατί...?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@chiossif: αυτό κάνω για να ζήσω ;)

 

@parifal: άμα θέλεις να κάνεις C κώδικα να κάνει compile σε C++ compiler τότε πρέπει να κάνεις casting. Φυσικά, αυτό είναι τελείως άχρηστο: αν θέλεις να γράφεις C, τότε να την κάνεις compile με C compiler, ειδάλλως γράψε C++.

 

Αν από την άλλη απλώς θέλεις να βάλεις κάποιο κομμάτι C μέσα στο C++ πρόγραμμά σου, τότε η extern "C" {} είναι αυτό που σου χρειάζεται.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για την παλιά σχολή είναι τουλάχιστον θρησκευτικό ζήτημα το casting στην malloc (θα το βρεις σε παλαιά βιβλία) από την άλλη πλευρά τα πρότυπα εξελίσσονται οπότε ο dop έχει δίκιο.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 εβδομάδες αργότερα...

Για να επαναφέρω λιγάκι το θέμα...Το βρήκα απο search το θέμα αλλα μόνο γι΄αυτο δεν κατάλαβα διαβάζοντας εδώ...

 

 

Λοιπον, θέλω να κατασκεύαζω έναν δυσδιάστατο που οι διαστάσεις του κάθε φορα θα ειναι μεταβλητές(m,n που θα διαβάζονται απο ένα txt αρχείο).

 

 

Αυτο προφανώς γίνεται με malloc.Για έναν μονοδιάστατο πίνακα κατάλαβα πως γίνεται(ουσιαστιικά μόνο με έμμεση διευθυνδιοδότηση (*) γίνεται χρήση-προσπέλαση-δουλεια με τον πίνακα)Για τον δυσδιάστατο όμως πως θα το κάνω;θα πρέπει να κάνω κάποια ειδική δήλωση στην malloc ή να χρησιμοποιηθεί κάποια ειδική σημειογραφία με τους δείκτες;

 

Τhanks εκ των προτέρων!!!

 

:)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπορείς με το εξής:

 

>
typedef int data_t;
size_t m, n, i;
data_t **array;

array = malloc(m*sizeof *array);
if (array==NULL)
 /* error handling */
for (i=0; i<m; i++)
{
 array[i] = malloc(n*sizeof **array);
 if (array[i]==NULL)
 {
   size_t j;
   for (j=0; j<i; j++)
     free(array[j]);
   free(array);
   /* error message and exit? */
 }
}

 

Όσο αυξάνονται οι διαστάσεις, τόσο θα αυξάνονται και τα loops που θα φτιάχνουν τον πίνακα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Thanks dop...

 

 

Πες οτι θέλω να προσπελάσω ένα μέλος του δυσδιάστατου πίνακα:Aυτο θα γίνεται με σημειολογία δεικτών;(Προφανώς)Δηλαδή για το πρώτο πρώτο στοιχείο του πίνακα αρκεί να γράφω **array[0][0];Εδωπέρα οι δείκτες θα είναι όταν βάζουμε μονο αστεράκι;

 

Η C εσωτερικά σαν μονοδυάστατο τον χειρίζεται;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

...κώδικα σε παλαιότερο μύνημα στο ίδιο θέμα:

 

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

int main (void) {
   int n, i, j;
   double i1, **a, **b, *c;

/* Get array dimension */
   do{
       printf ("\nEnter matrix dimension N>0 : ");
       scanf ("%d",&n);
   }while(n<1);

/* Allocate memory to a as a double array NxN */
   if ((a=(double **)malloc(n*sizeof(double *)))==NULL){
       printf("\nNot enough memory avaliable.\n");
       exit(1);
   }

   for(i=0;i<n;i++){
       if ((a[i]=(double *)malloc(n*sizeof(double)))==NULL){
           printf("\nNot enough memory avaliable.\n");
           exit(1);
       }
   }

/* Fills a with data */
   for (i=0;i<n;i++){
       i1=(double)i+1;
       a[i][i]=i1/i1;
       for (j=0;j<i;j++)
           a[j][i]=a[i][j]=i1/(j+1);
   }

/* Displays a's data */
   printf("\nA array:\n");
   for (i=0;i<n;i++){
       for (j=0;j<n;j++)
           printf(" %7.3lf", a[i][j]);
       printf("\n");
   }

/* Allocate memory to b as a double array NxN */
   if ((b=(double **)malloc(n*sizeof(double *)))==NULL){
       printf("\nNot enough memory avaliable.\n");
       exit(1);
   }

   for(i=0;i<n;i++){
       if ((b[i]=(double *)malloc(n*sizeof(double)))==NULL){
           printf("\nNot enough memory avaliable.\n");
           exit(1);
       }
   }

/* Copies a to b */
   memcpy(b,a,n*n*sizeof(double));

/* Displays b's data */
   printf("\nB array:\n");
   for (i=0;i<n;i++){
       for (j=0;j<n;j++)
           printf(" %7.3lf", a[i][j]);
       printf("\n");
   }

/* Allocate memory to c as a double vector N */
   if ((c=(double *)malloc(n*sizeof(double)))==NULL){
       printf("\nNot enough memory avaliable.\n");
       exit(1);
   }

/* Copy and display a rows to c */
   for(i=0;i<n;i++){
       memcpy(c,a[i],n*sizeof(double));
       printf("\nC vector (with %d row data):\n", i);
       for (j=0;j<n;j++)
           printf(" %7.3lf", c[j]);
       printf("\n");
   }

/* Free a array */
   for(i=0;i<n;i++)
       free(a[i]);
   free(a);

/* Free b array */
   for(i=0;i<n;i++)
       free(b[i]);
   free(;

/* Free c vector */
   free(c);

   return 0;
}

 

Συνιστώ, δεύτερος, την χρήση typedef και size_t δηλώσεων όπως στον κώδικα του dop απλά δεν τις χρησιμοποίησα εδώ. Νομίζω όμως ότι κάλυψα το ερώτημά του profitis.

 

Υπάρχει ένα warning (μόνο)... dop, φίλοι, αναμένω τα σχόλιά σας.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

1. Η memcpy() ζει στο string.h. Άρα, #include <string.h>

2. Είπαμε, όχι casting στην malloc(). Και ο κώδικάς σου είναι το καλύτερο παράδειγμα: τι θα γίνει αν αντί για double i1, **a, **b, *c; έχουμε my_super_big_struct i1, **a, **b, *c; ? Πόσες φορές θα θυμηθούμε να αλλάξουμε τα πάντα;

3. Τρώω και ένα segmentation fault...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

...με τις διορθώσεις από dop:

 

>
/* array2d_malloc.c: malloc(usage, casting) memcpy...  v0.0.3 */

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

int main (void) {
   int n, i, j;
   double i1, **a, **b, *c;

/* Get array dimension */
   do{
       printf ("\nEnter matrix dimension N>0 : ");
       scanf ("%d",&n);
   }while(n<1);

/* Allocate memory to a as a double array NxN */
   if ((a=malloc(n*sizeof(double *)))==NULL){
       printf("\nNot enough memory avaliable.\n");
       exit(1);
   }

   for(i=0;i<n;i++){
       if ((a[i]=malloc(n*sizeof(double)))==NULL){
           printf("\nNot enough memory avaliable.\n");
           exit(1);
       }
   }

/* Fills a with data */
   for (i=0;i<n;i++){
       i1=(double)i+1;
       a[i][i]=i1/i1;
       for (j=0;j<i;j++)
           a[j][i]=a[i][j]=i1/(j+1);
   }

/* Displays a's data */
   printf("\nA array:\n");
   for (i=0;i<n;i++){
       for (j=0;j<n;j++)
           printf(" %7.3lf", a[i][j]);
       printf("\n");
   }

/* Allocate memory to b as a double array NxN */
   if ((b=malloc(n*sizeof(double *)))==NULL){
       printf("\nNot enough memory avaliable.\n");
       exit(1);
   }

   for(i=0;i<n;i++){
       if ((b[i]=malloc(n*sizeof(double)))==NULL){
           printf("\nNot enough memory avaliable.\n");
           exit(1);
       }
   }

/* Copies a to b */
   memcpy(b,a,n*n*sizeof(double));

/* Displays b's data */
   printf("\nB array:\n");
   for (i=0;i<n;i++){
       for (j=0;j<n;j++)
           printf(" %7.3lf", a[i][j]);
       printf("\n");
   }

/* Allocate memory to c as a double vector N */
   if ((c=malloc(n*sizeof(double)))==NULL){
       printf("\nNot enough memory avaliable.\n");
       exit(1);
   }

/* Copy and display a rows to c */
   for(i=0;i<n;i++){
       memcpy(c,a[i],n*sizeof(double));
       printf("\nC vector (with %d row data):\n", i);
       for (j=0;j<n;j++)
           printf(" %7.3lf", c[j]);
       printf("\n");
   }

/* Free a array */
   for(i=0;i<n;i++)
       free(a[i]);
   free(a);

/* Free b array */
   for(i=0;i<n;i++)
       free(b[i]);
   free(;

/* Free c vector */
   free(c);

   return 0;
}

 

0. Φίλε dop, όπως βλέπεις έχω διορθώσει ΚΑΙ ΤΟ int main(void) :-)

 

1. Δίκαιο έχεις το'χα ξεχάσει. Έγινε.

 

2. ΟΚ και με αυτό. Το'χα παραδεχτεί απλώς ξέχασα να βγάλω το casting τα υπόλοιπα έγιναν copy paste (σε forum είμαστε...)

 

3. Αν το δοκιμάσεις με τιμή έως 8 όλα πάνε καλά (τουλάχιστον στην gcc (GCC) 4.1.0 (SUSE Linux) μου). Αν το δοκιμάσεις με τιμή 9 (και πάνω) όμως... Δοκίμασες να σχολιάσεις τo free "block" στο τέλος; Μήπως τελικά μαζί με το casting πρέπει να καταργήσουμε και τα free; :-)

 

( Που'ναι το λάθος...ΟΕΟ... )

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δοκιμάζοντας τον κώδικα σου στην CodeGear Turbo C++ Express για MS-Windows (είσοδος 8), δίχως να τον έχω μελετήσει καθόλου και με ενεργοποιημένο τον εσωτερικό ανιχνευτή σφαλμάτων διαχείρισης μνήμης (CodeGuard) του compiler μου, έλαβα σφάλμα Access overrun στην εντολή memcpy(b,a,n*n*sizeof(double *)); η οποία δοκιμάζει να προσπελάσει 256 bytes από το heap που είναι μόλις 32 bytes long (δοκίμασε να αλλάξεις το "*n*n*sizeof" σε "n*sizeof" ή καλύτερα αφαίρεσε την εντελώς).

 

Υ.Γ.

1. Θα μου πεις πως μπορεί να πέφτει έξω ο ανιχνευτής μου.

2. Στην εκτύπωση των περιεχομένων του b άλλαξε το "printf(" %7.3lf", a[j]);" σε "printf(" %7.3lf", b[j]);".

3. Φαίνεται πως υπάρχουν ορισμένα σφάλματα στην αποδέσμευση μνήμης (free(b)), ο λόγος προέρχεται από το ότι η "memcpy(b,a,n)" © ή η "CopyMemory(b,a,n)" (Windows API) στην περίπτωση μας (**a,**b) αντικαθιστά συνολικά τις διευθύνσεις του b[]([]) με εκείνες του a[]([]) οπότε η free(b) δοκιμάζει να αποδεσμεύσει τις διευθύνσεις της a[]([]) αφήνοντας τις b=malloc μη αποδεσμευμένες. Το πρόβλημα είναι μεγαλύτερο αλλά γίνεται αμέσως αντιληπτό στις κλήσεις free(b); -δοκίμασε να δεις τις διευθύνσεις των a & b μετά την memcpy με printf "%X\n",&a[j] κτλ. σε εμένα είναι ίδιες.

 

Ο παρακάτω κώδικας δουλεύει σωστά με τον compiler μου και τον CodeGuard (έχω αφαιρέσει την memcpy(b,a,n) η οποία στην αρχική μορφή της φαίνεται να δημιουργεί προβλήματα σε multi-dimensional arrays, προς χάριν δυο αργών for).

 

>
/* array2d_malloc.c: malloc(usage, casting) memcpy...  v0.0.3 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

int main (void) {
int n, i, j;
double i1, **a, **b, *c;

/* Get array dimension */
do{
	printf ("\nEnter matrix dimension N>0 : ");
	scanf ("%d",&n);
}while(n<1);

/* Allocate memory to a as a double array NxN */
if ((a=malloc(n*sizeof(double *)))==NULL){
	printf("\nNot enough memory avaliable.\n");
	exit(1);
}

for(i=0;i<n;i++){
	if ((a[i]=malloc(n*sizeof(double)))==NULL){
		printf("\nNot enough memory avaliable.\n");
		exit(1);
	}
}

/* Fills a with data */
for (i=0;i<n;i++){
	i1=(double)i+1;
	a[i][i]=i1/i1;
	for (j=0;j<i;j++)
		a[j][i]=a[i][j]=i1/(j+1);
}

/* Displays a's data */
printf("\nA array:\n");
for (i=0;i<n;i++){
	for (j=0;j<n;j++)
		printf(" %7.3lf", a[i][j]);
	printf("\n");
}

printf(" | HIT KEY TO CONTINUE |"); getch();

/* Allocate memory to b as a double array NxN */
if ((b=malloc(n*sizeof(double *)))==NULL){
	printf("\nNot enough memory avaliable.\n");
	exit(1);
}

for(i=0;i<n;i++){
	if ((b[i]=malloc(n*sizeof(double)))==NULL){
		printf("\nNot enough memory avaliable.\n");
		exit(1);
	}
}

/* Copies a to b */
for(i=0;i<n;i++)
 for(j=0;j<n;j++)
  b[i][j] = a[i][j];
  
/* memcpy(b,a,n*sizeof(double *)); */

/* Displays b's data */
printf("\nB array:\n");
for (i=0;i<n;i++){
	for (j=0;j<n;j++)
		printf(" %7.3lf", b[i][j]);
	printf("\n");
}

printf(" | HIT KEY TO CONTINUE |"); getch();

/* Allocate memory to c as a double vector N */
if ((c=malloc(n*sizeof(double)))==NULL){
	printf("\nNot enough memory avaliable.\n");
	exit(1);
}

/* Copy and display a rows to c */
for(i=0;i<n;i++){
	memcpy(c,a[i],n*sizeof(double));
	printf("\nC vector (with %d row data):\n", i);
	for (j=0;j<n;j++)
		printf(" %7.3lf", c[j]);
	printf("\n");
}

printf(" | HIT KEY TO CLEANUP |"); getch();

/* Free a array    */
for(i=0;i<n;i++)
	free(a[i]);
free(a);

/* Free b array    */
for(i=0;i<n;i++)
	free(b[i]);
free(;

/* Free c vector */
free(c);

printf("\n | HIT KEY TO QUIT |"); getch();

return 0;
}

 

Καλή συνέχεια!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δεν θα έπρεπε να υπάρχει πρόβλημα με την memcpy(). Αντιγράφω από την man page στο linux (που δεν έχει και τις καλύτερες man pages):

The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas should not overlap. Use memmove(3) if the memory areas do overlap.

 

Θεωρητικά δεν πρέπει να υπάρχει πρόβλημα - και πρακτικά δεν έχει, αφού την έχω χρησιμοποιήσει άπειρες φορές. Αλλού είναι το πρόβλημα - μόλις βρω λίγο χρόνο θα το κοιτάξω.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπράβο... Πλησίασες αρκετά... Συνέχισε να το ψάχνεις αν έχεις χρόνο.

 

@dop & other "Programming Insomniacs":

Πρώτα όλα τα άλλα (οικογένεια, σπουδές, ταίρια, ότι θέλετε) και μετά το forum. Απλά πείτε μου:

 

"Να το πάρει το ποτάμι;"

 

Είναι απλό, είναι μπροστά σας ΑΛΛΑ...

 

(@all: Αν το βρεις μην το μαρτυρίσεις αμέσως... Από την άλλη, μην αφιερώσεις πάνω από 30 λεπτά... Νομίζω ότι δεν αξίζει περισσότερο χρόνο)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπράβο... Πλησίασες αρκετά... Συνέχισε να το ψάχνεις αν έχεις χρόνο.

 

Φίλε chiossif,

 

Είναι τόσο μικρά .. * και όμως είναι τόσο σημαντικά, κοινά αλλά διαφορετικά * ..

το ένα κοιτάζει ανατολικά και το άλλο δυτικά..

 

Δεν λέω τίποτε περισσότερο..

Τα υπόλοιπα τα αφήνω σε σένα -όποτε κρίνεις σκόπιμο.

;)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.


  • Δημιουργία νέου...