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

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

Δημοσ. (επεξεργασμένο)

Καλησπέρα σας,

 

Πίνακες στην γλώσσα προγραμματισμού C μπορούν να δημιουργηθούν με δύο τρόπους και χωρίζονται σε δύο κατηγορίες:

α) Στατικοί πίνακες

β) Δυναμικοί πίνακες

 

Στατικοί πίνακες: Είναι οι πίνακες που όπως λέει και η λεξη έχουν μια στατική=σταθερή δομή απο όταν αρχίζει το πρόγραμμά μας μέχρι να τελειώσει.

 

Δυναμικοί πίνακες: Αντίθετα με τους στατικούς, οι δυναμικοί προσφέρουν τη δυνατότητα στο χρήστη να μεταβάλλει το μέγεθός τους. Ίσως φαίνεται λίγο παράξενο αυτό πχ. Εάν έχουμε έναν πίνακα 3x2 ΔΥΝΑΜΙΚΑ φτιαγμένο μπορούμε να τον αλλάξουμε σε 8x10.

 

Δημιουργία μονοδιάστατου πίνακα:

 

>
/* Δημιουργία μονοδιάσταστου πίνακα Α */
/* Δώστε τιμές στον πίνακα */
[color="DarkGreen"]#include <stdio.h>
#include <stdlib.h>
#define n 5
int main(void){
int i, number;
int A[n];

	printf("Please type numbers for the A array:\n");
	for(i=0; i<n; i++){
		printf("A[%d]: \n", i);
		scanf("%d", &number);
		A[i]=number;
	}

	for(i=0; i<n; i++){
		printf("A[%d]: %d\n", i, A[i]);
	}

return 0;
}
[/color]

 

Δημιουργία διδιάστατου πίνακα:

 

>
/* Δημιουργία διδιάστατου πίνακα B */
/* Δώστε τιμές στον πίνακα */
[color="DarkGreen"]#include <stdio.h>
#include <stdlib.h>
#define n 3
#define m 2
int main(void){
int i, j, number;
int B[n][m];

	printf("Please type numbers for the B array:\n");
	for(i=0; i<n; i++){
		for(j=0; j<m; j++){
			printf("B[%d][%d]: \n", i, j);
			scanf("%d", &number);
			B[i][j]=number;
		}
	}

	for(i=0; i<n; i++){
		for(j=0; j<m; j++){
			printf("B[%d][%d]: %d\n", i, j, B[i][j]);
		}
	}

return 0;
}
[/color]

 

Δημιουργία μονοδιάστατου πίνακα(δυναμικά):

 

>
/* Δημιουργία μονοδιάστατου πίνακα B δυναμικά*/
/* Δώστε τιμές στον πίνακα */
[color="DarkGreen"]#include <stdio.h>
#include <stdlib.h>
#define n 3
int main(void){
int i, number;
int *B;

	B=(int *)malloc(n*sizeof(int));

	printf("Please type numbers for the B dynamic array:\n");
	for(i=0; i<n; i++){
			printf("B[%d]: \n", i);
			scanf("%d", &number);
			B[i]=number;
	}

	for(i=0; i<n; i++){
			printf("B[%d]: %d\n", i, B[i]);
	}

return 0;
}
[/color]

 

Δημιουργία διδιάστατου πίνακα(δυναμικά):

 

>
/* Δημιουργία διδιάστατου πίνακα B δυναμικά*/
/* Δώστε τιμές στον πίνακα */
[color="DarkGreen"]#include <stdio.h>
#include <stdlib.h>
#define n 3
#define m 2
int main(void){
int i, j, number;
int **B;

	B=(int **)malloc(n*sizeof(int *));
		for(i=0; i<n; i++){
			B[i]=(int *)malloc(m*sizeof(int));
		}

	printf("Please type numbers for the B dynamic array:\n");
	for(i=0; i<n; i++){
		for(j=0; j<m; j++){
			printf("B[%d][%d]: \n", i, j);
			scanf("%d", &number);
			B[i][j]=number;
		}
	}

	for(i=0; i<n; i++){
		for(j=0; j<m; j++){
			printf("B[%d][%d]: %d\n", i, j, B[i][j]);
		}
	}

return 0;
}[/color]

 

