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

Μια μικρή βοήθεια στην C!


georgep800

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

Δημοσ.

Είμαι αρχάριος και έχω μια απορία...

Θέλω να δεσμεύσω δυναμικά μνήμη ώστε να αποθηκεύσω αριθμούς(int). Κάθε φορά όταν θα αποθηκεύω ένα αριθμό, τότε θα δεσμεύω και την μνήμη. Επίσης θα πρέπει να μπορώ να προσπελάζω τους αριθμούς που έχω εισάγει. Προφανώς θα πρέπει να χρησιμοποιήσω την malloc, έτσι;

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

Δημοσ.

H malloc exei to ekshs prototype:

 

void *malloc(size_t size);

 

Epistrefei dhladh enan void pointer ton opoion mporeis na kaneis cast se oti type pointer 8eleis, px (int *)

H parametros einai typou size_t diladi unsigned int kai desmeuei bytes.

 

H xrhsh ths entolhs ginete os ekshs:

 

Orizeis prwta enan int pointer

int * p;

 

Desmeueis dunamika mnhmh gia mia metablhth int

p = (int *) malloc(sizeof(int)); /* Desmeush mnhmhs gia mia metablhth int (o tupos int einai 4 bytes sto mhxanhma mou opote h sizeof epistrefei 4) kai desmeuonte 4 bytes */

 

H sizeof(type) briskei to mege8os se bytes tou typou int kai epistrefei metablhth tupoy size_t.

 

Gia na xrhsimopoihseis thn mnhmh pou molis desmeuses:

*p = 5;

 

Ean h8eles na desmeuseis mnhmh gia ena array me 10 integers 8a eggrafes

p = (int *) malloc(10 * sizeof(int));

 

 

Ena paradeigma:

 

#include <stdio.h>

#include <stdlib.h>

 

int main() {

int *p, i;

 

 

p = (int *) malloc(sizeof(int));

 

*p = 3;

 

printf("P is: %d\n", *p);

 

p = (int *) malloc(10 * sizeof(int));

 

for (i = 0; i < 10; i++)

p = i*i;

 

for (i = 0; i < 10; i++)

printf("p[%d] = %d\n", i, p);

 

free(p);

 

return 0;

}

 

An 8elame na prospelasoume ton pinaka me pointers to programma 8a grafotan os ekshs:

 

#include <stdio.h>

#include <stdlib.h>

 

int main() {

int *p, i, *tp;

 

 

p = (int *) malloc(sizeof(int));

 

*p = 3;

 

printf("P is: %d\n", *p);

 

p = (int *) malloc(10 * sizeof(int));

 

tp = p;

 

for (i = 0; i < 10; i++)

*tp++ = i * i;

 

for (i = 0; i < 10; i++)

printf("p[%d] = %d\n", i, p);

 

free(p);

 

return 0;

}

 

Elpizw na boh8hsa, mhn ksexaseis na kaneis #include to header <stdlib.h> kai free() thn mnhmh pou desmeuses otan den xreiazese pleon tis metablhtes. Epishs panta na kaneis elenxo meta thn klhsh tis malloc gia na diapustoseis an ontos desmeutike h mnhmh

px.

p = (int *) malloc(sizeof(int));

 

if (p == NULL) {

/* handle error */

}

 

Links:

http://en.wikipedia.org/wiki/Malloc

http://computer.howstuffworks.com/c29.htm

http://www.pccl.demon.co.uk/C/sizeof.html <-- sizeof

 

Good Luck

Δημοσ.

Θέλω να δεσμεύσω δυναμικά μνήμη ώστε να αποθηκεύσω αριθμούς(int).

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

 

Κάθε φορά όταν θα αποθηκεύω ένα αριθμό, τότε θα δεσμεύω και την μνήμη.

Αυτή σου η φράση όμως αλλάζει κάπως τα πράγματα. Η λύση σε αυτό το πρόβλημα λέγεται συνδεδεμένη λίστα και με απλή έρευνα (linked list) βρήκα αυτά: http://en.wikipedia.org/wiki/Linked_list και http://cslibrary.stanford.edu/103 .

 

Είμαι αρχάριος και έχω μια απορία...

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