Εάν χρειάζεστε κάποια διευκρίνηση πείτε μου...

Επεξ/σία από linuxs
  • Απαντ. 31
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Δημοσ.
Πώς παιδεύεστε με τους πίνακες στη C/C++...

 

H έλλειψη εγγενούς υποστήριξης είναι μεγάλος μπελάς.

Αν πχ. θέλω έναν πίνακα με μιγαδικούς τι κάνω ;

Aν θέλω μια εντολή να δρα σε έναν ολόκληρο πίνακα τι κάνω ( πχ. cos(A) ) ;

Μεγάλη φασαρία...

 

Στην Fortran που υποστηρίζονται ενδογενώς είναι μια-δύο γραμμές.

Ούτε malloc, ούτε κλάσσεις, ούτε δείκτες....

 

Συμφωνώ με τα άλλα μηνύματα σου που προτείνεις αντικειμενοστραφή

προγραμματισμό αλλά η Fortran έχει πεθάνει και έχουν λιώσει και τα κόκκαλα της.

 

 

Δημιουργία μονοδιάστατου πίνακα(δυναμικά):

 

>
[color="DarkGreen"]
	B=[b](int *)[/b]malloc(n*sizeof(int));
[/color]

 

Δημιουργία διδιάστατου πίνακα(δυναμικά):

 

>
[color="DarkGreen"]
	B=[b](int **)[/b]malloc(n*sizeof(int *));
			B[i]=[b](int *)[/b]malloc(m*sizeof(int));
[/color]

 

Εάν χρειάζεστε κάποια διευκρίνηση πείτε μου...

 

linuxs ωραίος. Σίγουρα θα βοηθήσει πολύ κόσμο.

Μια ένσταση έχω μόνο στην χρήση των casts. Καλή πρακτική είναι να αποφεύγονται

τα cast όπου δεν είναι απαραίτητα.

 

Παλαιότερα η malloc επέστρεφε char * οπότε ήταν συνήθης η χρήση των cast

για να πάρεις τον τύπο που ήθελες, όπως εδώ το (int *) και (int **).

Πλέον η malloc επιστρέφει void *. Το πρότυπο της C δηλώνει ότι γίνεται αυτόματα

μετατροπή από οποιοδήποτε τύπο δείκτη σε void * και αντίστροφα οπότε το cast

δεν χρειάζεται.

 

** Σε C++ δεν γίνεται η μετατροπή οπότε χρειάζεται το cast **

Δημοσ. (επεξεργασμένο)
Συμφωνώ με τα άλλα μηνύματα σου που προτείνεις αντικειμενοστραφή

προγραμματισμό αλλά η Fortran έχει πεθάνει και έχουν λιώσει και τα κόκκαλα της.

 

 

 

linuxs ωραίος. Σίγουρα θα βοηθήσει πολύ κόσμο.

Μια ένσταση έχω μόνο στην χρήση των casts. Καλή πρακτική είναι να αποφεύγονται

τα cast όπου δεν είναι απαραίτητα.

 

Παλαιότερα η malloc επέστρεφε char * οπότε ήταν συνήθης η χρήση των cast

για να πάρεις τον τύπο που ήθελες, όπως εδώ το (int *) και (int **).

Πλέον η malloc επιστρέφει void *. Το πρότυπο της C δηλώνει ότι γίνεται αυτόματα

μετατροπή από οποιοδήποτε τύπο δείκτη σε void * και αντίστροφα οπότε το cast

δεν χρειάζεται.

 

** Σε C++ δεν γίνεται η μετατροπή οπότε χρειάζεται το cast **

 

ευχαριστώ...

 

Να σημειώσω οτι μάλλον δεν πρόλαβα την παλιότερη γενιά με τα "char" όπως ανέφερες.

Όπως και να έχει, πιστεύω πως, πολλές φορές ίσως είναι καλό να χρησιμοποιείς γενικούς τύπους, γιατί:

1) Επαναλαμβάνεις πράγματα που ήδη έχεις μάθει με αποτέλεσμα να μην τα ξεχνάς.