Αν μπορείς να κάνεις και με πίνακες την δουλειά σου, τα παραπάνω παραδείγματα είναι ενδεικτικά και άρα ξεκίνα.

 

Σε κάθε περίπτωση πρέπει να κάνεις κάτι ώστε να μην μείνεις αρχάριος. Η μόνη βοήθεια που προτείνω σε αυτό είναι το διάβασμα ενός καλού βιβλίου...

Δημοσ.

Καταρχήν σας ευχαριστώ για την βοήθεια!

@DiAvOl ήσουν κατατοπιστικότατος, πιστεύω κατάλαβα πως δουλεύει!

 

@chiossif έχω το βιβλίο που έχεις στο avatar σου, όπως επίσης και τον "Οδηγό της C". Δεν αναφέρει όμως αρκετά πράγματα...

 

Νομίζω ότι με πίνακες θα μου είναι ευκολότερο, οπότε λέω να το κάνω έτσι. Μου δημιουργήθηκε και μια ακόμα απορία.

Όταν έχω δεσμεύσει μνήμη για έναν ακέραιο και δεσμεύσω ξανά μνήμη για άλλον έναν ακέραιο, ο τελευταίος δείκτης έχει σχέση με τον προηγούμενο δείκτη που μου επιστράφηκε; Το ρωτάω με την έννοια αν π.χ. έχω εισάγει 10 αριθμούς(έχοντας δεσμεύσει την μνήμη για τον κάθε ένα ξεχωριστά) πως μπορώ να πάω στον πρώτο αριθμό που έχω εισάγει, με ένα βήμα;

 

Επίσης και κάτι άλλο. Αν πάω στον πρώτο αριθμό ή σε οποιονδήποτε άλλο απο τους 10 αριθμούς και θελήσω να διαγράψω κάποιον, θα υπάρξει κάποιο πρόβλημα; Μήπως δεν θα έχω συνοχή;

Δημοσ.

Καταρχάς η malloc πρέπει να καλείται ως εξής:

>
int *p = malloc(sizeof(*p));

Έτσι, αφενός θα μας προειδοποίησει ο compiler αν προσπαθήσουμε να αποθηκεύσουμε pointer x τύπου σε pointer y τύπου. Αφεταίρου, ακόμα και αν αλλάξει ο τύπος του p, δεν χρειάζεται να πειράξουμε την malloc().

 

Στα υπόλοιπα τώρα: δεν σου εγγυάται κανείς ότι ο κάθε pointer σε κάποιο μέρος της δεσμευμένης μνήμης θα είναι ο αμέσος επόμενος από την προηγούμενη δέσμευση - εκτός και αν έχεις κάποια δικιά σου malloc. Διαγραφές μπορείς να κάνεις άφοβα.

 

Αν είναι να χρησιμοποιήσεις pointers για αποθήκευση ints και αυτοί οι pointers θα βρίσκονται σε κάποια δομή, τότε μπορείς πολύ απλά να αποθηκεύσεις τους ίδιους τους ints, καθώς στα 32bit μηχανήματα συνήθως sizeof(void*)==sizeof(int). Μάλιστα στα 64bit, sizeof(void*)>sizeof(int)

Δημοσ.

@DiAvOl

 

Μια ερώτηση, σχετικά με το παρακάτω τμήμα κώδικα π έγραψες πιο πάνω:

 

>

tp = p;

for (i = 0; i < 10; i++)
*tp++ = i * i;

for (i = 0; i < 10; i++)
printf("p[%d] = %d\n", i, p[i]);

 

Το tp, δεν κατάλαβα τι ακριβώς κάνει...

 

Δλδ στην αρχή το κάνεις ίσο με το p, δλδ στο παράδειγμα ίσο με το 3.

 

Μετά μέσα στη for βάζεις τιμές στο δείκτη tp αντί όπως έκανες στο προηγούμενο παράδειγμα με τον πίνακα. Στη συνέχεια κάνεις ολίσθηση το tp και αυξάνεται...

 

Δεν κατάλαβα που χρησιμεύει αυτό, ειδικά όταν στη συνέχεια δεν το χρησιμοποιείς πουθενά αλλού... Αν ξεκινούσε το tp απο το 0, θα μου φαινόταν λογική η ολίσθηση. Επίσης δεν κατάλαβα επακριβώς τη δουλειά του tp, δλδ λειτουργεί σαν πίνακας;

 