2) Είσαι σίγουρος ότι όταν θα κάνεις compile δεν θα έχεις λάθος εκεί (έστω και αν προκλήθηκε απο απροσεξία)

3) Υπάρχει και ένα μικρό tip για να τα θυμάσαι..."όσο προσωράς τα * μειώνονται κατα ένα".

 

Πιστεύω να καλύφτηκες...φιλικά

 

linuxs.

 

---------- Προσθήκη στις 21:10 ---------- Προηγούμενο μήνυμα στις 21:04 ----------

 

Πώς παιδεύεστε με τους πίνακες στη C/C++...

 

H έλλειψη εγγενούς υποστήριξης είναι μεγάλος μπελάς.

Αν πχ. θέλω έναν πίνακα με μιγαδικούς τι κάνω ;

Aν θέλω μια εντολή να δρα σε έναν ολόκληρο πίνακα τι κάνω ( πχ. cos(A) ) ;

Μεγάλη φασαρία...

 

Στην Fortran που υποστηρίζονται ενδογενώς είναι μια-δύο γραμμές.

Ούτε malloc, ούτε κλάσσεις, ούτε δείκτες....

 

Λίγο άσχετο.

Δεν κόβω το κεφάλι μου αλλα στο προγραματισμό στο λύκειο, στο 6ο κεφάλαιο όταν έλεγε για τις γλώσσες(fortran) δεν έλεγε δίπλα: "Κυριώς για μαθηματικές πράξεις"? Αν έχω δίκιο, αυτός είναι ο λόγος που χρησιμοποιείς την Fortran για το cos(Α) που ανέφερες...

 

φιλικά,

 

linuxs.

Επεξ/σία από linuxs
Δημοσ.

ο στατικός πινακας δηλαδή σε μια συνάρτηση υπάρχει από την αρχή μέχρι το τέλος ενός προγράμματος?

 

δεν μπορώ έχω έναν πινακα από structs να παρουσιάσω έτσι μιγαδικούς?

 

δεν μπορώ να φτιάξω μια ρουτίνα που να κάνει cos σε όλα τα στοιχεια ενός πινακα?

Δημοσ.

Τα offtopic μηνύματα έγιναν split σε νέο thread.

 

Παρακαλώ κρατήστε το παρόν νήμα καθαρό από περαιτέρω offtopic posts τύπου «Καλά αυτά που γράφεις, στην τάδε γλώσσα όμως...» κλπ κλπ.

 

Ευχαριστώ.

  • 7 μήνες μετά...
Δημοσ.

ο στατικός πινακας δηλαδή σε μια συνάρτηση υπάρχει από την αρχή μέχρι το τέλος ενός προγράμματος?

 

δεν μπορώ έχω έναν πινακα από structs να παρουσιάσω έτσι μιγαδικούς?

 

δεν μπορώ να φτιάξω μια ρουτίνα που να κάνει cos σε όλα τα στοιχεια ενός πινακα?

 

ναι στον στατικό στατικό πίνακα ορίζει εξαρχής το μέγεθος του πίνακα που θέλεις...μπορείς να έχεις έναν πινακα από structs να παρουσιάσω έτσι μιγαδικούς.! :)

  • 8 μήνες μετά...
Δημοσ.

Μπορεί κάποιος να εξηγήσει λίγο αναλυτικά πως δουλεύουν οι δυναμικοί πίνακες;

Γενικά έχω μάθει λίγα πράγματα για τη C, καθώς είμαι πρωτοετής και δεν καταλαβαίνω τον κώδικα παραπάνω..

Ας πούμε πως θέλουμε να φτιάξουμε ένα μονοδιάστατο πίνακα N θέσεων, όπου το N το καθορίζει ο χρήστης…

Πώς πρέπει να σκεφτούμε για να το κάνουμε;

Ευχαριστώ..

Δημοσ.

Μπορεί κάποιος να εξηγήσει λίγο αναλυτικά πως δουλεύουν οι δυναμικοί πίνακες;

Γενικά έχω μάθει λίγα πράγματα για τη C, καθώς είμαι πρωτοετής και δεν καταλαβαίνω τον κώδικα παραπάνω..

Ας πούμε πως θέλουμε να φτιάξουμε ένα μονοδιάστατο πίνακα N θέσεων, όπου το N το καθορίζει ο χρήστης…

Πώς πρέπει να σκεφτούμε για να το κάνουμε;

Ευχαριστώ..

Βασικά, από το πρότυπο C99 και μετά έχουμε 3 ειδών πίνακες, τους 2 που λέει αυτό το νήμα και τους Variable Length Arrays που προστέθηκαν μετά το C99 (μαζί με την δυνατότητα να ορίζεις μεταβλητές σε οποιαδήποτε γραμμή του scope και όχι μόνο στην αρχή του, όπως ίσχυε μέχρι και το ANSI standard)

 

Στο ερώτημά σου λοιπόν υπάρχουν 2 τρόποι: είτε με δυναμική διαχείριση μνήμης (που δουλεύει παντού) είτε με πίνακες μεταβλητού μεγέθους που ισχύει μόνο σε compilers που υποστηρίζουν το πρότυπο C99.

 

Πίνακες Μεταβλητού Μεγέθους (C99)

 

>
#include <stdio.h>

int main( void )
{
 int nelems = 0;

 do {
       printf("How many elements (must be more than 0) ?  ");
   	scanf("%d", &nelems );
  } while (nelems < 1);

 int array[ nelems ] = {0};
 ...
 return 0;
}

 

Δυναμική Διαχείριση Μνήμης

 

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

int main( void )
{
 int nelems = 0;
 int *array = NULL;

 do {
       printf("How many elements (must be more than 0) ?  ");
   	scanf("%d", &nelems );
 } while (nelems < 1);

 array = calloc( nelems, sizeof(int) );
 if ( !array ) {
 	puts("memory failure, exiting program...");
 	exit( EXIT_FAILURE );
 }
 ...
 free( array );
 exit( EXIT_SUCCES );
}

 

ΥΓ. Επίσης, ένας πίνακας μπορεί να οριστεί δυναμικά ως μονοδιάστατος με πλήθος στοιχείων nelems ( = MAXROWS* MAXCOLS) και να διαχειριστεί σαν να ήταν δισδιάστατος, με τους τύπους:

 

>
irow = n / MAXCOLS;
jcol  = n % MAXCOLS;

με το n να είναι ο μετρητής που διατρέχει τα nelems στοιχεία του μονοδιάστατου πίνακα (η εκάστοτε δηλαδή τρέχουσα θέση του).

 

Το αντίστροφο δίνεται από τον τύπο:

 

>
n = irow * MAXCOLS + jcol

με τα irow και jcol να είναι οι μετρητές των γραμμών και των στηλών αντίστοιχα, αν επιλέξεις να διατρέχεις τον πίνακα με 2 φωλιασμένα loops (σαν να ήταν δηλαδή δισδιάστατος) και θέλεις στο κάθε βήμα να υπολογίζεις τη τρέχουσα θέση του μονοδιάστατου πίνακα, δηλαδή το n.

 

Ο τελευταίος είναι ο τρόπος που υλοποιούνται εσωτερικά από τον compiler οι δισδιάστατοι πίνακες, όταν ορίζονται ως πίνακες επί τούτου (είτε στατικά είτε με μεταβλητό μέγεθος)... π.χ...

 

>
int array[ MAXROWS ][ MAXCOLS ];

και εγγυάται πως ο πίνακας καταλαμβάνει συνεχόμενη μνήμη.

Δημοσ.

ακριβώς επειδή υλοποιούνται έτσι, μπορείς να τους φτιάξεις εσύ και δυναμικά.

 

Δηλαδή, για rows x columns πίνακα, δεσμεύεις rows*columns+rows blocks μνήμης, αναλόγως το size της μεταβλητής, και, εάν έχουμε 3x4 πίνακα, 0, 5, 10 στοιχεία είναι δείκτες για την "επόμενη" σειρά.

 

Έτσι, και δυναμικά δεσμεύεις μνήμη, και συνεχόμενη είναι αλλά και μπορείς να χρησιμοποιείς το a[n][m] notation χωρίς να χρησιμοποιείς workaround για το "σε ποια σειρά και στήλη είμαι".