2ο ερώτημα σχετικό με δέσμευση μνήμης και πίνακα 2 διαστάσεων...

 

>
float **p;

float N,M;

printf ("\n Dwse to N kai to M: ");
scanf ("%f%f",&N,&M);

meg=N*sizeof(int *);

p=malloc(meg);

meg=N*sizeof(float);

for (i=0;i<N;i++)
{
  p[i]=malloc(meg);
   
    if (p==NULL)  
      {
       printf ("\n\n FAILURE! \n\n);
        return 0;
       }
   }

 

Μπορεί κανείς να μου εξηγήσει λιγάκι τι γίνεται; Τα 2 * τι ακριβώς κάνουν;

 

Δηλαδή αν ήταν Ν διαστάσεων θα είχαμε και Ν *;

 

Απ'οτι μας εξήγησε ο καθηγητής, στην αρχή δεσμεύουμε χώρο Ν θέσεων για το p και στη συνέχεια χώρο Μ θέσεων για κάθε δεσμευμένη θέση του Ν.

 

Δηλαδή για τον πρώτο πραγματικό απο τους Ν πραγματικούς, δεσμεύουμε Μ θέσεις, δλδ στην ουσία είναι σαν να δεσμεύουμε Μ στήλες για την πρώτη γραμμή, και ούτο κάθε εξής....

 

Παρόλα αυτά έχω μπερδευτεί πολύ γιατί μας έδωσε και ένα δεύτερο παράδειγμα, αυτή τη φορά για δυναμική δέσμευση μνήμης σε 2 διαστάσεις με την μια διάσταση γνωστή (!) αυτό είναι που δεν το κατάλαβα καθόλου μα καθόλου....

 

>
float (*p)[N];

float M; 

printf ("\n Dwse to M: \n");
scanf ("%f",&M);

meg=N*M*sizeof(float);

p=malloc(meg);

if (p==NULL)
return 0;

 

Όποιος μπορεί και εδώ να μου εξηγήσει τι έγινε θα με σώσει απο την παράνοια...

 

Δεν μπορώ να καταλάβω αφού πάλι είναι πίνακας 2 διαστάσεων γιατί δεν χρησιμοποίησε 2 *;

 

EDIT

 

Και κάτι ακόμα, εφόσον γίνεται να δεσμεύουμε χώρο με μια απο τις δυο διαστάσεις να είναι άγνωστη (πράγμα π δεν καταλαβαίνω πως διάολο γίνεται), υπάρχει περίπτωση να γίνεται το ίδιο και για 2 ή και περισσότερες άγνωστες διαστάσεις;

 

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

Δημοσ.

Φίλε lomar,

 

μην παρανοής. ΑΠΛΑ διάβασε το 5ο Κεφάλαιο: "Δείκτες και Πϊνακες" από το K&R. ΟΛΕΣ οι απαντήσεις στις απορίες σου ΕΙΝΑΙ ΕΚΕΙ.

 

Επίσης αυτό το θέμα το συζητήσαμε και εκεί:

http://www.insomnia.gr/vb3/showthread.php?t=167487

(ιδιαίτερα από το 23ο και μετά- το quiz-λάθος δεν αφορά αυτό που ρώτησες)

οπότε ρίξε μια ματιά να τα θυμηθείς.

 

Σκέψου επίσης τις ακόλουθες προτάσεις:

 

- Κάθε όνομα πίνακα είναι δείκτης στο 1ο στοιχείο του.

Δηλαδή:

 

int a[10];

int *p, k;

p=a;

 

Το p είναι δείκτης σε ακέραιο και το a ΔΕΙΚΤΗΣ στο a[0].

Οι ακόλουθες φράσεις ΕΙΝΑΙ ισοδύναμες:

p=a; <===> p=&a[0];

k=*p; <===> k=a[0]; <===> k=*a;

 

- H malloc δεσμεύει μνήμη ΤΗΝ ΣΤΙΓΜΗ ΤΗΣ ΚΛΗΣΗΣ ΤΗΣ.

Δηλαδή:

1η περίπτωση:

 

int a[10], i;

 

for (i=0;i<10;i++)

a=2*i; <===> *(a+i)=2*i;

 

2η περίπτωση:

 

int *p,i;

 

p=malloc(10*sizeof(int));

 

for (i=0;i<10;i++)

p=2*i; <===> *(p+i)=2*i;

 

Στην 1η περίπτωση ΤΗΝ ΣΤΙΓΜΗ της μεταγλώτισης δεσμεύεται η μνήμη 10 int και ο ΣΤΑΘΕΡΟΣ ΔΕΙΚΤΗΣ a δείχνει σε αυτήν. Στην 2η περίπτωση ορίζεται κατ'αρχήν ο δείκτης p (ΜΕΤΑΒΛΗΤΟΣ) και αφού η malloc δεσμεύση μνήμη 10 int βάζουμε τον p να δείχνει σε αυτήν. Εννοείται ότι οι παραπάνω δηλώσεις μπορούν να ανακατευτούν στην περίπτωση πολλών διαστάσεων (αυτό που έκανε ο δάσκαλος σου).

 

- 'Ενα αστεράκι για κάθε διάσταση; Ναι, αν σκοπεύεις να δηλώνεις int ***p; και να χρησιμοποιείς με p[j][k]. ΣΧΕΔΟΝ ΠΑΝΤΑ όμως τα ** (ή και το ένα στο παράδειγμα μου) αρκούν διότι με ένα απλό τρικ της μορφής p[ ((i*N)+j)*M+k ] "μιλάς" σε όσες διαστάσεις θες.

 

Ελπίζω να βοήθησα. Επαναλαμβάνω - θυμίζω το διάβασμα...

Δημοσ.

@chiossif

 

To παραπάνω βιβλίο δν το έχω :(

 

Αnyway, κατάλαβα τι θές να πεις!!!!!!!!

 

δλδ στην πρώτη περίπτωση μου λές ότι, εφόσον ο 1ος όρος του δυναμικά ορισμένου πίνακα (έστω ότι είναι ο *α) είναι ο α[0] (αφότου δεσμευθεί ο κατάλληλος χώρος απο την malloc προκειμένου να γίνει πίνακας ο δείκτης α), τότε ο επόμενος όρος είναι ο *(α+1), επειδή η επόμενη θέση του δυναμικά ορισμένου πίνακα είναι η α[0]+1 και γενικά α[0]+i, επειδή όμως θέλουμε την διεύθυνση μνήμης του κάθε όρου χρησιμοποιούμε αυτή την πρόταση: *(α[0]+i).

 

πχ, έστω ότι ο πρώτος όρος είναι ο α[0]=15 <=> *α=15, ο επόμενος θα είναι δεσμευμένος στην επόμενη θέση μνήμης, στη 16, και η τιμή που θα έχει το δεύτερο στοιχείο του πίνακα θα είναι η: *16 <=> *(α[0]+1), η τιμή του τρίτου στοιχείου θα είναι *(α[0]+2) κτλ.

 

Αυτό το κατάλαβα και δεν περίμενα ποτε να χρησιμοποιούνται έτσι οι δείκτες, πολύ κατατοπιστικό το παράδειγμά σου :D

 

Αυτό όμως δεν το πολυκατάλαβα: p[ ((i*N)+j)*M+k ]

 

Δλδ μου λες οτι: η μεταβλητή p θα έχει: i φορές το Ν και όλο αυτό +j, το j τι είναι και σε τι εξυπηρετεί;

 

Παρακάτω, το *Μ+k το καταλαβαίνω μέχρι και το Μ, εννοείς δλδ οτι στον αρχικό χώρο των Ν θέσεων τον πολ\ζεις με Μ φορές, προκειμένου για κάθε Ν να υπάρχουν Μ θέσεις (δλδ για κάθε γραμμή και ανάλογες στήλες) το +k (που φαντάζομαι οτι είναι τις ίδιας λογικής με το +j) δν το καταλαβαίνω...

 

Πάντως η όλη λογική με τους δείκτες είναι φανταστική, αυτοί που έφτιαξαν τη C κατάφεραν με 2 τελεστές και μια λιτή λογική να φτιάξουν κάτι το οποίο έχει θεωρητικά άπειρες δυνατότητες και είναι πολύ ευέλικτο και προσαρμόσιμο!

Δημοσ.

To παραπάνω βιβλίο δν το έχω :(

 

Αγόρασέ το λοιπόν. Δεν πρέπει να λύπει από την βιβλιοθήκη σου.

 

...επειδή η επόμενη θέση του δυναμικά ορισμένου πίνακα είναι η α[0]+1 και γενικά α[0]+i, επειδή όμως θέλουμε την διεύθυνση μνήμης του κάθε όρου χρησιμοποιούμε αυτή την πρόταση: *(α[0]+i).

 

Εδώ έχεις συντακτικά λάθη με την χρήση των τελεστών * και &. Φαντάσου ότι *="εκεί που δείχνει το..." ενώ &="η διεύθυνση του...". Άρα σωστό είναι έτσι *(&a[0]+i) και όχι *(α[0]+i). Φυσικά κανείς δεν το γράφει αυτό πρακτικά.

 

Αυτό όμως δεν το πολυκατάλαβα: p[ ((i*N)+j)*M+k ]

Φαντάσου τον πίνακα Α[3][3]:

 

1 2 3

4 5 6

7 8 9

 

τα στοιχεία του έχουν αριθμοδείκτες (indexes) στην C:

 

00 01 02

10 11 12

20 21 22

 

Αν ήταν μονοδιάστατος A[9]={1,2,3,4,5,6,7,8,9} οι αριθμοδείκτες του θα ήταν: 0 1 2 3 4 5 6 7 8.

Και τώρα αν σκεφτείς ότι ο αριθμοδείκτης είναι η "απόσταση" από το 1ο στοιχείο:

 

Να τι ισχύει για το στοιχείο της 3ης γραμμής 2ης στήλης το 8:

a[2*3+1]=a[7]=8. Το 2 είναι η γραμμή το 3 είναι το πλήθος στηλών το 1 είναι η στήλη και το 7 είναι ο αριθμοδείκτης στην μονοδιάστατη έκδοσή του.

Με αυτό τον τρόπο πιάνω ΜΟΝΟΔΙΑΣΤΑΤΑ όση μνήμη χρειάζομαι (με μια malloc) και μετά "παίζω" με όσες διαστάσεις θέλω.

 

Πάντως η όλη λογική με τους δείκτες είναι φανταστική, αυτοί που έφτιαξαν τη C κατάφεραν με 2 τελεστές και μια λιτή λογική να φτιάξουν κάτι το οποίο έχει θεωρητικά άπειρες δυνατότητες και είναι πολύ ευέλικτο και προσαρμόσιμο!

 

Μα τί περιμένεις;

Ξεκίνα το διάβασμα:

The C Programming Language, Second Edition

 

Φυσικά δεν είναι το μόνο που τα γράφει αυτά.

ΕΙΝΑΙ ΟΜΩΣ ΤΟ ΠΡΩΤΟ !

Δημοσ.

@chiossif

 

Το βιβλίο αυτό υπάρχει μεταγλωττισμένο στα Ελληνικά; Και αν ναι ο τίτλος είναι ο ίδιος;

 

Λοιπόν έγραψα το παρακάτω πρόγραμμα για δυναμική δέσμευση μνήμης, τον δικό σου τρόπο για δυναμική δέσμευση μνήμης κατάλαβα μεν τη λογική του, αλλά δεν κατάφερα να βρώ ένα λογικό τρόπο για να τον χειριστώ...

 

Anyway:

 

>
#include <stdio.h>
#include <stdlib.h>
#define N 10

int main ()
{


int i, j, meg;
int (*a)[N],M;

printf ("\n Dwse ton arithmo twn sthlwn tou pinaka: \n");
scanf ("%d",&M);

meg=N*M*sizeof(int *);

a=malloc(meg);

if (!a)
{
  printf("FAILURE!!! \n");
  return 1;
}

 for (i=0;i<N;i++) 
  for (j=0;j<M;j++)
    a[i][j]=i*j;

   
for (i=0;i<N;i++)
 for (j=0;j<M;j++)
   printf ("\n To i einai: %d  to j einai: %d kai to p[i][j] einai: %d \n",i,j,a[i][j]);

for (i=0;i<N;i++)
  free(a[i]);

free(a);

return 0;
}


 

Το error o Compiler (MiniGW Developer Studio, πάλι άλλαξα, αυτή τη φορά μετά απο παρότρυνση του parsifal...:)) μου το βγάζει στη 17η γραμμή,

 

a=malloc(meg);

 

Μπορεί κάποιος να μου πεί γιατί αυτό είναι λάθος;

 

Αυτόν τον τρόπο μας τον έχει δείξει ο καθηγητής στο ΤΕΙ και πάλι είναι λάθος!

Δημοσ.
@DiAvOl

 

Μια ερώτηση, σχετικά με το παρακάτω τμήμα κώδικα π έγραψες πιο πάνω:

 

>

tp = p;

for (i = 0; i < 10; i++)
*tp++ = i * i;

for (i = 0; i < 10; i++)
printf("p[%d] = %d\n", i, p[i]);

 

Epeidi ligo poio katw ston kwdika kanw free(p);

An anti gia *tp++ xrhsimopoiousa ton pointer *p++ den 8a mporousa na kanw free tin mnhmh me apotelesma na parousiastoun memory leaks

Δημοσ.
Είμαι αρχάριος και έχω μια απορία...

Θέλω να δεσμεύσω δυναμικά μνήμη ώστε να αποθηκεύσω αριθμούς(int). Κάθε φορά όταν θα αποθηκεύω ένα αριθμό, τότε θα δεσμεύω και την μνήμη. Επίσης θα πρέπει να μπορώ να προσπελάζω τους αριθμούς που έχω εισάγει. Προφανώς θα πρέπει να χρησιμοποιήσω την malloc, έτσι;

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

 

 

Ένας πολύ απλός τρόπος για να δεσμεύεις δυναμικά μνήμη είναι με την βοήθεια της ρουτίνας realloc η οποία επιτρέπει να αυξάνεις το μέγεθος του δεσμευμένου μπλοκ μνήμης δίχως απώλεια των ήδη καταχωρημένων σε αυτό στοιχείων (στην περίπτωση μας, τα δεδομένα του αριθμητικού πίνακα).

 

Το παρακάτω πρόγραμμα αυξάνει το μέγεθος του δυναμικού int πίνακα pnArray κατά ένα int (nArraySize++) δεσμεύοντας τον ανάλογο χώρο (realloc). Εάν η διαδικασία πετύχει (!=NULL) ζητά (scanf) από τον χειριστή να εισάγει έναν οιονδήποτε αριθμό αποθηκεύοντας τον στον πίνακα (&pnArray[nArraySize-1] –το -1 είναι απαραίτητο καθώς στην C μετράμε από το μηδέν, επίσης δεν μπορούμε απλά να ζητήσουμε (με το nArraySize*sizeof(int)) 0 bytes από την realloc!). Εάν ο αριθμός που δίδει ο χειριστής είναι το μηδέν (!pnArray[nArraySize-1]) τότε τον αποθηκεύουμε και διακόπτουμε τον βρόγχο εισαγωγής αριθμών (for). Ο βρόγχος for θα διακοπεί αυτόματα μόνο αν ο χειριστής εισάγει πάνω από MAXINT στοιχεία (αριθμούς) στον πίνακα. To ΜΑΧΙΝΤ παραδοσιακά ισούται με την τιμή 32,767 αλλά στους 32bit compilers μπορεί να είναι πολύ μεγαλύτερο! (πχ. 2,147,483,647). Αν δεν θέλουμε έναν τέτοιο έλεγχο ασφάλειας μπορούμε απλά να αφαιρέσουμε την συνθήκη "nArraySize<MAXINT".

 

Με την έξοδο μας από το βρόγχο for, το πρόγραμμα τυπώνει στην οθόνη (for(nArrayIdx=0..) μια λίστα με όλους τους εισαχθέντες στον πίνακα αριθμούς.

 

>
//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <values.h>

int main(int argc, char* argv[])
{
  int   *pnArray = 0, nArraySize , nArrayIdx;

  for(nArraySize=1;nArraySize<MAXINT;nArraySize++)
   {
     if((pnArray=realloc(pnArray,nArraySize*sizeof(int)))!=NULL)
      {
        printf(" Enter number to store or Zero to quit: ");
        scanf("%d",&pnArray[nArraySize-1]);

        if(!pnArray[nArraySize-1])
         break;
      }
     else
      {
        printf(" Not enough memory to store number!\n");
        return -1;
      }
   }

  for(nArrayIdx=0;nArrayIdx<nArraySize;nArrayIdx++)
   printf(" [%d] = %d\n",nArrayIdx,pnArray[nArrayIdx]);

  free(pnArray);

  return 0;
}

 

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

Δημοσ.

@Lomar:

 

Είσαι ένα κλικ πίσω:

σου έδωσα έναν σύνδεσμο [ http://cm.bell-labs.com/cm/cs/cbook/ ] για το βιβλίο The C Programming Language, Second Edition. Πήγες; Έριξες μια ματιά;

ΕΚΕΙ έχει, πέρα από τον τίτλο, τον εκδότη, το ISBN και το ελληνικό εξώφυλλο

(το οποίο δεν θα είναι και η πρώτη φορά που το βλέπεις).

 

Σχετικά με τον κώδικά σου: όπως ξαναέγραψα στο στάδιο που είσαι πρέπει να ΔΙΑΒΑΖΕΙΣ και όχι να γράφεις. Λοιπόν: το ότι σου βγάζει λάθος κάποιος compiler, κάπου εξασφαλίζει ότι ΥΠΑΡΧΕΙ ΛΑΘΟΣ αλλά όχι ποιό και που είναι.

 

Ενώ ορίζεις πίνακα δεικτών σε γραμμές, στην συνέχεια ζητάς ΜΟΝΟΜΙΑΣ όλη την μημη του πίνακα. ΑΥΤΟ ΔΕΝ ΕΙΝΑΙ ΛΑΘΟΣ αν όμως ξέρεις τι θέλεις να κάνεις.

 

Λοιπόν ξεκίνα το διάβασμα από τα παραδείγματα:

 

http://www.insomnia.gr/vb3/showpost.php?p=1380665&postcount=5

http://www.insomnia.gr/vb3/showpost.php?p=1407118&postcount=23

http://www.insomnia.gr/vb3/showpost.php?p=1411074&postcount=39

 

Να και μια παραλλαγή του #5 με δήλωση όπως αυτή που προσπάθησες (μικτή):

 

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

#define MAX_N 1024 /* Maximum number of rows */

int main (void) {
   int n, i, j;
   double i1, *a[MAX_N]; /* Array of pointers to each row */

   do {
       printf ("\nEnter matrix dimension N:(0,%d] : ",MAX_N);
       scanf ("%d",&n);
   }
   while(n<1||n>MAX_N);

   /* This part is NOT needed anymore, why? */
   /*
       if ((a=(double **)malloc(n*sizeof(double *)))==NULL){
           printf("\nNot enough memory available.\n");
           exit(1);
       }
   */

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

   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);
   }

   for (i=0;i<n;i++) {
       for (j=0;j<n;j++)
           printf(" %7.3lf", a[i][j]);
       printf("\n");
   }

   for(i=0;i<n;i++)
       free(a[i]);
   /* This is not needed anymore too */
   /*
       free(a);
   */
   return 0;
}

Σύγκρινέ το με το #5 και τα ξαναλέμε...

 

Ήμουν το πρωί λίγο υπερβολικός με την έκφραση μου: "...πρέπει να ΔΙΑΒΑΖΕΙΣ και όχι να γράφεις..." και την ανακαλώ. Φίλε Lomar πρόσεξε, ανακαλώ την έκφραση ΌΧΙ την προτροπή για ΔΙΑΒΑΣΜΑ.

Δημοσ.

@Directx

 

Πολύ ενδιαφέρον αυτό που αναφέρεις! Το έκανα τελικά με malloc, αν και νομίζω ότι η διαδικασία που περιγράφεις θα μου ήταν πιο χρήσιμη!

Ευχαριστώ πάντως!

Δημοσ.

@chiossif

 

Αυτό είναι το βιβλίο;

 

Έχω μπερδευτεί πάρα πολύ όμως, αλλιώς μου τα λένε στη σχολή αλλιώς είναι στη πραγματικότητα... :(

 

Τί εννοείς όταν λες οτι ζητάω μονομιάς όλη τι μνήμη του πίνακα; Ένας διαφορετικός τρόπος θα μπορούσε να ήταν αυτός;

 

>
for (i=0;i<n;i++)
for (j=0;j<m;j++)
 {
   p[i]=(int *)malloc(n*sizeof(int));
   if (p==NULL)
     return 1;
 }

 

Δεν ξέρω καν αν έκανα τη δεσμευση σωστα, τελικά είναι πολύ πολύπλοκο ζήτημα η δέσμευση μνήμης...

 

Σ'ευχαριστώ πάντως για την παρότρυνση, έχεις δίκιο θέλει πολύ διάβασμα και εξάσκηση αλλά το πρόβλημα είναι οτι είμαι πολύ μπερδεμένος με αυτά που βλέπω εδώ, στον compiler μου και στο ΤΕΙ...

 

 

EDIT:

 

@chiossif

 

Σε αυτό το πόστ σου, θέλω μια μικρή διευκρίνηση με την χρήση των array η οποία θα με βοηθήσει να κατανοήσω και τι εννοείς όταν λες οτι μονομιάς όλη τη μνήμη του πίνακα...

 

>
if ((a=(double **)malloc(n*sizeof(double *)))==NULL){
       printf("\nNot enough memory available.\n");
       exit(1);
   }

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

 

Γιατί στη πρώτη περίπτωση, όπου κάνεις έλεγχο για τη διαθεσιμότητα της μνήμης χρησιμοποιείς για τον τύπο δεδομένων 2* και 1* αντίστοιχα και στη δεύτερη περίπτωση, ένα και κανένα *. Αναφέρομαι σε αυτά: if ((a=(double **)malloc(n*sizeof(double *)))==NULL) και if ((a=(double **)malloc(n*sizeof(double *)))==NULL).

 

Καταλαβαίνω πως την πρώτη φορά γίνεται έλεγχος για το αν υπάρχει διαθέσιμη μνήμη για ολόκληρο τον πίνακα, και την δεύτερη φορά για το αν υπάρχει διαθέσιμη μνήμη για την κάθε στήλη στη κάθε γραμμή του πίνακα, (δλδ αν για Ν πλήθος κελιών τάδε τύπου υπάρχει χώρος και μετά αν για κάθε κελί απο αυτά υπάρχει χώρος για να καταχωρηθεί Μ πλήθος άλλων κελιών για κάθε κελί των Ν, του τάδε τύπου αντίστοιχα) εκεί που έχω μπερδευτεί είναι στη σύνταξη της εντολής...

 

Έτσι μου έρχεται να πάω να πιάσω τον καθηγητή και να του τα δείξω ΟΛΑ ΑΥΤΑ για να δω τι θα μου λέει μετα!

 

P.S. Και η βλακεία είναι οτι είναι καλός καθηγητής και πρόθυμος να εξηγήσει, αλλά όλα αυτά για τους δείκτες δε μας τα έχει πει έτσι (πολύ πιο απλοϊκά και όχι απλά εννοώ πως τα έχουμε διδαχθεί) και έτσι δε μπορούσα να του κάνω και τις ανάλογες απορίες...

 

2ο EDIT

 

Ακόμα δν κατάλαβα τι κάνουν τα 2*, και μέσα στις σημειώσεις του καθηγητή, δεν αναφέρει πουθενά (απ'όσο είδα)!!!

Μήπως μπορεί να μου το εξηγήσει κανείς αυτό; Δλδ τι ακριβώς κάνουν, και γιατί άλλοι δηλώνουν πίνακα με 1 * και άλλοι με 2 *; Είναι θέμα στυλ ή κάτι πιο ουσιαστικό;

 

Ευχαριστώ πολύ για την όποια βοήθεια μου έχετε προσφέρει μέχρι τώρα, και για την ανοχή σας...

 

BTW το βιβλίο, σωστό λάθος, μόλις το παρήγγειλα απο τον παπασωτηρίου...

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

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

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