Δημοσ.

ακριβώς επειδή υλοποιούνται έτσι, μπορείς να τους φτιάξεις εσύ και δυναμικά.

 

Δηλαδή, για rows x columns πίνακα, δεσμεύεις rows*columns+rows blocks μνήμης, αναλόγως το size της μεταβλητής, και, εάν έχουμε 3x4 πίνακα, 0, 5, 10 στοιχεία είναι δείκτες για την "επόμενη" σειρά.

 

Έτσι, και δυναμικά δεσμεύεις μνήμη, και συνεχόμενη είναι αλλά και μπορείς να χρησιμοποιείς το a[n][m] notation χωρίς να χρησιμοποιείς workaround για το "σε ποια σειρά και στήλη είμαι".

 

Έτσι όμως χρειάζεσαι άλλο workaround για να μη αποθηκεύεις meaningful τιμές στην έξτρα στήλη που χρησιμοποιείς, έτσι δεν είναι; Εκτός αν εννοείς κάτι άλλο.

 

Κανονικά αρκεί να δεσμεύσεις (rows * columns) στοιχεία, και τα 2D indexing workarounds τα κάνεις 2 macros.

Δημοσ.

Μπορεί κάποιος να εξηγήσει λίγο αναλυτικά πως δουλεύουν οι δυναμικοί πίνακες;

Γενικά έχω μάθει λίγα πράγματα για τη C, καθώς είμαι πρωτοετής και δεν καταλαβαίνω τον κώδικα παραπάνω..

Ας πούμε πως θέλουμε να φτιάξουμε ένα μονοδιάστατο πίνακα N θέσεων, όπου το N το καθορίζει ο χρήστης…

Πώς πρέπει να σκεφτούμε για να το κάνουμε;

Ευχαριστώ..

 

Γιατι σας μαθαινουν πινακες χωρις να σας μαθουν το memory layout..........................

 

Googlare "process memory layout" μπας και καταλαβεις ποιος ο λογος που τα κανεις αυτα.

Δημοσ.

Έτσι όμως χρειάζεσαι άλλο workaround για να μη αποθηκεύεις meaningful τιμές στην έξτρα στήλη που χρησιμοποιείς, έτσι δεν είναι; Εκτός αν εννοείς κάτι άλλο.

 

Κανονικά αρκεί να δεσμεύσεις (rows * columns) στοιχεία, και τα 2D indexing workarounds τα κάνεις 2 macros.

 

 

True. Αλλά από το να έχεις macros καλύτερα να έχεις square brackets :P

Δημοσ.

Α, τώρα κατάλαβα τι εννοείς, ομορφιά :)

 

Παραθέτω και κώδικα για αυτά που έχω γράψει παραπάνω, για να είναι ολοκληρωμένη η απάντηση...

 

Π.χ.

 

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

#define MAXROWS  	5
#define MAXCOLS    	10
#define MAXSIZE   	(MAXROWS * MAXCOLS)

#define n2i(n)      	( (n) / MAXCOLS )
#define n2j(n)      	( (n) % MAXCOLS )
#define ij2n(i,j)   	( (i) * MAXCOLS + (j) )

int main( void )
{
register int i =0, j = 0, n = 0;
int *array = calloc( MAXSIZE, sizeof(int) );

if ( !array )
         	exit( EXIT_FAILURE );

/* parse as 2D */
for (i=0; i < MAXROWS; i++)
           for (j=0; j < MAXCOLS; j++)
           	printf("Pos: %d, Val: %d\n", ij2n(i,j), array[ ij2n(i,j) ]);

/* parse as 1D */
for (n=0; n < MAXSIZE; n++)
       	printf("Row: %d, Col: %d, Val: %d\n", n2i(i), n2j(j), array[ n ] );

free( array );
exit( EXIT_SUCCESS );
}

Δημοσ.

Ωραία οσον αφορά πίνακες μορφής int...

Τι γίνεται όμως όταν θέλω να αποθηκεύσω Ν αριθμό strings, (μεταβλητού μεγέθους),

όπου το Ν και κάθε string ορίζεται από το χρήστη;

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

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